2018-03-18 06:06:01 +01:00
|
|
|
require "common/list"
|
2014-05-03 14:13:44 +02:00
|
|
|
|
2018-03-18 06:06:01 +01:00
|
|
|
module Risc
|
2015-10-23 20:27:36 +02:00
|
|
|
|
2018-03-18 06:06:01 +01:00
|
|
|
# the register machine has at least 8 registers, named r0-r5 , :lr and :pc
|
|
|
|
# (for historical reasons , r for register, pc for ProgramCounter ie next instruction address
|
|
|
|
# and lr means LinkRegister, ie the location where to return to when in a function)
|
|
|
|
#
|
|
|
|
# We can load and store their contents, move data between them and
|
|
|
|
# access (get/set) memory at a constant offset from a register
|
|
|
|
# While Mom works with objects, the register machine has registers,
|
|
|
|
# but we keep the names for better understanding, r2-5 are temporary/scratch
|
|
|
|
# There is no direct memory access, only through registers
|
|
|
|
# Constants can/must be loaded into registers before use
|
|
|
|
|
|
|
|
# At compile time, Instructions form a linked list (:next attribute is the link)
|
|
|
|
# At run time Instructions are traversesed as a graph
|
|
|
|
#
|
2015-10-23 20:27:36 +02:00
|
|
|
# Branches fan out, Labels collect
|
|
|
|
# Labels are the only valid branch targets
|
2018-03-18 06:06:01 +01:00
|
|
|
#
|
2014-10-03 09:25:10 +02:00
|
|
|
class Instruction
|
2018-03-18 06:06:01 +01:00
|
|
|
include Common::List
|
2014-10-03 09:25:10 +02:00
|
|
|
|
2015-10-23 20:27:36 +02:00
|
|
|
def initialize source , nekst = nil
|
2015-10-28 20:38:23 +01:00
|
|
|
@source = source
|
|
|
|
@next = nekst
|
|
|
|
return unless source
|
2018-03-22 17:38:19 +01:00
|
|
|
raise "Source must be string or Instruction, not #{source.class}" unless source.is_a?(String) or source.is_a?(Mom::Instruction)
|
2015-07-18 10:21:49 +02:00
|
|
|
end
|
2015-07-27 11:13:39 +02:00
|
|
|
attr_reader :source
|
2015-07-18 10:21:49 +02:00
|
|
|
|
2018-03-26 13:54:41 +02:00
|
|
|
def to_arr
|
|
|
|
ret = []
|
|
|
|
self.each {|ins| ret << ins}
|
2015-10-23 20:27:36 +02:00
|
|
|
ret
|
2014-06-08 00:41:56 +02:00
|
|
|
end
|
2015-10-23 20:27:36 +02:00
|
|
|
|
2015-10-24 16:12:36 +02:00
|
|
|
# derived classes must provide a byte_length
|
|
|
|
def byte_length
|
|
|
|
raise "Abstract called on #{self}"
|
|
|
|
end
|
|
|
|
|
2018-03-25 18:38:59 +02:00
|
|
|
def to_cpu( translator )
|
|
|
|
translator.translate( self )
|
|
|
|
end
|
|
|
|
|
2018-03-26 13:54:41 +02:00
|
|
|
def assemble_all( io )
|
2015-10-25 09:54:19 +01:00
|
|
|
self.assemble(io)
|
2018-03-26 13:54:41 +02:00
|
|
|
self.next.assemble_all(io) if self.next
|
2015-10-25 09:54:19 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def assemble io
|
|
|
|
raise "Abstract called on #{self}"
|
|
|
|
end
|
|
|
|
|
2018-03-26 13:54:41 +02:00
|
|
|
def total_byte_length
|
|
|
|
ret = 0
|
|
|
|
self.each{|ins| ret += ins.byte_length}
|
2015-10-24 16:12:36 +02:00
|
|
|
ret
|
|
|
|
end
|
|
|
|
|
2018-03-26 13:54:41 +02:00
|
|
|
def set_position( position )
|
2017-01-01 20:52:35 +01:00
|
|
|
Positioned.set_position(self,position)
|
2015-10-24 16:12:36 +02:00
|
|
|
position += byte_length
|
|
|
|
if self.next
|
2018-03-26 13:54:41 +02:00
|
|
|
self.next.set_position( position )
|
2015-10-24 16:12:36 +02:00
|
|
|
else
|
|
|
|
position
|
|
|
|
end
|
|
|
|
end
|
2015-10-25 11:03:31 +01:00
|
|
|
|
2018-03-22 17:38:19 +01:00
|
|
|
def class_source( derived)
|
|
|
|
"#{self.class.name.split("::").last}: #{derived} #{source_mini}"
|
|
|
|
end
|
|
|
|
def source_mini
|
|
|
|
return "(no source)" unless source
|
2018-03-23 17:55:23 +01:00
|
|
|
return "(from: #{source[0..25]})" if source.is_a?(String)
|
2018-03-22 17:38:19 +01:00
|
|
|
"(from: #{source.class.name.split("::").last})"
|
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
2015-05-24 19:00:11 +02:00
|
|
|
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
2014-10-03 10:05:17 +02:00
|
|
|
|
2016-12-11 13:06:09 +01:00
|
|
|
require_relative "instructions/setter"
|
2016-12-11 13:12:35 +01:00
|
|
|
require_relative "instructions/getter"
|
2016-12-25 17:02:39 +01:00
|
|
|
require_relative "instructions/reg_to_slot"
|
2016-12-25 17:05:39 +01:00
|
|
|
require_relative "instructions/slot_to_reg"
|
2016-12-25 17:11:58 +01:00
|
|
|
require_relative "instructions/reg_to_byte"
|
|
|
|
require_relative "instructions/byte_to_reg"
|
2014-10-03 10:07:18 +02:00
|
|
|
require_relative "instructions/load_constant"
|
2015-06-22 21:48:42 +02:00
|
|
|
require_relative "instructions/syscall"
|
2014-10-04 11:52:47 +02:00
|
|
|
require_relative "instructions/function_call"
|
|
|
|
require_relative "instructions/function_return"
|
2018-03-21 11:32:46 +01:00
|
|
|
require_relative "instructions/transfer"
|
2015-10-23 20:27:36 +02:00
|
|
|
require_relative "instructions/label"
|
2015-07-17 12:21:57 +02:00
|
|
|
require_relative "instructions/branch"
|
2015-08-04 21:01:20 +02:00
|
|
|
require_relative "instructions/operator_instruction"
|