more work on syscalls

float_support
Anton Lydike 4 years ago
parent a69cc7d346
commit a483db65c7

@ -5,6 +5,7 @@ from .Exceptions import *
from .helpers import *
from .Config import RunConfig
from .Registers import Registers
from .Syscall import SyscallInterface, Syscall
import typing
if typing.TYPE_CHECKING:
@ -14,14 +15,14 @@ if typing.TYPE_CHECKING:
class CPU:
def __init__(self, conf: RunConfig):
from . import MMU, Executable, LoadedExecutable, LoadedInstruction
self.mmu = MMU(conf)
self.regs = Registers()
from . import MMU
self.pc = 0
self.exit = False
self.exit_code = 0
self.conf = conf
self.mmu = MMU(conf)
self.regs = Registers()
self.syscall_int = SyscallInterface()
def load(self, e: 'Executable'):
@ -215,6 +216,7 @@ class CPU:
INS_NOT_IMPLEMENTED(ins)
def instruction_scall(self, ins: 'LoadedInstruction'):
ASSERT_LEN(ins.args, 0)
syscall = Syscall(self.regs.get('a7'), self.regs)
self.syscall_int.handle_syscall(syscall)
@ -235,14 +237,3 @@ class CPU:
if method.startswith('instruction_'):
yield method[12:]
@dataclass(frozen=True)
class Syscall:
id: int
registers: Registers
class SyscallInterface:
def handle_syscall(self, scall: Syscall):
print("syscall {} received!".format(scall.id))
scall.registers.dump_reg_a()

@ -7,3 +7,7 @@ class RunConfig:
color: bool = True
preffered_stack_size: Optional[int] = None
debug_instruction: bool = True
# allowed syscalls
scall_input: bool = True
scall_fs: bool = False

@ -99,11 +99,23 @@ class InvalidRegisterException(RiscemuBaseException):
)
class InvalidSyscallException(RiscemuBaseException):
def __init__(self, scall):
self.scall = scall
def message(self):
return "{}(Invalid syscall: {})".format(
self.__class__.__name__,
self.scall
)
def INS_NOT_IMPLEMENTED(ins):
raise UnimplementedInstruction(ins)
class NumberFormatException(RiscemuBaseException):
class NumberFormatException(RiscemuBaseException):
def __init__(self, msg):
super().__init__()
self.msg = msg

@ -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')

@ -41,8 +41,13 @@ def int_from_bytes(bytes, unsigned=False):
return num
# Colors
FMT_ORANGE = '\033[33m'
FMT_GRAY = '\033[37m'
FMT_CYAN = '\033[36m'
FMT_GREEN = '\033[32m'
FMT_BOLD = '\033[1m'
FMT_MAGENTA = '\033[35m'
FMT_NONE = '\033[0m'
FMT_UNDERLINE = '\033[4m'

@ -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…
Cancel
Save