added unified instruction parsing

float_support
Anton Lydike 4 years ago
parent 2d378f2e0a
commit 1957e11f62

@ -35,19 +35,19 @@ class CPU:
self.instruction_sets: List['InstructionSet'] = list()
self.instructions: Dict[str, Callable[[LoadedInstruction], None]] = dict()
for set_class in instruction_sets:
ins_set = set_class()
self.instructions.update(ins_set.load(self))
ins_set = set_class(self)
self.instructions.update(ins_set.load())
self.instruction_sets.append(ins_set)
# provide global syscall symbols if option is set
if conf.include_scall_symbols:
self.mmu.global_symbols.update(self.syscall_int.get_syscall_symbols())
def get_tokenizer(self, input):
def get_tokenizer(self, tokenizer_input):
"""
Returns a tokenizer that respects the language of the CPU
"""
return RiscVTokenizer(input, self.all_instructions())
return RiscVTokenizer(tokenizer_input, self.all_instructions())
def load(self, e: 'Executable'):
"""
@ -93,23 +93,6 @@ class CPU:
# this should never be reached, as unknown instructions are imparseable
raise RuntimeError("Unknown instruction: {}".format(ins))
def parse_mem_ins(self, ins: 'LoadedInstruction') -> Tuple[str, int]:
"""
parses both rd, rs1, imm and rd, imm(rs1) arguments and returns (rd, imm+rs1)
(so a register and address tuple for memory instructions)
"""
if len(ins.args) == 3:
# handle rd, rs1, imm
rs1 = ins.get_reg(1)
imm = ins.get_imm(2)
else:
ASSERT_LEN(ins.args, 2)
ASSERT_IN("(", ins.args[1])
imm, rs1 = ins.get_imm_reg(1)
# handle rd, imm(rs1)
rd = ins.get_reg(0)
return rd, self.regs.get(rs1) + imm
def all_instructions(self) -> List[str]:
return list(self.instructions.keys())

@ -8,16 +8,19 @@ class InstructionSet(ABC):
"""
Represents a collection of instructions
"""
def __init__(self):
self.cpu: typing.Optional['CPU'] = None
self.mmu: typing.Optional['MMU'] = None
self.regs: typing.Optional['Registers'] = None
def load(self, cpu: 'CPU'):
def __init__(self, cpu: 'CPU'):
self.cpu = cpu
self.mmu = cpu.mmu
self.regs = cpu.regs
def load(self) -> typing.Dict[str, typing.Callable[['LoadedInstruction'], None]]:
"""
This is called by the CPU once it instantiates this instruction set
It returns a dictionary of all instructions in this instruction set,
pointing to the correct handler for it
"""
return {
name: ins for name, ins in self.get_instructions()
}
@ -27,24 +30,46 @@ class InstructionSet(ABC):
if member.startswith('instruction_'):
yield member[12:].replace('_', '.'), getattr(self, member)
def parse_mem_ins(self, ins: 'LoadedInstruction'):
return self.cpu.parse_mem_ins(ins)
def parse_mem_ins(self, ins: 'LoadedInstruction') -> Tuple[str, int]:
"""
parses both rd, rs, imm and rd, imm(rs) arguments and returns (rd, imm+rs1)
(so a register and address tuple for memory instructions)
"""
if len(ins.args) == 3:
# handle rd, rs1, imm
rs = self.get_reg_content(ins, 1)
imm = ins.get_imm(2)
else:
# handle rd, imm(rs1)
ASSERT_LEN(ins.args, 2)
ASSERT_IN("(", ins.args[1])
imm, rs_name = ins.get_imm_reg(1)
rs = self.regs.get(rs_name)
rd = ins.get_reg(0)
return rd, rs + imm
def parse_rd_rs_rs(self, ins: 'LoadedInstruction'):
def parse_rd_rs_rs(self, ins: 'LoadedInstruction') -> Tuple[str, int, int]:
"""
Assumes the command is in <name> rd, rs1, rs2 format
Returns the name of rd, and the values in rs1 and rs2
"""
ASSERT_LEN(ins.args, 3)
return ins.get_reg(0), self.get_reg_content(ins, 1), self.get_reg_content(ins, 2)
def parse_rd_rs_imm(self, ins: 'LoadedInstruction'):
def parse_rd_rs_imm(self, ins: 'LoadedInstruction') -> Tuple[str, int, int]:
"""
Assumes the command is in <name> rd, rs, imm format
Returns the name of rd, the value in rs and the immediate imm
"""
ASSERT_LEN(ins.args, 3)
return ins.get_reg(0), self.get_reg_content(ins, 1), ins.get_imm(2)
def get_reg_content(self, ins: 'LoadedInstruction', ind: int):
def get_reg_content(self, ins: 'LoadedInstruction', ind: int) -> int:
"""
get the register name from ins and then return the register contents
"""
return self.regs.get(ins.get_reg(ind))
@property
def pc(self):
return self.cpu.pc
@ -57,4 +82,4 @@ class InstructionSet(ABC):
return "InstructionSet[{}] with {} instructions".format(
self.__class__.__name__,
len(list(self.get_instructions()))
)
)

Loading…
Cancel
Save