# Path: VM/util.py
# class Instruction(metaclass=InstructionMeta):
#     """
#     This class is here for convenience purposes only since it's much simpler (a.k.a. easier to type) to inherit from a class
#      than to use some weird metaclass. Also, all classes inheriting this one are automagically registered by the metaclass.
#     """
#     ...
# 
# def is_signed_out_of_range(num: int, size: int) -> bool:
#     """
#     Check if the signed number `num` is out of range for signed numbers of `size` byte length.
#     :param num:
#     :param size:
#     :return:
#     """
#     if size == 1:
#         return -128 <= num <= 127
#     elif size == 2:
#         return -32_768 <= num <= 32_767
#     elif size == 4:
#         return -2_147_483_648 <= num <= 2_147_483_647
# 
#     raise ValueError(f'Invalid number size: {size} not in (1, 2, 4)')
# 
# Path: VM/misc.py
# def parity(num: int) -> int:
#     """
#     Calculate the parity of the least significant byte of a number.
#     See: https://graphics.stanford.edu/~seander/bithacks.html#ParityWith64Bits
#     :param num: The byte to calculate the parity of.
#     :return:
#     """
# 
#     return ((((num & 0xFF) * 0x0101010101010101) & 0x8040201008040201) % 0x1FF) & 1
# 
# class Shift(enum.Enum):
#     C_ONE  = 1
#     C_CL   = 2
#     C_imm8 = 3
# 
#     SHL = 4
#     SHR = 5
#     SAR = 6
# 
# def MSB(num: int, size: int) -> int:
#     """
#     Get the most significant bit of a `size`-byte number `num`.
#     :param num: A number.
#     :param size: The number of bytes in this number.
#     :return:
#     """
# 
#     return (num >> (size * 8 - 1)) & 1
# 
# def LSB(num: int) -> int:
#     """
#     Get the least significant bit of a `size`-byte number `num`.
#     :param num: A number.
#     :param size: The number of bytes in this number.
#     :return:
#     """
# 
#     return num & 1


from ..util import Instruction, is_signed_out_of_range
from ..misc import parity, Shift, MSB, LSB
from functools import partialmethod as P
    from ..debug import debug_operand, debug_register_operand
import operator
    import logging
        b = operation(a, sz)

        if operation == NEGNOT.operation_neg:
            sign_b = (b >> (sz * 8 - 1)) & 1
            vm.reg.eflags.CF = a != 0
            vm.reg.eflags.SF = sign_b
            vm.reg.eflags.ZF = b == 0
            vm.reg.eflags.PF = parity(b)
            vm.reg.eflags.OF = is_signed_out_of_range(b, sz)
            # TODO: deal with AF
            # vm.reg.efags.AF = ??

        b &= MAXVALS[sz]
        (type).set(loc, sz, b)

        if __debug__:
            dbg = debug_operand(RM, sz)
            logger.debug(
                '%s %s=%d (%s := %d)',
                operation.__name__,
                dbg, a,
                dbg, b
            )

        return True


####################
# SAL / SAR / SHL / SHR
####################

# Path: VM/util.py
# class Instruction(metaclass=InstructionMeta):
#     """
#     This class is here for convenience purposes only since it's much simpler (a.k.a. easier to type) to inherit from a class
#      than to use some weird metaclass. Also, all classes inheriting this one are automagically registered by the metaclass.
#     """
#     ...
# 
# def is_signed_out_of_range(num: int, size: int) -> bool:
#     """
#     Check if the signed number `num` is out of range for signed numbers of `size` byte length.
#     :param num:
#     :param size:
#     :return:
#     """
#     if size == 1:
#         return -128 <= num <= 127
#     elif size == 2:
#         return -32_768 <= num <= 32_767
#     elif size == 4:
#         return -2_147_483_648 <= num <= 2_147_483_647
# 
#     raise ValueError(f'Invalid number size: {size} not in (1, 2, 4)')
# 
# Path: VM/misc.py
# def parity(num: int) -> int:
#     """
#     Calculate the parity of the least significant byte of a number.
#     See: https://graphics.stanford.edu/~seander/bithacks.html#ParityWith64Bits
#     :param num: The byte to calculate the parity of.
#     :return:
#     """
# 
#     return ((((num & 0xFF) * 0x0101010101010101) & 0x8040201008040201) % 0x1FF) & 1
# 
# class Shift(enum.Enum):
#     C_ONE  = 1
#     C_CL   = 2
#     C_imm8 = 3
# 
#     SHL = 4
#     SHR = 5
#     SAR = 6
# 
# def MSB(num: int, size: int) -> int:
#     """
#     Get the most significant bit of a `size`-byte number `num`.
#     :param num: A number.
#     :param size: The number of bytes in this number.
#     :return:
#     """
# 
#     return (num >> (size * 8 - 1)) & 1
# 
# def LSB(num: int) -> int:
#     """
#     Get the least significant bit of a `size`-byte number `num`.
#     :param num: A number.
#     :param size: The number of bytes in this number.
#     :return:
#     """
# 
#     return num & 1


# Path: VM/instructions/bitwise.py
from ..util import Instruction, is_signed_out_of_range
from ..misc import parity, Shift, MSB, LSB
from functools import partialmethod as P
    from ..debug import debug_operand, debug_register_operand
import operator
    import logging

        b = operation(a, sz)

        if operation == NEGNOT.operation_neg:
            sign_b = (b >> (sz * 8 - 1)) & 1
            vm.reg.eflags.CF = a != 0
            vm.reg.eflags.SF = sign_b
            vm.reg.eflags.ZF = b == 0
            vm.reg.eflags.PF = parity(b)
            vm.reg.eflags.OF = is_signed_out_of_range(b, sz)
            # TODO: deal with AF
            # vm.reg.efags.AF = ??

        b &= MAXVALS[sz]
        (type).set(loc, sz, b)

        if __debug__:
            dbg = debug_operand(RM, sz)
            logger.debug(
                '%s %s=%d (%s := %d)',
                operation.__name__,
                dbg, a,
                dbg, b
            )

        return True


####################
# SAL / SAR / SHL / SHR
####################

class SHIFT(Instruction):