add an unlimited register mode
This commit is contained in:
parent
86063d64d7
commit
636e06f243
@ -57,12 +57,19 @@ if __name__ == '__main__':
|
||||
setattr(namespace, self.dest, d)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu')
|
||||
parser = argparse.ArgumentParser(description='RISC-V Userspace parser and emulator', prog='riscemu',
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('files', metavar='file.asm', type=str, nargs='+',
|
||||
help='The assembly files to load, the last one will be run')
|
||||
|
||||
parser.add_argument('--options', '-o', action=OptionStringAction,
|
||||
keys=('disable_debug', 'no_syscall_symbols', 'fail_on_ex', 'add_accept_imm'))
|
||||
keys=('disable_debug', 'no_syscall_symbols', 'fail_on_ex', 'add_accept_imm', 'unlimited_regs'),
|
||||
help="""Toggle options. Available options are:
|
||||
disable_debug: Disable ebreak instructions
|
||||
no_syscall_symbols: Don't add symbols for SCALL_EXIT and others
|
||||
fail_on_ex: If set, exceptions won't trigger the debugger
|
||||
add_accept_imm: Accept "add rd, rs, imm" instruction (instead of addi)
|
||||
unlimited_regs: Allow an unlimited number of registers""")
|
||||
|
||||
parser.add_argument('--syscall-opts', '-so', action=OptionStringAction,
|
||||
keys=('fs_access', 'disable_input'))
|
||||
@ -88,6 +95,7 @@ if __name__ == '__main__':
|
||||
include_scall_symbols=not args.options['no_syscall_symbols'],
|
||||
debug_on_exception=not args.options['fail_on_ex'],
|
||||
add_accept_imm=args.options['add_accept_imm'],
|
||||
unlimited_registers=args.options['unlimited_regs'],
|
||||
scall_fs=args.syscall_opts['fs_access'],
|
||||
scall_input=not args.syscall_opts['disable_input'],
|
||||
verbosity=args.verbose
|
||||
|
@ -20,6 +20,7 @@ class RunConfig:
|
||||
scall_fs: bool = False
|
||||
verbosity: int = 0
|
||||
slowdown: float = 1
|
||||
unlimited_registers: bool = False
|
||||
|
||||
|
||||
CONFIG = RunConfig()
|
||||
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
|
||||
This package holds all instruction sets, available to the processor
|
||||
"""
|
||||
|
||||
from .instruction_set import InstructionSet
|
||||
from .instruction_set import InstructionSet, Instruction
|
||||
from .RV32M import RV32M
|
||||
from .RV32I import RV32I
|
||||
from .RV32A import RV32A
|
||||
|
@ -110,6 +110,9 @@ class AssemblyFileLoader(ProgramLoader):
|
||||
with open(self.source_path, 'r') as f:
|
||||
return parse_tokens(self.filename, tokenize(f))
|
||||
|
||||
def parse_io(self, io):
|
||||
return parse_tokens(self.filename, tokenize(io))
|
||||
|
||||
@classmethod
|
||||
def can_parse(cls, source_path: str) -> float:
|
||||
"""
|
||||
|
@ -17,11 +17,22 @@ class Registers:
|
||||
Represents a bunch of registers
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
valid_regs = {
|
||||
'zero', 'ra', 'sp', 'gp', 'tp', 's0', 'fp',
|
||||
't0', 't1', 't2', 't3', 't4', 't5', 't6',
|
||||
's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11',
|
||||
'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7',
|
||||
'ft0', 'ft1', 'ft2', 'ft3', 'ft4', 'ft5', 'ft6', 'ft7',
|
||||
'fs0', 'fs1', 'fs2', 'fs3', 'fs4', 'fs5', 'fs6', 'fs7', 'fs8', 'fs9', 'fs10', 'fs11',
|
||||
'fa0', 'fa1', 'fa2', 'fa3', 'fa4', 'fa5', 'fa6', 'fa7'
|
||||
}
|
||||
|
||||
def __init__(self, infinite_regs: bool = False):
|
||||
from .types import Int32
|
||||
self.vals = defaultdict(lambda: Int32(0))
|
||||
self.last_set = None
|
||||
self.last_read = None
|
||||
self.infinite_regs = infinite_regs
|
||||
|
||||
def dump(self, full=False):
|
||||
"""
|
||||
@ -108,7 +119,10 @@ class Registers:
|
||||
reg = 's1'
|
||||
if mark_set:
|
||||
self.last_set = reg
|
||||
# check 32 bit signed bounds
|
||||
|
||||
if not self.infinite_regs and reg not in self.valid_regs:
|
||||
raise RuntimeError("Invalid register: {}".format(reg))
|
||||
|
||||
self.vals[reg] = val.unsigned()
|
||||
return True
|
||||
|
||||
@ -123,6 +137,10 @@ class Registers:
|
||||
# raise InvalidRegisterException(reg)
|
||||
if reg == 'fp':
|
||||
reg = 's0'
|
||||
|
||||
if not self.infinite_regs and reg not in self.valid_regs:
|
||||
raise RuntimeError("Invalid register: {}".format(reg))
|
||||
|
||||
if mark_read:
|
||||
self.last_read = reg
|
||||
return self.vals[reg]
|
||||
|
@ -31,7 +31,7 @@ class CPU(ABC):
|
||||
|
||||
def __init__(self, mmu: 'MMU', instruction_sets: List[Type['InstructionSet']], conf: RunConfig):
|
||||
self.mmu = mmu
|
||||
self.regs = Registers()
|
||||
self.regs = Registers(conf.unlimited_registers)
|
||||
self.conf = conf
|
||||
|
||||
self.instruction_sets = set()
|
||||
|
Loading…
Reference in New Issue
Block a user