# Path: VM/ctypes_types.py

# 
# Path: VM/FPU.py
# class _FPU_status(ctypes.LittleEndianStructure):
# class _FPU_control(ctypes.LittleEndianStructure):
# class FPU_status(ctypes.Union):
# class FPU_control(ctypes.Union):
# class FPU_tag(ctypes.LittleEndianStructure):
# class binary32(ctypes.LittleEndianStructure):
# class binary64(ctypes.LittleEndianStructure):
# class _binary80(ctypes.LittleEndianStructure):  # Double Extended-Precision Floating-Point format
# class FPInvalidArithmeticOperand(Exception):
# class binary80(_binary80):
# class _FPU(ctypes.LittleEndianStructure):
# class FPU(_FPU):
#     BIAS = 127
#     BIAS = 1023
#     BIAS = 16383
#     ZERO = lambda sign=0: binary80(0, 0, sign)
#         S = s1 + s2
#         S = s1 - s2
#             S = -S
#         S = s1 * s2
#         S = s1 // s2
#     def __float__(self):
#     def __float__(self):
#     def __str__(self):
#     def __float__(self) -> float:
#     def __int__(self) -> int:
#     def __align_exponents(self, other) -> (int, int, int):
#     def __normalize(exponent: int, significand: int, bits: int = 63) -> (int, int):
#     def __is_zero(self) -> bool:
#     def __is_SNaN(self) -> bool:
#     def __is_QNaN(self) -> bool:
#     def __is_NaN(self) -> bool:
#     def __is_Inf(self, sign=None) -> bool:
#     def __neg__(self):
#     def __add__(self, other):
#     def __sub__(self, other):
#     def __mul__(self, other):
#     def __truediv__(self, other):
#     def __eq__(self, other) -> bool:
#     def __gt__(self, other) -> bool:
#     def __lt__(self, other) -> bool:
#     def from_int(val: int):
#     def from_double(val: float):
#     def from_float(val: float):
#     def __init__(self, *args, **kwargs):
#     def store_top(self, value: binary80) -> None:
#     def store(self, index: int, value: binary80) -> None:
#     def push(self, value: binary80) -> None:
#     def _push_float(self, value: float) -> None:
#     def pop(self) -> binary80:
#     def _pop_float(self) -> float:
#     def add(self, a: int, b: int) -> binary80:
#     def sub(self, a: int, b: int) -> binary80:
#     def mul(self, a: int, b: int) -> binary80:
#     def div(self, a: int, b: int) -> binary80:
#     def ST(self, index: int) -> binary80:


from ctypes import addressof, pointer, memmove, memset, string_at
from .ctypes_types import ubyte, uword, udword, uqword
from .FPU import flt, dbl, binary80
            )

        assert offset >= 0, f'Invalid memory address: {hex(offset)}'

        addr = self.__segment_base + offset
        if size == 4:
            # faster than byte unpacking with shifts
            self.mem[addr:addr + 4] = (val & 0xFFFFFFFF).to_bytes(4, 'little')
        elif size == 2:
            # faster than `(val & 0xFFFF).to_bytes(2, 'little')`
            self.mem[addr:addr + 2] = val & 0xFF, (val >> 8) & 0xFF  # (val & 0xFFFF).to_bytes(2, 'little')
        elif size == 1:
            self.mem[addr] = val
        else:
            raise RuntimeError(f'Memory.set: invalid size: {size} not in (1, 2, 4). Use Memory.set_bytes instead')

    def set_float(self, offset: int, size: int, val: binary80) -> None:
        # self.asan(offset, size) -> pasted here for speed
        if self.__segment_base + offset > self.__size or self.__segment_base + offset + size > self.__size:
            raise MemoryError(
                f'Not enough memory (tried to write to address range 0x{offset:08x}-0x{offset + size:08x} '
                f'({size} bytes), maximum address: 0x{self.size:08x} bytes)'
            )

        assert offset >= 0, f'Invalid memory address: {hex(offset)}'

        converted = {4: flt, 8: dbl}[size](float(val))

        addr = self.__segment_base + offset


# Path: VM/ctypes_types.py

