From 10a3c4201e63d904d6e69f989ad64cde7c8e3e3d Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Sun, 17 Apr 2022 12:34:07 +0200 Subject: [PATCH] cleaned up and improved memory dumping code --- riscemu/helpers.py | 21 +++---------- riscemu/types/memory_section.py | 54 ++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/riscemu/helpers.py b/riscemu/helpers.py index 0a469b6..a73b919 100644 --- a/riscemu/helpers.py +++ b/riscemu/helpers.py @@ -44,8 +44,8 @@ def apply_highlight(item, ind, hi_ind): return item -def highlight_in_list(items, hi_ind): - return " ".join([apply_highlight(item, i, hi_ind) for i, item in enumerate(items)]) +def highlight_in_list(items, hi_ind, joiner=" "): + return joiner.join([apply_highlight(item, i, hi_ind) for i, item in enumerate(items)]) def format_bytes(byte_arr: bytearray, fmt: str, group: int = 1, highlight: int = -1): @@ -60,21 +60,8 @@ def format_bytes(byte_arr: bytearray, fmt: str, group: int = 1, highlight: int = spc = str(ceil(log10(2 ** (group * 8)))) return highlight_in_list([('{:0' + spc + 'd}').format(UInt32(ch)) for ch in chunks], highlight) - if fmt == 'ascii': - return "".join(repr(chr(b))[1:-1] for b in byte_arr) - - -def bind_twos_complement(val): - """ - does over/underflows for 32 bit two's complement numbers - :param val: - :return: - """ - if val < -2147483648: - return val + 4294967296 - elif val > 2147483647: - return val - 4294967296 - return val + if fmt == 'char': + return highlight_in_list((repr(chr(b))[1:-1] for b in byte_arr), highlight, "") T = TypeVar('T') diff --git a/riscemu/types/memory_section.py b/riscemu/types/memory_section.py index a1512e4..a135bcb 100644 --- a/riscemu/types/memory_section.py +++ b/riscemu/types/memory_section.py @@ -2,9 +2,9 @@ from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Optional -from ..colors import FMT_MEM, FMT_NONE, FMT_UNDERLINE, FMT_ORANGE +from ..colors import FMT_MEM, FMT_NONE, FMT_UNDERLINE, FMT_ORANGE, FMT_ERROR from ..helpers import format_bytes -from . import MemoryFlags, T_AbsoluteAddress, InstructionContext, T_RelativeAddress, Instruction +from . import MemoryFlags, T_AbsoluteAddress, InstructionContext, T_RelativeAddress, Instruction, Int32 @dataclass @@ -32,17 +32,55 @@ class MemorySection(ABC): def read_ins(self, offset: T_RelativeAddress) -> Instruction: pass - def dump(self, start: T_RelativeAddress, end: Optional[T_RelativeAddress] = None, fmt: str = 'hex', - bytes_per_row: int = 16, rows: int = 10, group: int = 4): - if self.flags.executable: + def dump(self, start: T_RelativeAddress, end: Optional[T_RelativeAddress] = None, fmt: str = None, + bytes_per_row: int = None, rows: int = 10, group: int = None, highlight: int = None): + """ + Dump the section. If no end is given, the rows around start are printed and start is highlighted. + + :param start: The address to start at + :param end: The end of the printed space + :param fmt: either hex, int, char or asm + :param bytes_per_row: the number of bytes displayed per row + :param rows: the number of rows displayed + :param group: Group this many bytes into one when displaying + :param highlight: Highligh the group containing this address + :return: + """ + if isinstance(start, Int32): + start = start.value + if isinstance(end, Int32): + end = end.value + + if fmt is None: + if self.flags.executable and self.flags.read_only: + bytes_per_row = 4 + fmt = 'asm' + else: + fmt = 'hex' + + if fmt == 'char': + if bytes_per_row is None: + bytes_per_row = 4 + if group is None: + group = 1 + + if group is None: + group = 4 + + if bytes_per_row is None: bytes_per_row = 4 - highlight = None + + if fmt not in ('asm', 'hex', 'int', 'char'): + print(FMT_ERROR + '[MemorySection] Unknown format {}, known formats are {}'.format( + fmt, ", ".join(('asm', 'hex', 'int', 'char')) + ) + FMT_NONE) + if end is None: - end = min(start + (bytes_per_row * (rows // 2)), self.size - 1) + end = min(start + (bytes_per_row * (rows // 2)), self.size) highlight = start start = max(0, start - (bytes_per_row * (rows // 2))) - if self.flags.executable: + if fmt == 'asm': print(FMT_MEM + "{}, viewing {} instructions:".format( self, (end - start) // 4 ) + FMT_NONE)