You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
riscemu/riscemu/helpers.py

100 lines
2.8 KiB
Python

"""
RiscEmu (c) 2021 Anton Lydike
SPDX-License-Identifier: MIT
"""
from math import log10, ceil
from .Exceptions import *
def align_addr(addr: int, to_bytes: int = 8) -> int:
"""
align an address to `to_bytes` (meaning addr & to_bytes = 0)
"""
return addr + (-addr % to_bytes)
def parse_numeric_argument(arg: str) -> int:
"""
parse hex or int strings
"""
try:
if '0x' in arg or '0X' in arg:
return int(arg, 16)
return int(arg)
except ValueError as ex:
raise ParseException('Invalid immediate argument \"{}\", maybe missing symbol?'.format(arg), (arg, ex))
def int_to_bytes(val, bytes=4, unsigned=False) -> bytearray:
"""
int -> byte (two's complement)
"""
if unsigned and val < 0:
raise NumberFormatException("unsigned negative number!")
return bytearray([
(val >> ((bytes - i - 1) * 8)) & 0xFF for i in range(bytes)
])
def int_from_bytes(bytes, unsigned=False) -> int:
"""
byte -> int (two's complement)
"""
num = 0
for b in bytes:
num = num << 8
num += b
if unsigned:
return num
return to_signed(num)
def to_unsigned(num: int, bytes=4) -> int:
if num < 0:
return 2 ** (bytes * 8) + num
return num
def to_signed(num: int, bytes=4) -> int:
if num >> (bytes * 8 - 1):
return num - 2 ** (8 * bytes)
return num
def create_chunks(my_list, chunk_size):
"""Split a list like [a,b,c,d,e,f,g,h,i,j,k,l,m] into e.g. [[a,b,c,d],[e,f,g,h],[i,j,k,l],[m]]"""
return [my_list[i:i + chunk_size] for i in range(0, len(my_list), chunk_size)]
def apply_highlight(item, ind, hi_ind):
"""
applies some hightlight such as underline to item if ind == hi_ind
"""
if ind == hi_ind:
return FMT_UNDERLINE + FMT_ORANGE + item + FMT_NONE
return item
def highlight_in_list(items, hi_ind):
return " ".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):
"""Format byte array as per fmt. Group into groups of size `group`, and highlight index `highlight`."""
chunks = create_chunks(byte_arr, group)
if fmt == 'hex':
return highlight_in_list(['0x{}'.format(ch.hex()) for ch in chunks], highlight)
if fmt == 'int':
spc = str(ceil(log10(2 ** (group * 8 - 1))) + 1)
return highlight_in_list([('{:0' + spc + 'd}').format(int_from_bytes(ch)) for ch in chunks], highlight)
if fmt == 'uint':
spc = str(ceil(log10(2 ** (group * 8))))
return highlight_in_list([('{:0' + spc + 'd}').format(int_from_bytes(ch, unsigned=True)) for ch in chunks],
highlight)
if fmt == 'ascii':
return "".join(repr(chr(b))[1:-1] for b in byte_arr)