added global symbol support!

float_support
Anton Lydike 4 years ago
parent 9aaaf7313f
commit 8fc519ee86

@ -4,6 +4,7 @@ fibs: .space 56
.text
main:
func_fibs:
addi s1, zero, 0 # storage index
addi s2, zero, 56 # last storage index
addi t0, zero, 1 # t0 = F_{i}
@ -20,3 +21,8 @@ loop:
addi a7, zero, 93
ebreak # launch debugger
scall # exit with code 0
.set test_val, 0xFF
.global func_fibs

@ -44,6 +44,14 @@ def ASSERT_IN(a1, a2):
raise ParseException("ASSERTION_FAILED: Expected {} to not be in {}".format(a1, a2), (a1, a2))
class LinkerException(RiscemuBaseException):
def __init__(self, msg, data):
self.msg = msg
self.data = data
def message(self):
return FMT_PARSE + "{}(\"{}\", data={})".format(self.__class__.__name__, self.msg, self.data) + FMT_NONE
# MMU Exceptions
class MemoryAccessException(RiscemuBaseException):
@ -64,7 +72,7 @@ class MemoryAccessException(RiscemuBaseException):
) + FMT_NONE
class OutOfMemoryEsception(RiscemuBaseException):
class OutOfMemoryException(RiscemuBaseException):
def __init__(self, action):
self.action = action

@ -66,15 +66,17 @@ class Executable:
sections: Dict[str, MemorySection]
symbols: Dict[str, Tuple[str, int]]
stack_pref: Optional[int]
exported_symbols: List[str]
name: str
def __repr__(self):
return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {})".format(
return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {}, globals={})".format(
self.__class__.__name__,
" ".join(self.sections.keys()),
" ".join(self.symbols.keys()),
self.stack_pref,
self.run_ptr
self.run_ptr,
",".join(self.exported_symbols)
)
@ -98,8 +100,8 @@ class LoadedInstruction:
raise ParseException("Instruction {} expected argument at {} (args: {})".format(self.name, num, self.args))
arg = self.args[num]
# look up symbols
if arg in self.bin.symbols:
return self.bin.symbols[arg]
if self.bin.has_symb(arg):
return self.bin.lookup_symbol(arg)
return parse_numeric_argument(arg)
def get_imm_reg(self, num: int):
@ -111,8 +113,8 @@ class LoadedInstruction:
arg = self.args[num]
ASSERT_IN("(", arg)
imm, reg = arg[:-1].split("(")
if imm in self.bin.symbols:
return self.bin.symbols[imm], reg
if self.bin.has_symb(imm):
return self.bin.lookup_symbol(imm), reg
return parse_numeric_argument(imm), reg
def get_reg(self, num: int):
@ -244,13 +246,17 @@ class LoadedExecutable:
symbols: Dict[str, int]
run_ptr: int
stack_heap: Tuple[int, int] # pointers to stack and heap, are nullptr if no stack/heap is available
exported_symbols: Dict[str, int]
global_symbol_table: Dict[str, int]
def __init__(self, exe: Executable, base_addr: int):
def __init__(self, exe: Executable, base_addr: int, global_symbol_table: Dict[str, int]):
self.name = exe.name
self.base_addr = base_addr
self.sections = list()
self.sections_by_name = dict()
self.symbols = dict()
self.exported_symbols = dict()
self.global_symbol_table = dict()
# stack/heap if wanted
if exe.stack_pref is not None:
@ -281,15 +287,29 @@ class LoadedExecutable:
curr = align_addr(loaded_sec.size + curr)
for name, (sec_name, offset) in exe.symbols.items():
if sec_name == '_static_':
self.symbols[name] = offset
else:
ASSERT_IN(sec_name, self.sections_by_name)
self.symbols[name] = self.sections_by_name[sec_name].base + offset
for name in exe.exported_symbols:
self.exported_symbols[name] = self.symbols[name]
self.size = curr - base_addr
# translate run_ptr from executable
run_ptr_sec, run_ptr_off = exe.run_ptr
self.run_ptr = self.sections_by_name[run_ptr_sec].base + run_ptr_off
def lookup_symbol(self, name):
if name in self.symbols:
return self.symbols[name]
if name in self.global_symbol_table:
return self.global_symbol_table[name]
raise LinkerException('Symbol {} not found!'.format(name), (self,))
def __repr__(self):
return '{}[{}](base=0x{:08X}, size={}bytes, sections={}, run_ptr=0x{:08X})'.format(
self.__class__.__name__,
@ -299,3 +319,6 @@ class LoadedExecutable:
" ".join(self.sections_by_name.keys()),
self.run_ptr
)
def has_symb(self, arg):
return arg in self.symbols or arg in self.global_symbol_table

