added global symbol support!

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

@ -4,6 +4,7 @@ fibs: .space 56
.text .text
main: main:
func_fibs:
addi s1, zero, 0 # storage index addi s1, zero, 0 # storage index
addi s2, zero, 56 # last storage index addi s2, zero, 56 # last storage index
addi t0, zero, 1 # t0 = F_{i} addi t0, zero, 1 # t0 = F_{i}
@ -20,3 +21,8 @@ loop:
addi a7, zero, 93 addi a7, zero, 93
ebreak # launch debugger ebreak # launch debugger
scall # exit with code 0 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)) 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 # MMU Exceptions
class MemoryAccessException(RiscemuBaseException): class MemoryAccessException(RiscemuBaseException):
@ -64,7 +72,7 @@ class MemoryAccessException(RiscemuBaseException):
) + FMT_NONE ) + FMT_NONE
class OutOfMemoryEsception(RiscemuBaseException): class OutOfMemoryException(RiscemuBaseException):
def __init__(self, action): def __init__(self, action):
self.action = action self.action = action

@ -66,15 +66,17 @@ class Executable:
sections: Dict[str, MemorySection] sections: Dict[str, MemorySection]
symbols: Dict[str, Tuple[str, int]] symbols: Dict[str, Tuple[str, int]]
stack_pref: Optional[int] stack_pref: Optional[int]
exported_symbols: List[str]
name: str name: str
def __repr__(self): def __repr__(self):
return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {})".format( return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {}, globals={})".format(
self.__class__.__name__, self.__class__.__name__,
" ".join(self.sections.keys()), " ".join(self.sections.keys()),
" ".join(self.symbols.keys()), " ".join(self.symbols.keys()),
self.stack_pref, 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)) raise ParseException("Instruction {} expected argument at {} (args: {})".format(self.name, num, self.args))
arg = self.args[num] arg = self.args[num]
# look up symbols # look up symbols
if arg in self.bin.symbols: if self.bin.has_symb(arg):
return self.bin.symbols[arg] return self.bin.lookup_symbol(arg)
return parse_numeric_argument(arg) return parse_numeric_argument(arg)
def get_imm_reg(self, num: int): def get_imm_reg(self, num: int):
@ -111,8 +113,8 @@ class LoadedInstruction:
arg = self.args[num] arg = self.args[num]
ASSERT_IN("(", arg) ASSERT_IN("(", arg)
imm, reg = arg[:-1].split("(") imm, reg = arg[:-1].split("(")
if imm in self.bin.symbols: if self.bin.has_symb(imm):
return self.bin.symbols[imm], reg return self.bin.lookup_symbol(imm), reg
return parse_numeric_argument(imm), reg return parse_numeric_argument(imm), reg
def get_reg(self, num: int): def get_reg(self, num: int):
@ -244,13 +246,17 @@ class LoadedExecutable:
symbols: Dict[str, int] symbols: Dict[str, int]
run_ptr: int run_ptr: int
stack_heap: Tuple[int, int] # pointers to stack and heap, are nullptr if no stack/heap is available 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.name = exe.name
self.base_addr = base_addr self.base_addr = base_addr
self.sections = list() self.sections = list()
self.sections_by_name = dict() self.sections_by_name = dict()
self.symbols = dict() self.symbols = dict()
self.exported_symbols = dict()
self.global_symbol_table = dict()
# stack/heap if wanted # stack/heap if wanted
if exe.stack_pref is not None: if exe.stack_pref is not None:
@ -281,15 +287,29 @@ class LoadedExecutable:
curr = align_addr(loaded_sec.size + curr) curr = align_addr(loaded_sec.size + curr)
for name, (sec_name, offset) in exe.symbols.items(): 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) ASSERT_IN(sec_name, self.sections_by_name)
self.symbols[name] = self.sections_by_name[sec_name].base + offset 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 self.size = curr - base_addr
# translate run_ptr from executable # translate run_ptr from executable
run_ptr_sec, run_ptr_off = exe.run_ptr run_ptr_sec, run_ptr_off = exe.run_ptr
self.run_ptr = self.sections_by_name[run_ptr_sec].base + run_ptr_off 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): def __repr__(self):
return '{}[{}](base=0x{:08X}, size={}bytes, sections={}, run_ptr=0x{:08X})'.format( return '{}[{}](base=0x{:08X}, size={}bytes, sections={}, run_ptr=0x{:08X})'.format(
self.__class__.__name__, self.__class__.__name__,
@ -299,3 +319,6 @@ class LoadedExecutable:
" ".join(self.sections_by_name.keys()), " ".join(self.sections_by_name.keys()),
self.run_ptr 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'] start_ptr = self.symbols['_start']
elif 'main' in self.symbols: elif 'main' in self.symbols:
start_ptr = self.symbols['main'] 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'): def parse_instruction(self, ins: 'RiscVInstructionToken'):
if self.active_section is None: if self.active_section is None:
@ -103,7 +103,7 @@ class ExecutableParser:
def op_global(self, op: 'RiscVPseudoOpToken'): def op_global(self, op: 'RiscVPseudoOpToken'):
ASSERT_LEN(op.args, 1) ASSERT_LEN(op.args, 1)
name = op.args[1] name = op.args[0]
self.globals.append(name) self.globals.append(name)
def op_set(self, op: 'RiscVPseudoOpToken'): def op_set(self, op: 'RiscVPseudoOpToken'):

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

@ -23,7 +23,7 @@ PSEUDO_OPS = [
'.data', '.data',
'.half', '.half',
'.text', '.text',
'.word' '.word',
'.set', '.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, \ from .Tokenizer import RiscVToken, RiscVInput, RiscVTokenizer, RiscVInstructionToken, RiscVSymbolToken, \
RiscVPseudoOpToken, TokenType RiscVPseudoOpToken, TokenType

@ -2,6 +2,7 @@ if __name__ == '__main__':
from . import * from . import *
from .helpers import * from .helpers import *
import argparse import argparse
import sys
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu') 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') 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_NONE = ""
FMT_PRINT = "" FMT_PRINT = ""
try:
tk = RiscVTokenizer(RiscVInput.from_file(args.file)) tk = RiscVTokenizer(RiscVInput.from_file(args.file))
tk.tokenize() tk.tokenize()
@ -42,6 +44,11 @@ if __name__ == '__main__':
print(token) print(token)
executable = ExecutableParser(tk).parse() 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) cpu = CPU(cfg)
le = cpu.load(executable) le = cpu.load(executable)

Loading…
Cancel
Save