diff --git a/docs/assembly.md b/docs/assembly.md index 2ac95ea..634f774 100644 --- a/docs/assembly.md +++ b/docs/assembly.md @@ -35,10 +35,3 @@ Currently only these three sections are supported: * `data` read-write data (non-executable) * `rodata` read-only data (non-executable) * `text` executable data (read-only) - - -## Allocating stack -another pseudo-op is recognized: `.stack `. This marks the executable as requesting at least `` bytes of stack. -If the loader respects this wish, the sp is initialized pointing to the end of the stack. - - \ No newline at end of file diff --git a/riscemu/CPU.py b/riscemu/CPU.py index 43990b1..e2fd594 100644 --- a/riscemu/CPU.py +++ b/riscemu/CPU.py @@ -85,9 +85,6 @@ class CPU: Run a loaded executable """ self.pc = le.run_ptr - sp, hp = le.stack_heap - self.regs.set('sp', sp) - self.regs.set('a0', hp) # set a0 to point to the heap print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(le.run_ptr, le.name) + FMT_NONE) self.__run() diff --git a/riscemu/Executable.py b/riscemu/Executable.py index 4a9969a..0237251 100644 --- a/riscemu/Executable.py +++ b/riscemu/Executable.py @@ -75,16 +75,14 @@ class Executable: run_ptr: Tuple[str, int] 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 = {}, globals={})".format( + return "{}(sections = {}, symbols = {}, run_ptr = {}, globals={})".format( self.__class__.__name__, " ".join(self.sections.keys()), " ".join(self.symbols.keys()), - self.stack_pref, self.run_ptr, ",".join(self.exported_symbols) ) @@ -257,7 +255,6 @@ class LoadedExecutable: sections: List[LoadedMemorySection] 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] @@ -284,20 +281,6 @@ class LoadedExecutable: self.sections_by_name[loaded_sec.name] = loaded_sec curr = align_addr(loaded_sec.size + curr) - # stack/heap if wanted - if exe.stack_pref is not None: - self.sections.append(LoadedMemorySection( - 'stack', - curr, - exe.stack_pref, - bytearray(exe.stack_pref), - MemoryFlags(read_only=False, executable=False), - self.name - )) - self.stack_heap = (curr, curr + exe.stack_pref) - else: - self.stack_heap = (0, 0) - for name, (sec_name, offset) in exe.symbols.items(): if sec_name == '_static_': self.symbols[name] = offset diff --git a/riscemu/ExecutableParser.py b/riscemu/ExecutableParser.py index 71433dc..a06e85f 100644 --- a/riscemu/ExecutableParser.py +++ b/riscemu/ExecutableParser.py @@ -28,7 +28,6 @@ class ExecutableParser: self.tokenizer = tokenizer self.active_section: Optional[str] = None self.implicit_sections = False - self.stack_pref: Optional[int] = None self.globals: List[str] = list() def parse(self) -> Executable: @@ -52,7 +51,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.globals, self.tokenizer.name) + return Executable(start_ptr, self.sections, self.symbols, self.globals, self.tokenizer.name) def parse_instruction(self, ins: 'RiscVInstructionToken') -> None: """ @@ -152,15 +151,6 @@ class ExecutableParser: str = op.args[0][1:-1].encode('ascii').decode('unicode_escape') self._curr_sec().add(bytearray(str + '\0', 'ascii')) - def op_stack(self, op: 'RiscVPseudoOpToken'): - """ - handles a .stack token. Sets the stack size preferences - :param op: The token - """ - ASSERT_LEN(op.args, 1) - size = parse_numeric_argument(op.args[0]) - self.stack_pref = size - def op_global(self, op: 'RiscVPseudoOpToken'): """ handles a .global token. Marks the token as global @@ -192,7 +182,6 @@ class ExecutableParser: val = parse_numeric_argument(op.args[0]) self._curr_sec().add(int_to_bytes(val, 4)) - ## Section handler code def _set_sec(self, name: str, flags: MemoryFlags, cls=MemorySection): if name not in self.sections: diff --git a/riscemu/MMU.py b/riscemu/MMU.py index c50509c..a63d3f0 100644 --- a/riscemu/MMU.py +++ b/riscemu/MMU.py @@ -5,7 +5,7 @@ SPDX-License-Identifier: BSD-2-Clause """ from .Config import RunConfig -from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction +from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags from .helpers import align_addr from .Exceptions import OutOfMemoryException from .colors import * @@ -48,38 +48,31 @@ class MMU: :param conf: The config to respect """ - self.sections = list() - self.binaries = list() - self.last_bin = None - self.conf = conf - self.global_symbols = dict() + self.sections: List[LoadedMemorySection] = list() + self.binaries: List[LoadedExecutable] = list() + self.first_free_addr: int = 0x100 + self.conf: RunConfig = conf + self.global_symbols: Dict[str, int] = dict() - def load_bin(self, bin: Executable) -> LoadedExecutable: + def load_bin(self, exe: Executable) -> LoadedExecutable: """ Load an executable into memory - :param bin: the executable to load + :param exe: the executable to load :return: A LoadedExecutable :raises OutOfMemoryException: When all memory is used """ - if self.last_bin is None: - addr = 0x100 # start at 0x100 instead of 0x00 - else: - addr = self.last_bin.size + self.last_bin.base_addr - # align to 8 byte word - addr = align_addr(addr) - # apply preferred stack size from config - if bin.stack_pref is None: - bin.stack_pref = self.conf.preffered_stack_size + # align to 8 byte word + addr = align_addr(self.first_free_addr) - loaded_bin = LoadedExecutable(bin, addr, self.global_symbols) + loaded_bin = LoadedExecutable(exe, addr, self.global_symbols) if loaded_bin.size + addr > self.max_size: raise OutOfMemoryException('load of executable') self.binaries.append(loaded_bin) - self.last_bin = loaded_bin + self.first_free_addr = loaded_bin.base_addr + loaded_bin.size # read sections into sec dict for sec in loaded_bin.sections: diff --git a/riscemu/Tokenizer.py b/riscemu/Tokenizer.py index 4911700..6bc57bd 100644 --- a/riscemu/Tokenizer.py +++ b/riscemu/Tokenizer.py @@ -15,7 +15,6 @@ PSEUDO_OPS = [ '.double', '.extern', '.global', - '.stack', '.align', '.float', '.kdata', diff --git a/riscemu/__main__.py b/riscemu/__main__.py index 444710c..1aa5966 100644 --- a/riscemu/__main__.py +++ b/riscemu/__main__.py @@ -15,6 +15,7 @@ if __name__ == '__main__': all_ins_names = list(InstructionSetDict.keys()) + class OptionStringAction(argparse.Action): def __init__(self, option_strings, dest, keys=None, omit_empty=False, **kwargs): if keys is None: @@ -57,8 +58,8 @@ if __name__ == '__main__': parser.add_argument('--syscall-opts', '-so', action=OptionStringAction, keys=('fs_access', 'disable_input')) - parser.add_argument('--instruction-sets', '-is', action=OptionStringAction, help="Instruction sets to load, available are: {}. " - "All are enabled by default" + parser.add_argument('--instruction-sets', '-is', action=OptionStringAction, + help="Instruction sets to load, available are: {}. All are enabled by default" .format(", ".join(all_ins_names)), keys={k: True for k in all_ins_names}, omit_empty=True) parser.add_argument('--default_stack_size', type=int, help='Default stack size of loaded programs', default=None, @@ -76,7 +77,6 @@ if __name__ == '__main__': scall_input=not args.syscall_opts['disable_input'] ) - if not hasattr(args, 'ins'): setattr(args, 'ins', {k: True for k in all_ins_names}) @@ -99,7 +99,6 @@ if __name__ == '__main__': except RiscemuBaseException as e: print("Error while parsing: {}".format(e.message())) import traceback + traceback.print_exception(type(e), e, e.__traceback__) sys.exit(1) - -