@ -36,7 +36,7 @@ class ExecutableParser:
start_ptr = self.symbols['_start']
elif 'main' in self.symbols:
start_ptr = self.symbols['main']
return Executable(start_ptr, self.sections, self.symbols, self.stack_pref, self.tokenizer.name)
return Executable(start_ptr, self.sections, self.symbols, self.stack_pref, self.globals, self.tokenizer.name)
def parse_instruction(self, ins: 'RiscVInstructionToken'):
if self.active_section is None:
@ -103,7 +103,7 @@ class ExecutableParser:
def op_global(self, op: 'RiscVPseudoOpToken'):
ASSERT_LEN(op.args, 1)
name = op.args[1]
name = op.args[0]
self.globals.append(name)
def op_set(self, op: 'RiscVPseudoOpToken'):

@ -1,7 +1,7 @@
from .Config import RunConfig
from .Executable import Executable, LoadedExecutable, LoadedMemorySection
from .helpers import align_addr
from .Exceptions import OutOfMemoryEsception
from .Exceptions import OutOfMemoryException
from typing import Dict, List, Tuple, Optional
@ -20,6 +20,7 @@ class MMU:
self.binaries = list()
self.last_bin = None
self.conf = conf
self.global_symbols = dict()
def load_bin(self, bin: Executable):
if self.last_bin is None:
@ -33,10 +34,10 @@ class MMU:
if bin.stack_pref is None:
bin.stack_pref = self.conf.preffered_stack_size
loaded_bin = LoadedExecutable(bin, addr)
loaded_bin = LoadedExecutable(bin, addr, self.global_symbols)
if loaded_bin.size + addr > self.max_size:
raise OutOfMemoryEsception('load of executable')
raise OutOfMemoryException('load of executable')
self.binaries.append(loaded_bin)
self.last_bin = loaded_bin
@ -45,6 +46,8 @@ class MMU:
for sec in loaded_bin.sections:
self.sections.append(sec)
self.global_symbols.update(loaded_bin.exported_symbols)
print("Successfully loaded {}".format(loaded_bin))
return loaded_bin

@ -23,7 +23,7 @@ PSEUDO_OPS = [
'.data',
'.half',
'.text',
'.word'
'.word',
'.set',
]

@ -1,4 +1,4 @@
from .Exceptions import ASSERT_NOT_NULL, ASSERT_LEN, ASSERT_IN, ASSERT_EQ, ASSERT_NOT_IN
from .Exceptions import *
from .Tokenizer import RiscVToken, RiscVInput, RiscVTokenizer, RiscVInstructionToken, RiscVSymbolToken, \
RiscVPseudoOpToken, TokenType

@ -2,6 +2,7 @@ if __name__ == '__main__':
from . import *
from .helpers import *
import argparse
import sys
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu')
parser.add_argument('file', metavar='file.asm', type=str, help='The assembly file to interpret and run')
@ -33,6 +34,7 @@ if __name__ == '__main__':
FMT_NONE = ""
FMT_PRINT = ""
try:
tk = RiscVTokenizer(RiscVInput.from_file(args.file))
tk.tokenize()
@ -42,6 +44,11 @@ if __name__ == '__main__':
print(token)
executable = ExecutableParser(tk).parse()
except RiscemuBaseException as e:
print("Error while parsing: {}".format(e.message()))
import traceback
traceback.print_exception(type(e), e, e.__traceback__)
sys.exit(1)
cpu = CPU(cfg)
le = cpu.load(executable)

Loading…
Cancel
Save