removed stack pref pseudo-op in preperation for real stack impl

float_support
Anton Lydike 4 years ago
parent a52506a17f
commit bc8c061c6d

@ -35,10 +35,3 @@ Currently only these three sections are supported:
* `data` read-write data (non-executable) * `data` read-write data (non-executable)
* `rodata` read-only data (non-executable) * `rodata` read-only data (non-executable)
* `text` executable data (read-only) * `text` executable data (read-only)
## Allocating stack
another pseudo-op is recognized: `.stack <len>`. This marks the executable as requesting at least `<len>` bytes of stack.
If the loader respects this wish, the sp is initialized pointing to the end of the stack.

@ -85,9 +85,6 @@ class CPU:
Run a loaded executable Run a loaded executable
""" """
self.pc = le.run_ptr 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) print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(le.run_ptr, le.name) + FMT_NONE)
self.__run() self.__run()

@ -75,16 +75,14 @@ class Executable:
run_ptr: Tuple[str, int] run_ptr: Tuple[str, int]
sections: Dict[str, MemorySection] sections: Dict[str, MemorySection]
symbols: Dict[str, Tuple[str, int]] symbols: Dict[str, Tuple[str, int]]
stack_pref: Optional[int]
exported_symbols: List[str] exported_symbols: List[str]
name: str name: str
def __repr__(self): def __repr__(self):
return "{}(sections = {}, symbols = {}, stack = {}, run_ptr = {}, globals={})".format( return "{}(sections = {}, symbols = {}, 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.run_ptr, self.run_ptr,
",".join(self.exported_symbols) ",".join(self.exported_symbols)
) )
@ -257,7 +255,6 @@ class LoadedExecutable:
sections: List[LoadedMemorySection] sections: List[LoadedMemorySection]
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
exported_symbols: Dict[str, int] exported_symbols: Dict[str, int]
global_symbol_table: Dict[str, int] global_symbol_table: Dict[str, int]
@ -284,20 +281,6 @@ class LoadedExecutable:
self.sections_by_name[loaded_sec.name] = loaded_sec self.sections_by_name[loaded_sec.name] = loaded_sec
curr = align_addr(loaded_sec.size + curr) 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(): for name, (sec_name, offset) in exe.symbols.items():
if sec_name == '_static_': if sec_name == '_static_':
self.symbols[name] = offset self.symbols[name] = offset

@ -28,7 +28,6 @@ class ExecutableParser:
self.tokenizer = tokenizer self.tokenizer = tokenizer
self.active_section: Optional[str] = None self.active_section: Optional[str] = None
self.implicit_sections = False self.implicit_sections = False
self.stack_pref: Optional[int] = None
self.globals: List[str] = list() self.globals: List[str] = list()
def parse(self) -> Executable: def parse(self) -> Executable:
@ -52,7 +51,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.globals, self.tokenizer.name) return Executable(start_ptr, self.sections, self.symbols, self.globals, self.tokenizer.name)
def parse_instruction(self, ins: 'RiscVInstructionToken') -> None: def parse_instruction(self, ins: 'RiscVInstructionToken') -> None:
""" """
@ -152,15 +151,6 @@ class ExecutableParser:
str = op.args[0][1:-1].encode('ascii').decode('unicode_escape') str = op.args[0][1:-1].encode('ascii').decode('unicode_escape')
self._curr_sec().add(bytearray(str + '\0', 'ascii')) 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'): def op_global(self, op: 'RiscVPseudoOpToken'):
""" """
handles a .global token. Marks the token as global handles a .global token. Marks the token as global
@ -192,7 +182,6 @@ class ExecutableParser:
val = parse_numeric_argument(op.args[0]) val = parse_numeric_argument(op.args[0])
self._curr_sec().add(int_to_bytes(val, 4)) self._curr_sec().add(int_to_bytes(val, 4))
## Section handler code ## Section handler code
def _set_sec(self, name: str, flags: MemoryFlags, cls=MemorySection): def _set_sec(self, name: str, flags: MemoryFlags, cls=MemorySection):
if name not in self.sections: if name not in self.sections:

@ -5,7 +5,7 @@ SPDX-License-Identifier: BSD-2-Clause
""" """
from .Config import RunConfig 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 .helpers import align_addr
from .Exceptions import OutOfMemoryException from .Exceptions import OutOfMemoryException
from .colors import * from .colors import *
@ -48,38 +48,31 @@ class MMU:
:param conf: The config to respect :param conf: The config to respect
""" """
self.sections = list() self.sections: List[LoadedMemorySection] = list()
self.binaries = list() self.binaries: List[LoadedExecutable] = list()
self.last_bin = None self.first_free_addr: int = 0x100
self.conf = conf self.conf: RunConfig = conf
self.global_symbols = dict() 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 Load an executable into memory
:param bin: the executable to load :param exe: the executable to load
:return: A LoadedExecutable :return: A LoadedExecutable
:raises OutOfMemoryException: When all memory is used :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 # align to 8 byte word
if bin.stack_pref is None: addr = align_addr(self.first_free_addr)
bin.stack_pref = self.conf.preffered_stack_size
loaded_bin = LoadedExecutable(bin, addr, self.global_symbols) loaded_bin = LoadedExecutable(exe, addr, self.global_symbols)
if loaded_bin.size + addr > self.max_size: if loaded_bin.size + addr > self.max_size:
raise OutOfMemoryException('load of executable') raise OutOfMemoryException('load of executable')
self.binaries.append(loaded_bin) 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 # read sections into sec dict
for sec in loaded_bin.sections: for sec in loaded_bin.sections:

@ -15,7 +15,6 @@ PSEUDO_OPS = [
'.double', '.double',
'.extern', '.extern',
'.global', '.global',
'.stack',
'.align', '.align',
'.float', '.float',
'.kdata', '.kdata',

@ -15,6 +15,7 @@ if __name__ == '__main__':
all_ins_names = list(InstructionSetDict.keys()) all_ins_names = list(InstructionSetDict.keys())
class OptionStringAction(argparse.Action): class OptionStringAction(argparse.Action):
def __init__(self, option_strings, dest, keys=None, omit_empty=False, **kwargs): def __init__(self, option_strings, dest, keys=None, omit_empty=False, **kwargs):
if keys is None: if keys is None:
@ -57,8 +58,8 @@ if __name__ == '__main__':
parser.add_argument('--syscall-opts', '-so', action=OptionStringAction, parser.add_argument('--syscall-opts', '-so', action=OptionStringAction,
keys=('fs_access', 'disable_input')) keys=('fs_access', 'disable_input'))
parser.add_argument('--instruction-sets', '-is', action=OptionStringAction, help="Instruction sets to load, available are: {}. " parser.add_argument('--instruction-sets', '-is', action=OptionStringAction,
"All are enabled by default" 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) .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, 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'] scall_input=not args.syscall_opts['disable_input']
) )
if not hasattr(args, 'ins'): if not hasattr(args, 'ins'):
setattr(args, 'ins', {k: True for k in all_ins_names}) setattr(args, 'ins', {k: True for k in all_ins_names})
@ -99,7 +99,6 @@ if __name__ == '__main__':
except RiscemuBaseException as e: except RiscemuBaseException as e:
print("Error while parsing: {}".format(e.message())) print("Error while parsing: {}".format(e.message()))
import traceback import traceback
traceback.print_exception(type(e), e, e.__traceback__) traceback.print_exception(type(e), e, e.__traceback__)
sys.exit(1) sys.exit(1)

Loading…
Cancel
Save