Compare commits

...

3 Commits

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (riscemu)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (riscemu)" project-jdk-type="Python SDK" />
</project> </project>

@ -10,7 +10,7 @@
<excludeFolder url="file://$MODULE_DIR$/riscemu.egg-info" /> <excludeFolder url="file://$MODULE_DIR$/riscemu.egg-info" />
<excludeFolder url="file://$MODULE_DIR$/build" /> <excludeFolder url="file://$MODULE_DIR$/build" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.10 (riscemu)" jdkType="Python SDK" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

@ -1,5 +1,21 @@
# Changelog # Changelog
## Upcoming 2.0.6
**Planned:**
- Add a floating point unit
- Add a crt0.s
- Add `mmap2` syscall with code 192
## 2.0.5
- Added unlimited register mode with `-o unlimited_regs`
## 2.0.4
- Bugfix: fix a sign issue in instruction parsing for `rd, rs, rs` format
- Bugfix: respect `conf.debug_instruction` setting
## 2.0.3 - 2022-04-18 ## 2.0.3 - 2022-04-18
- Syscalls: cleaned up formatting and added instructions for extensions - Syscalls: cleaned up formatting and added instructions for extensions

@ -252,7 +252,7 @@ class MMU:
sec.base = at_addr sec.base = at_addr
self.sections.append(sec) self.sections.append(sec)
self._update_state() self._update_state()
return True return True
def _update_state(self): def _update_state(self):
""" """
@ -281,14 +281,3 @@ class MMU:
return sec.context return sec.context
return InstructionContext() return InstructionContext()
def report_addr(self, addr: T_AbsoluteAddress):
sec = self.get_sec_containing(addr)
if not sec:
print("addr is in no section!")
return
owner = [b for b in self.programs if b.name == sec.owner]
if owner:
print("owned by: {}".format(owner[0]))
print("{}: 0x{:0x} + 0x{:0x}".format(name, val, addr - val))

@ -269,9 +269,10 @@ class RV32I(InstructionSet):
def instruction_jalr(self, ins: 'Instruction'): def instruction_jalr(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 2) ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0) reg = ins.get_reg(0)
addr = ins.get_imm(1) base = ins.get_reg(1)
addr = ins.get_imm(2)
self.regs.set(reg, Int32(self.pc)) self.regs.set(reg, Int32(self.pc))
self.pc = addr self.pc = self.regs.get(base).unsigned_value + addr
def instruction_ret(self, ins: 'Instruction'): def instruction_ret(self, ins: 'Instruction'):
ASSERT_LEN(ins.args, 0) ASSERT_LEN(ins.args, 0)

@ -6,8 +6,10 @@ SPDX-License-Identifier: MIT
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from math import log2, ceil
from typing import Dict, IO from typing import Dict, IO
from .types import BinaryDataMemorySection, MemoryFlags
from .colors import FMT_SYSCALL, FMT_NONE from .colors import FMT_SYSCALL, FMT_NONE
from .types import Int32, CPU from .types import Int32, CPU
from .types.exceptions import InvalidSyscallException from .types.exceptions import InvalidSyscallException
@ -16,6 +18,7 @@ SYSCALLS = {
63: 'read', 63: 'read',
64: 'write', 64: 'write',
93: 'exit', 93: 'exit',
192: 'mmap2',
1024: 'open', 1024: 'open',
1025: 'close', 1025: 'close',
} }
@ -27,6 +30,18 @@ dictionary and implement a method with the same name on the SyscallInterface
class. class.
""" """
ADDITIONAL_SYMBOLS = {
'MAP_PRIVATE': 1<<0,
'MAP_SHARED': 1<<1,
'MAP_ANON': 1<<2,
'MAP_ANONYMOUS': 1<<2,
'PROT_READ': 1<<0,
'PROT_WRITE': 1<<1,
}
"""
A set of additional symbols that are used by various syscalls.
"""
OPEN_MODES = { OPEN_MODES = {
0: 'rb', 0: 'rb',
1: 'wb', 1: 'wb',
@ -56,7 +71,7 @@ class Syscall:
self.id, self.name self.id, self.name
) )
def ret(self, code): def ret(self, code: int | Int32):
self.cpu.regs.set('a0', Int32(code)) self.cpu.regs.set('a0', Int32(code))
@ -66,10 +81,14 @@ def get_syscall_symbols():
:return: dictionary of all syscall symbols (SCALL_<name> -> id) :return: dictionary of all syscall symbols (SCALL_<name> -> id)
""" """
return { items: Dict[str, int] = {
('SCALL_' + name.upper()): num for num, name in SYSCALLS.items() ('SCALL_' + name.upper()): num for num, name in SYSCALLS.items()
} }
items.update(ADDITIONAL_SYMBOLS)
return items
class SyscallInterface: class SyscallInterface:
""" """
@ -198,6 +217,57 @@ class SyscallInterface:
scall.cpu.halted = True scall.cpu.halted = True
scall.cpu.exit_code = scall.cpu.regs.get('a0').value scall.cpu.exit_code = scall.cpu.regs.get('a0').value
def mmap2(self, scall: Syscall):
"""
mmap2 syscall:
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
Only supported modes:
addr = <any>
prot = either PROT_READ or PROT_READ | PROT_WRITE
flags = MAP_PRIVATE | MAP_ANONYMOUS
fd = <ignored>
off_t = <ignored>
"""
addr = scall.cpu.regs.get('a0').unsigned_value
size = scall.cpu.regs.get('a1').unsigned_value
prot = scall.cpu.regs.get('a2').unsigned_value
flags = scall.cpu.regs.get('a3').unsigned_value
# error out if prot is not 1 or 3:
# 1 = PROT_READ
# 3 = PROT_READ | PROT_WRITE
if prot != 1 and prot != 3:
return scall.ret(-1)
# round size up to multiple of 4096
size = 4096 * ceil(size / 4096)
section = BinaryDataMemorySection(
bytearray(size),
'.data.runtime-allocated',
None,
'system',
base=addr,
flags=MemoryFlags(read_only=prot != 3, executable=False)
)
# try to insert section
if scall.cpu.mmu.load_section(section, addr != 0):
return scall.ret(section.base)
# if that failed, and we tried to force an address,
# try again at any address
elif addr != 0:
section.base = 0
if scall.cpu.mmu.load_section(section):
return scall.ret(section.base)
# if that didn't work, return error
return scall.ret(-1)
def __repr__(self): def __repr__(self):
return "{}(\n\tfiles={}\n)".format( return "{}(\n\tfiles={}\n)".format(
self.__class__.__name__, self.__class__.__name__,

@ -1,12 +1,16 @@
import typing import typing
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import List, Type, Callable, Set, Dict from typing import List, Type, Callable, Set, Dict, TYPE_CHECKING
from ..registers import Registers from ..registers import Registers
from ..config import RunConfig from ..config import RunConfig
from ..colors import FMT_RED, FMT_NONE, FMT_ERROR, FMT_CPU from ..colors import FMT_RED, FMT_NONE, FMT_ERROR, FMT_CPU
from . import T_AbsoluteAddress, Instruction, Program, ProgramLoader from . import T_AbsoluteAddress, Instruction, Program, ProgramLoader
if TYPE_CHECKING:
from .. import MMU
from ..instructions import InstructionSet
class CPU(ABC): class CPU(ABC):
# static cpu configuration # static cpu configuration

Loading…
Cancel
Save