getting a _start and _exit, just missing the actual code

This commit is contained in:
Torsten Ruger
2014-05-06 00:12:04 +03:00
parent 7d20b5e2df
commit 22b5117c8b
12 changed files with 43 additions and 105 deletions

View File

@ -40,14 +40,15 @@ module Arm
end
def main_entry
mov( :left => :fp , :right => 0 )
entry = Vm::Block.new("main_entry")
entry.add_code mov( :left => :fp , :right => 0 )
end
def main_exit
syscall(0)
entry = Vm::Block.new("main_exit")
entry.add_code syscall(0)
end
def syscall num
mov( :left => 7 , :right => num )
swi( :left => 0 )
[mov( :left => :r7 , :right => num ) , swi( :left => 0 )]
end
end
end

View File

@ -1,5 +1,5 @@
require 'arm/nodes'
require 'arm/block'
require 'vm/block'
require 'stream_reader'
require 'stringio'
require "arm/string_literal"
@ -43,7 +43,7 @@ module Arm
def add_string str
code = @string_table[str]
return code if code
data = Arm::StringLiteral.new(str)
data = Vm::StringLiteral.new(str)
@string_table[str] = data
end

View File

@ -1,83 +0,0 @@
require_relative 'call_instruction'
require_relative 'stack_instruction'
require_relative 'logic_instruction'
require_relative 'memory_instruction'
module Arm
class Code ; end
# A Block is the smalles unit of code, a list of instructions as it were
# It is also a point to jump/branch to. An address in the final stream.
# To allow for forward branches creation does not fix the position.
# Thee position is fixed in one of three ways
# - create the block with ruby block, signalling that the instantiation poin is the position
# - call block.code with the code or if you wish program.add_block (and add you code with calls)
# - the assmebly process will pin it if it wasn't set
# creating blocks is done by calling the blocks name/label on either a program or a block
# (method missing will cathc the call and create the block)
# and the easiest way is to go into a ruby block and start writing instructions
# Example (backward jump):
# program.loop do create a new block with label loop
# sub r1 , r1 , 1 count the r1 register down
# bne :loop jump back to loop when the counter is not zero
# end (initialization and actual code missing off course)
# Example (forward jump)
# else_block = program.else
# program.if do
# test r1 , 0 test some condition
# beq :else_block
# mov . . .. .. do whatever the if block does
# end
# else_block.code do
# ldr .... do whatever else does
# end
# Blocks are also used to create instructions, and so Block has functions for every cpu instruction
# and to make using the apu function easier, there are functions that create registers as well
class Block < Code
def initialize(name , prog)
super()
@name = name.to_sym
@codes = []
@position = 0
@program = prog
end
attr_reader :name
# length of the codes. In arm it would be the length * 4
# (strings are stored globally in the Assembler)
def length
@codes.inject(0) {| sum , item | sum + item.length}
end
def add_code(kode)
kode.at(@position)
length = kode.length
@position += length
@codes << kode
end
def assemble(io)
@codes.each do |obj|
obj.assemble io
end
end
# this is used to create blocks.
# All functions that have no args are interpreted as block names
# In fact the block calls are delegated to the program which then instantiates the blocks
def method_missing(meth, *args, &block)
if args.length == 0
@program.send(meth , *args , &block)
else
super
end
end
end
end

View File

@ -35,6 +35,7 @@ module Arm
case @opcode
when :b, :bl
arg = @args[0]
#puts "BLAB #{arg.inspect}"
if( arg.is_a? Fixnum ) #HACK to not have to change the code just now
arg = Arm::NumLiteral.new( arg )
end

View File

@ -17,7 +17,7 @@ module Arm
#(stays in subclases, while build is overriden to provide different arguments)
def do_build(arg)
if arg.is_a?(Arm::StringLiteral)
if arg.is_a?(Vm::StringLiteral)
# do pc relative addressing with the difference to the instuction
# 8 is for the funny pipeline adjustment (ie oc pointing to fetch and not execute)
arg = Arm::NumLiteral.new( arg.position - self.position - 8 )
@ -71,6 +71,7 @@ module Arm
def assemble(io)
build
instuction_class = 0b00 # OPC_DATA_PROCESSING
puts inspect
val = @operand.is_a?(Symbol) ? reg_code(@operand) : @operand
val |= (reg_code(@rd) << 12)
val |= (reg_code(@rn) << 12+4)

View File

@ -1,30 +0,0 @@
require "vm/code"
module Arm
# The name really says it all.
# The only interesting thing is storage.
# Currently string are stored "inline" , ie in the code segment.
# Mainly because that works an i aint no elf expert.
class StringLiteral < Vm::Code
# currently aligned to 4 (ie padded with 0) and off course 0 at the end
def initialize(str)
length = str.length
# rounding up to the next 4 (always adding one for zero pad)
pad = ((length / 4 ) + 1 ) * 4 - length
raise "#{pad} #{self}" unless pad >= 1
@string = str + "\x00" * pad
end
# the strings length plus padding
def length
@string.length
end
# just writing the string
def assemble(io)
io << @string
end
end
end