bit of cleaning, updated readme
This commit is contained in:
parent
c68577c3f4
commit
f658ecf425
@ -1,50 +1,48 @@
|
|||||||
Register Machine
|
Register Machine
|
||||||
===============
|
================
|
||||||
|
|
||||||
This is the logic that uses the compiled virtual object space to produce code and an executable binary.
|
The RegisterMachine, is an abstract machine with registers. Think of it as an arm machine with
|
||||||
|
normal instruction names. It is not however an abstraction of existing hardware, but only
|
||||||
|
of that subset that we need.
|
||||||
|
|
||||||
There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the
|
Our primary objective is to compile Phisol to this level, so the register machine has:
|
||||||
plain ones in this directory don't assemble to binary). Currently there is only the Arm module to actually do
|
- object access instructions
|
||||||
that.
|
- object load
|
||||||
|
- object oriented call semantics
|
||||||
|
- extended (and extensible) branching
|
||||||
|
- normal integer operators (but no sub word instructions)
|
||||||
|
|
||||||
The elf module is used to generate the actual binary from the final Space. Space is a virtual class representing
|
All data is in objects.
|
||||||
all objects that will be in the executable. Other than MethodSource, objects get transformed to data.
|
|
||||||
|
|
||||||
But MethodSource, which are made up of Blocks, are compiled into a stream of bytes,
|
The register machine is aware of Parfait objects, and specifically uses Message and Frame to
|
||||||
which are the binary code for the function.
|
express call semantics.
|
||||||
|
|
||||||
Virtual Objects
|
Calls and syscalls
|
||||||
----------------
|
------------------
|
||||||
|
|
||||||
There are four virtual objects that are accessible (we can access their variables):
|
The RegisterMachine only uses 1 fixed register, the currently worked on Message.
|
||||||
|
|
||||||
- Self
|
There is no stack, rather messages form a linked list, and preparing to call, the data is pre-filled
|
||||||
- Message (arguments, method name, self)
|
into the next message. Calling then means moving the new message to the current one and jumping
|
||||||
- Frame (local and tmp variables)
|
to the address of the method. Returning is the somewhat reverse process.
|
||||||
- NewMessage ( to build the next message sent)
|
|
||||||
|
|
||||||
These are pretty much the first four registers. When the code goes from virtual to register,
|
Syscalls are implemented by *one* Syscall instruction. The Register machine does not specify/limit
|
||||||
we use register instructions to replace virtual ones.
|
the meaning or number of syscalls. This is implemented by the level below, eg the arm/interpreter.
|
||||||
|
|
||||||
Eg: A Virtual::Set can move data around inside those objects.
|
Interpreter
|
||||||
And since in Arm this can not be done in one instruction, we use two, one to move to an unused register
|
===========
|
||||||
and then into the destination. And then we need some fiddling of bits to shift the type info.
|
|
||||||
|
|
||||||
Another simple example is a Call. A simple case of a Class function call resolves the class object,
|
There is an interpreter that can interpret compiled register machine programs.
|
||||||
and with the method name the function to be found at compile-time.
|
This is very handy for debugging (an nothing else).
|
||||||
And so this results in a Register::Call, which is an Arm instruction.
|
|
||||||
|
|
||||||
A C call
|
Even more handy is the graphical interface for the interpreter, which is in it's own repository:
|
||||||
---------
|
salama-debugger.
|
||||||
|
|
||||||
Ok, there are no c calls. But syscalls are very similar.
|
Arm / Elf
|
||||||
This is not at all as simple as the nice Class call described above.
|
=========
|
||||||
|
|
||||||
For syscall in Arm (linux) you have to load registers 0-x (depending on call), load R7 with the
|
There is also a (very strightforward) transformation to arm instructions.
|
||||||
syscall number and then issue the software interupt instruction.
|
Together with the also quite minimal elf module, arm binaries can be produced.
|
||||||
If you get back something back, it's in R0.
|
|
||||||
|
|
||||||
In short, lots of shuffling. And to make it fit with our four object architecture,
|
These binaries have no external dependencies and in fact can not even call c at the moment
|
||||||
we need the Message to hold the data for the call and Sys (module) to be self.
|
(only syscalls :-)).
|
||||||
And then the actual functions do the shuffle, saving the data and restoring it.
|
|
||||||
And setting type information according to kernel documentation (as there is no runtime info)
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
module Register
|
|
||||||
class UnusedAndAbandonedInteger < Word
|
|
||||||
# needs to be here as Word's constructor is private (to make it abstract)
|
|
||||||
def initialize reg
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def less_or_equal block , right
|
|
||||||
block.cmp( self , right )
|
|
||||||
Register::BranchCondition.new :le
|
|
||||||
end
|
|
||||||
def greater_or_equal block , right
|
|
||||||
block.cmp( self , right )
|
|
||||||
Register::BranchCondition.new :ge
|
|
||||||
end
|
|
||||||
def greater_than block , right
|
|
||||||
block.cmp( self , right )
|
|
||||||
Register::BranchCondition.new :gt
|
|
||||||
end
|
|
||||||
def less_than block , right
|
|
||||||
block.cmp( self , right )
|
|
||||||
Register::BranchCondition.new :lt
|
|
||||||
end
|
|
||||||
def plus block , first , right
|
|
||||||
block.add( self , left , right )
|
|
||||||
self
|
|
||||||
end
|
|
||||||
def minus block , left , right
|
|
||||||
block.sub( self , left , right )
|
|
||||||
self
|
|
||||||
end
|
|
||||||
def left_shift block , left , right
|
|
||||||
block.mov( self , left , shift_lsr: right )
|
|
||||||
self
|
|
||||||
end
|
|
||||||
def equals block , right
|
|
||||||
block.cmp( self , right )
|
|
||||||
Register::BranchCondition.new :eq
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_true? function
|
|
||||||
function.cmp( self , 0 )
|
|
||||||
Register::BranchCondition.new :ne
|
|
||||||
end
|
|
||||||
|
|
||||||
def move block , right
|
|
||||||
block.mov( self , right )
|
|
||||||
self
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,3 +0,0 @@
|
|||||||
module Register
|
|
||||||
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user