more work on syscalls
parent
a69cc7d346
commit
a483db65c7
@ -0,0 +1,48 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from .Registers import Registers
|
||||||
|
from .Exceptions import InvalidSyscallException
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from . import CPU
|
||||||
|
|
||||||
|
SYSCALLS = {
|
||||||
|
63: 'read',
|
||||||
|
64: 'write',
|
||||||
|
93: 'exit'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Syscall:
|
||||||
|
id: int
|
||||||
|
registers: Registers
|
||||||
|
cpu: 'CPU'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return SYSCALLS.get(self.id, "unknown")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Syscall(id={}, name={})".format(
|
||||||
|
self.id, self.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SyscallInterface:
|
||||||
|
def handle_syscall(self, scall: Syscall):
|
||||||
|
if getattr(self, scall.name):
|
||||||
|
getattr(self, scall.name)(scall)
|
||||||
|
else:
|
||||||
|
raise InvalidSyscallException(scall)
|
||||||
|
|
||||||
|
def read(self, scall: Syscall):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def write(self, scall: Syscall):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exit(self, scall: Syscall):
|
||||||
|
scall.cpu.exit = True
|
||||||
|
scall.cpu.exit_code = scall.registers.get('a0')
|
@ -0,0 +1,52 @@
|
|||||||
|
if __name__ == '__main__':
|
||||||
|
from . import *
|
||||||
|
from .helpers import *
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator')
|
||||||
|
parser.add_argument('file', metavar='file.asm', type=str, help='The assembly file to interpret and run')
|
||||||
|
|
||||||
|
# RunConfig parameters
|
||||||
|
parser.add_argument('color', type=bool, help='Colored output', default=True)
|
||||||
|
parser.add_argument('default_stack_size', type=int, help='Default stack size of loaded programs', default=None,
|
||||||
|
metavar='default-stack-size')
|
||||||
|
parser.add_argument('debug_instruction', type=bool, default=True, metavar='debug-instruction',
|
||||||
|
help='Adds the dbg instruction, which launches an interactive debuggin session, smilar to '
|
||||||
|
'a breakpoint.')
|
||||||
|
|
||||||
|
parser.add_argument('print_tokens', metavar='print-tokens', type=bool, help='Print tokens after tokenization',
|
||||||
|
default=False)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
cfg = RunConfig(
|
||||||
|
color=args.color,
|
||||||
|
preffered_stack_size=args.default_stack_size,
|
||||||
|
debug_instruction=args.debug_instruction
|
||||||
|
)
|
||||||
|
|
||||||
|
if cfg.color:
|
||||||
|
FMT_PRINT = FMT_BOLD + FMT_MAGENTA
|
||||||
|
else:
|
||||||
|
FMT_NONE = ""
|
||||||
|
FMT_PRINT = ""
|
||||||
|
|
||||||
|
with open(args.file, 'r') as f:
|
||||||
|
asm = f.read()
|
||||||
|
|
||||||
|
tk = RiscVTokenizer(RiscVInput(asm))
|
||||||
|
tk.tokenize()
|
||||||
|
|
||||||
|
if args.print_tokens:
|
||||||
|
print(FMT_PRINT + "Tokens:" + FMT_NONE)
|
||||||
|
for token in tk.tokens:
|
||||||
|
print(token)
|
||||||
|
|
||||||
|
executable = ExecutableParser(tk).parse().get_execuable()
|
||||||
|
|
||||||
|
print(FMT_PRINT + "Executable:" + FMT_NONE, executable)
|
||||||
|
|
||||||
|
cpu = CPU(cfg)
|
||||||
|
le = cpu.load(executable)
|
||||||
|
cpu.run_loaded(le)
|
||||||
|
|
Loading…
Reference in New Issue