parsing and simple running works somewhat
parent
da4ae7c4c1
commit
6bc939572b
@ -1,15 +1,61 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
from .Executable import Executable, LoadedExecutable, LoadedMemorySection
|
||||||
class MemoryFlags:
|
from .helpers import align_addr
|
||||||
read_only: bool
|
from .Exceptions import OutOfMemoryEsception
|
||||||
executable: bool
|
from typing import Dict, List, Tuple, Optional
|
||||||
|
|
||||||
class MemoryRegion:
|
|
||||||
addr:int
|
|
||||||
len:int
|
|
||||||
flags: MemoryFlags
|
|
||||||
|
|
||||||
|
|
||||||
class MMU:
|
class MMU:
|
||||||
|
max_size = 0xFFFFFFFF
|
||||||
|
# make each block accessible by it's base addr
|
||||||
|
sections: List[LoadedMemorySection]
|
||||||
|
|
||||||
|
binaries: List[LoadedExecutable]
|
||||||
|
last_bin: Optional[LoadedExecutable] = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.sections = list()
|
||||||
|
self.binaries = list()
|
||||||
|
self.last_bin = None
|
||||||
|
|
||||||
|
def load_bin(self, bin: Executable):
|
||||||
|
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)
|
||||||
|
|
||||||
|
loaded_bin = LoadedExecutable(bin, addr)
|
||||||
|
|
||||||
|
if loaded_bin.size + addr > self.max_size:
|
||||||
|
raise OutOfMemoryEsception('load of executable')
|
||||||
|
|
||||||
|
self.binaries.append(loaded_bin)
|
||||||
|
self.last_bin = loaded_bin
|
||||||
|
|
||||||
|
# read sections into sec dict
|
||||||
|
for sec in loaded_bin.sections:
|
||||||
|
self.sections.append(sec)
|
||||||
|
|
||||||
|
return loaded_bin
|
||||||
|
|
||||||
|
def get_sec_containing(self, addr: int):
|
||||||
|
for sec in self.sections:
|
||||||
|
if sec.base <= addr < sec.base + sec.size:
|
||||||
|
return sec
|
||||||
|
|
||||||
|
def read_ins(self, addr: int):
|
||||||
|
sec = self.get_sec_containing(addr)
|
||||||
|
return sec.read_instruction(addr - sec.base)
|
||||||
|
|
||||||
|
def read(self, addr: int, size: int):
|
||||||
|
sec = self.get_sec_containing(addr)
|
||||||
|
return sec.read(addr - sec.base, size)
|
||||||
|
|
||||||
|
def write(self, addr: int, size: int, data):
|
||||||
|
sec = self.get_sec_containing(addr)
|
||||||
|
return sec.write(addr - sec.base, size, data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
from .CPU import CPU, Registers, Syscall, SyscallInterface
|
from .Exceptions import ASSERT_NOT_NULL, ASSERT_LEN, ASSERT_IN, ASSERT_EQ, ASSERT_NOT_IN
|
||||||
|
|
||||||
from .Tokenizer import RiscVToken, RiscVInput, RiscVTokenizer, RiscVInstructionToken, RiscVSymbolToken, \
|
from .Tokenizer import RiscVToken, RiscVInput, RiscVTokenizer, RiscVInstructionToken, RiscVSymbolToken, \
|
||||||
RiscVPseudoOpToken, TokenType
|
RiscVPseudoOpToken, TokenType
|
||||||
|
|
||||||
from .MMU import MemoryFlags, MemoryRegion, MMU
|
|
||||||
|
|
||||||
from .Exceptions import ASSERT_NOT_NULL, ASSERT_LEN, ASSERT_IN, ASSERT_EQ, ASSERT_NOT_IN
|
from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction
|
||||||
|
|
||||||
from .Executable import ExecutableParser, Executable
|
from .ExecutableParser import ExecutableParser
|
||||||
|
|
||||||
|
from .MMU import MMU
|
||||||
|
|
||||||
|
from .CPU import CPU, Registers, Syscall, SyscallInterface
|
@ -0,0 +1,38 @@
|
|||||||
|
def align_addr(addr: int, to_bytes: int = 8):
|
||||||
|
"""
|
||||||
|
align an address to `to_bytes` (meaning addr & to_bytes = 0)
|
||||||
|
"""
|
||||||
|
return addr + (-addr % to_bytes)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_numeric_argument(arg: str):
|
||||||
|
"""
|
||||||
|
parse hex or int strings
|
||||||
|
"""
|
||||||
|
if arg.startswith('0x') or arg.startswith('0X'):
|
||||||
|
return int(arg, 16)
|
||||||
|
return int(arg)
|
||||||
|
|
||||||
|
|
||||||
|
def int_to_bytes(val, bytes=4):
|
||||||
|
"""
|
||||||
|
int -> byte (two's complement)
|
||||||
|
"""
|
||||||
|
return bytearray([
|
||||||
|
(val >> ((bytes-i-1) * 8)) & 0xFF for i in range(bytes)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def int_from_bytes(bytes):
|
||||||
|
"""
|
||||||
|
byte -> int (two's complement)
|
||||||
|
"""
|
||||||
|
num = 0
|
||||||
|
for b in bytes:
|
||||||
|
num = num << 8
|
||||||
|
num += b
|
||||||
|
sign = num >> (len(bytes) * 8 - 1)
|
||||||
|
if sign:
|
||||||
|
return num - 2 ** (8 * len(bytes))
|
||||||
|
return num
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
from .CPU import *
|
|
||||||
from .Tokenizer import *
|
|
||||||
|
|
Loading…
Reference in New Issue