# 
# Path: VM/FPU.py
# class _FPU_status(ctypes.LittleEndianStructure):
# class _FPU_control(ctypes.LittleEndianStructure):
# class FPU_status(ctypes.Union):
# class FPU_control(ctypes.Union):
# class FPU_tag(ctypes.LittleEndianStructure):
# class binary32(ctypes.LittleEndianStructure):
# class binary64(ctypes.LittleEndianStructure):
# class _binary80(ctypes.LittleEndianStructure):  # Double Extended-Precision Floating-Point format
# class FPInvalidArithmeticOperand(Exception):
# class binary80(_binary80):
# class _FPU(ctypes.LittleEndianStructure):
# class FPU(_FPU):
#     BIAS = 127
#     BIAS = 1023
#     BIAS = 16383
#     ZERO = lambda sign=0: binary80(0, 0, sign)
#         S = s1 + s2
#         S = s1 - s2
#             S = -S
#         S = s1 * s2
#         S = s1 // s2
#     def __float__(self):
#     def __float__(self):
#     def __str__(self):
#     def __float__(self) -> float:
#     def __int__(self) -> int:
#     def __align_exponents(self, other) -> (int, int, int):
#     def __normalize(exponent: int, significand: int, bits: int = 63) -> (int, int):
#     def __is_zero(self) -> bool:
#     def __is_SNaN(self) -> bool:
#     def __is_QNaN(self) -> bool:
#     def __is_NaN(self) -> bool:
#     def __is_Inf(self, sign=None) -> bool:
#     def __neg__(self):
#     def __add__(self, other):
#     def __sub__(self, other):
#     def __mul__(self, other):
#     def __truediv__(self, other):
#     def __eq__(self, other) -> bool:
#     def __gt__(self, other) -> bool:
#     def __lt__(self, other) -> bool:
#     def from_int(val: int):
#     def from_double(val: float):
#     def from_float(val: float):
#     def __init__(self, *args, **kwargs):
#     def store_top(self, value: binary80) -> None:
#     def store(self, index: int, value: binary80) -> None:
#     def push(self, value: binary80) -> None:
#     def _push_float(self, value: float) -> None:
#     def pop(self) -> binary80:
#     def _pop_float(self) -> float:
#     def add(self, a: int, b: int) -> binary80:
#     def sub(self, a: int, b: int) -> binary80:
#     def mul(self, a: int, b: int) -> binary80:
#     def div(self, a: int, b: int) -> binary80:
#     def ST(self, index: int) -> binary80:


# Path: VM/Memory.py
from ctypes import addressof, pointer, memmove, memset, string_at
from .ctypes_types import ubyte, uword, udword, uqword
from .FPU import flt, dbl, binary80

            )

        assert offset >= 0, f'Invalid memory address: {hex(offset)}'

        addr = self.__segment_base + offset
        if size == 4:
            # faster than byte unpacking with shifts
            self.mem[addr:addr + 4] = (val & 0xFFFFFFFF).to_bytes(4, 'little')
        elif size == 2:
            # faster than `(val & 0xFFFF).to_bytes(2, 'little')`
            self.mem[addr:addr + 2] = val & 0xFF, (val >> 8) & 0xFF  # (val & 0xFFFF).to_bytes(2, 'little')
        elif size == 1:
            self.mem[addr] = val
        else:
            raise RuntimeError(f'Memory.set: invalid size: {size} not in (1, 2, 4). Use Memory.set_bytes instead')

    def set_float(self, offset: int, size: int, val: binary80) -> None:
        # self.asan(offset, size) -> pasted here for speed
        if self.__segment_base + offset > self.__size or self.__segment_base + offset + size > self.__size:
            raise MemoryError(
                f'Not enough memory (tried to write to address range 0x{offset:08x}-0x{offset + size:08x} '
                f'({size} bytes), maximum address: 0x{self.size:08x} bytes)'
            )

        assert offset >= 0, f'Invalid memory address: {hex(offset)}'

        converted = {4: flt, 8: dbl}[size](float(val))

        addr = self.__segment_base + offset


        self.mem[addr:addr + size] = {4: udword, 8: uqword}[size].from_buffer(converted).value.to_bytes(size, 'little')