rubyx/lib/vm/values.rb

146 lines
3.8 KiB
Ruby
Raw Normal View History

require_relative "code"
2014-06-14 09:59:25 +02:00
require_relative "register_reference"
2014-04-28 21:08:09 +02:00
module Vm
2014-05-02 07:02:25 +02:00
# Values represent the information as it is processed. Different subclasses for different types,
# each type with different operations.
# The oprerations on values is what makes a machine do things. Operations are captured as
# subclasses of Instruction and saved to Blocks
2014-05-02 07:02:25 +02:00
2014-05-03 14:13:44 +02:00
# Values are a way to reason about (create/validate) instructions.
2014-05-02 07:02:25 +02:00
# Word Values are what fits in a register. Derived classes
# Float, Reference , Integer(s) must fit the same registers
# just a base class for data. not sure how this will be usefull (may just have read too much llvm)
class Value
def class_for clazz
2014-05-21 18:43:46 +02:00
RegisterMachine.instance.class_for(clazz)
2014-05-10 09:59:56 +02:00
end
2014-05-02 07:02:25 +02:00
end
# Just a nice way to write branches
2014-06-14 10:12:53 +02:00
# Comparisons produce them, and branches take them as argument.
2014-05-22 20:38:57 +02:00
class BranchCondition < Value
2014-05-22 20:38:57 +02:00
def initialize operator
@operator = operator
end
attr_accessor :operator
#needed to check the opposite, ie not true
def not_operator
case @operator
when :le
:gt
when :gt
:le
when :lt
:ge
when :eq
:ne
2014-05-22 20:38:57 +02:00
else
raise "no implemented #{@operator}"
end
end
end
# This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base
# Must be promoted to A Word-Value to to anything makes is_a chaecking easier
# remembering that our oo machine is typed, no overloading or stuff
2014-05-02 07:02:25 +02:00
class Word < Value
2014-06-14 10:12:53 +02:00
attr_accessor :register
def register_symbol
2014-06-14 10:12:53 +02:00
@register.symbol
end
def inspect
"#{self.class.name} (#{register_symbol})"
2014-05-20 10:03:18 +02:00
end
def to_s
inspect
end
def initialize reg
2014-06-14 09:59:25 +02:00
if reg.is_a? RegisterReference
2014-06-14 10:12:53 +02:00
@register = reg
else
2014-06-14 10:12:53 +02:00
@register = RegisterReference.new(reg)
end
2014-05-05 08:35:40 +02:00
end
def length
4
end
2014-06-12 20:40:25 +02:00
# aka to string
def to_asm
"#{register_symbol}"
end
2014-04-28 21:08:09 +02:00
end
2014-05-02 07:02:25 +02:00
class Unsigned < Word
def plus block , unsigned
2014-05-21 18:43:46 +02:00
RegisterMachine.instance.unsigned_plus self , unsigned
2014-05-02 07:02:25 +02:00
end
end
class Integer < Word
2014-05-02 07:02:25 +02:00
def less_or_equal block , right
2014-06-14 10:12:53 +02:00
block.cmp( self , right )
Vm::BranchCondition.new :le
2014-05-06 20:36:28 +02:00
end
2014-05-28 19:10:16 +02:00
def greater_or_equal block , right
2014-06-14 10:12:53 +02:00
block.cmp( self , right )
Vm::BranchCondition.new :ge
2014-05-28 19:10:16 +02:00
end
2014-05-22 20:38:57 +02:00
def greater_than block , right
2014-06-14 10:12:53 +02:00
block.cmp( self , right )
Vm::BranchCondition.new :gt
2014-05-22 20:38:57 +02:00
end
def less_than block , right
2014-06-14 10:12:53 +02:00
block.cmp( self , right )
Vm::BranchCondition.new :lt
end
def at_index block , left , right
2014-06-14 10:12:53 +02:00
block.ldr( self , left , right )
self
end
def plus block , first , right
2014-06-14 10:12:53 +02:00
block.add( self , left , right )
self
end
2014-06-14 10:12:53 +02:00
def minus block , left , right
block.sub( self , left , right )
self
end
def left_shift block , first , right
2014-06-14 10:12:53 +02:00
block.mov( self , left , shift_lsr: right )
self
end
2014-06-07 22:22:32 +02:00
def equals block , right
2014-06-14 10:12:53 +02:00
block.cmp( self , right )
Vm::BranchCondition.new :eq
2014-06-07 22:22:32 +02:00
end
def load block , right
if(right.is_a? IntegerConstant)
block.mov( self , right ) #move the value
elsif right.is_a? StringConstant
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
2014-06-14 10:12:53 +02:00
block.mov( Integer.new(self.register.next_reg_use) , right.length ) #and the length HACK TODO
2014-06-13 22:51:53 +02:00
elsif right.is_a?(Boot::BootClass) or right.is_a?(Boot::MetaClass)
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
else
raise "unknown #{right.inspect}"
end
2014-05-21 20:15:23 +02:00
self
2014-05-03 14:13:44 +02:00
end
2014-05-14 11:02:54 +02:00
def move block , right
2014-05-21 20:15:23 +02:00
block.mov( self , right )
self
2014-05-14 11:02:54 +02:00
end
2014-05-02 07:02:25 +02:00
end
end
require_relative "constants"