def check_operand(operand): """Validates operand object as an instruction operand and converts it to a standard form""" from peachpy.x86_64.registers import Register from peachpy.x86_64.pseudo import Label from peachpy.x86_64.function import LocalVariable from peachpy import Constant, Argument from peachpy.util import is_int, is_int64 if isinstance(operand, (Register, Constant, MemoryOperand, LocalVariable, Argument, RIPRelativeOffset, Label)): return operand elif is_int(operand): if not is_int64(operand): raise ValueError( "The immediate operand %d is not representable as a 64-bit value" ) return operand elif isinstance(operand, list): if len(operand) != 1: raise ValueError( "Memory operands must be represented by a list with only one element" ) return MemoryOperand(operand[0]) else: raise TypeError("Unsupported operand: %s" % str(operand))
def check_operand(operand): """Validates operand object as an instruction operand and converts it to a standard form""" from peachpy.x86_64.registers import Register, MaskedRegister from peachpy.x86_64.pseudo import Label from peachpy.x86_64.function import LocalVariable from peachpy.literal import Constant from peachpy import Argument from peachpy.util import is_int, is_int64 if isinstance(operand, (Register, MaskedRegister, Constant, MemoryOperand, LocalVariable, Argument, RIPRelativeOffset, Label)): return operand elif is_int(operand): if not is_int64(operand): raise ValueError("The immediate operand %d is not representable as a 64-bit value") return operand elif isinstance(operand, list): if len(operand) != 1: raise ValueError("Memory operands must be represented by a list with only one element") return MemoryOperand(operand[0]) elif isinstance(operand, set): if len(operand) != 1: raise ValueError("Rounding control & suppress-all-errors operands must be represented by a set " "with only one element") return next(iter(operand)) else: raise TypeError("Unsupported operand: %s" % str(operand))
def format_operand(operand, assembly_format): assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \ "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'" immediate_prefix_map = {"peachpy": "", "gas": "$", "nasm": "", "go": "$"} from peachpy.util import is_int64 if is_int64(operand): return immediate_prefix_map[assembly_format] + str(operand) else: return operand.format(assembly_format)
def format_operand_type(operand): """Returns string representation of the operand type in assembly language""" from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32, GeneralPurposeRegister16,\ GeneralPurposeRegister8, MMXRegister, XMMRegister, YMMRegister,\ al, ax, eax, rax, cl, xmm0 from peachpy.x86_64.pseudo import Label from peachpy.util import is_int64, is_int32, is_int16, is_int8 if is_int8(operand): return "imm8" elif is_int16(operand): return "imm16" elif is_int32(operand): return "imm32" elif is_int64(operand): return "imm64" elif al == operand: return "al" elif ax == operand: return "ax" elif eax == operand: return "eax" elif rax == operand: return "rax" elif cl == operand: return "cl" elif xmm0 == operand: return "xmm0" elif isinstance(operand, GeneralPurposeRegister64): return "r64" elif isinstance(operand, GeneralPurposeRegister32): return "r32" elif isinstance(operand, GeneralPurposeRegister16): return "r16" elif isinstance(operand, GeneralPurposeRegister8): return "r8" elif isinstance(operand, MMXRegister): return "mm" elif isinstance(operand, XMMRegister): return "xmm" elif isinstance(operand, YMMRegister): return "ymm" elif isinstance(operand, MemoryOperand): if operand.size is None: return "m" else: return "m" + str(operand.size) elif isinstance(operand, Label): return "rel" else: return operand.__class__.__name__
def format_operand(operand, assembly_format): assert assembly_format in {"peachpy", "gnu", "nasm", "go"}, \ "Supported assembly formats are 'peachpy', 'gnu', 'nasm', 'go'" immediate_prefix_map = { "peachpy": "", "gnu": "$", "nasm": "", "go": "$" } from peachpy.util import is_int64 if is_int64(operand): return immediate_prefix_map[assembly_format] + str(operand) else: return operand.format(assembly_format)
def check_operand(operand): """Validates operand object as an instruction operand and converts it to a standard form""" from peachpy.x86_64.registers import Register, MaskedRegister from peachpy.x86_64.pseudo import Label from peachpy.x86_64.function import LocalVariable from peachpy.literal import Constant from peachpy import Argument from peachpy.util import is_int, is_int64 from copy import copy, deepcopy if isinstance(operand, Register): return copy(operand) elif isinstance(operand, (MaskedRegister, MemoryOperand)): return deepcopy(operand) elif isinstance(operand, (Argument, RIPRelativeOffset, Label)): return operand elif is_int(operand): if not is_int64(operand): raise ValueError( "The immediate operand %d is not representable as a 64-bit value" ) return operand elif isinstance(operand, list): if len(operand) != 1: raise ValueError( "Memory operands must be represented by a list with only one element" ) return MemoryOperand(operand[0]) elif isinstance(operand, Constant): from copy import copy, deepcopy operand = copy(operand) import peachpy.common.function if peachpy.common.function.active_function: operand.name = deepcopy( operand.name, peachpy.common.function.active_function._names_memo) return MemoryOperand(operand) elif isinstance(operand, LocalVariable): return MemoryOperand(operand) elif isinstance(operand, set): if len(operand) != 1: raise ValueError( "Rounding control & suppress-all-errors operands must be represented by a set " "with only one element") return next(iter(operand)) else: raise TypeError("Unsupported operand: %s" % str(operand))
def _uint64xN(name, n, *args): from peachpy.util import is_int, is_int64 assert is_int(n) args = [arg for arg in args if arg is not None] if len(args) == 0: raise ValueError("At least one constant value must be specified") if len(args) != 1 and len(args) != n: raise ValueError("Either 1 or %d values must be specified" % n) for i, number in enumerate(args): if not is_int(number): raise TypeError("The value %s is not an integer" % str(number)) if not is_int64(number): raise ValueError("The number %d is not a 64-bit integer" % number) if number < 0: args[i] += 0x10000000000000000 if len(args) == 1: args = [args[0]] * n return Constant(8 * n, n, tuple(args), uint64_t, name)
def __init__(self, *args, **kwargs): from peachpy.x86_64.function import active_function from peachpy.x86_64.registers import GeneralPurposeRegister, MMXRegister, XMMRegister, YMMRegister origin = kwargs.get("origin") prototype = kwargs.get("prototype") if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0: origin = inspect.stack() super(RETURN, self).__init__("RETURN", origin=origin) self.operands = tuple(map(check_operand, args)) if len(self.operands) == 0: # It is not an error to return nothing from a function with a return type self.in_regs = tuple() self.out_regs = tuple() self.out_operands = tuple() elif len(self.operands) == 1: # It is an error to return something from a void function from peachpy.util import is_int64, int_size if active_function.result_type is None: raise ValueError("Void function should not return a value") if active_function.result_type.is_integer or active_function.result_type.is_pointer: if is_int64(self.operands[0]): if active_function.result_type.size is None and int_size(self.operands[0]) > 4 or\ active_function.result_type.size is not None and \ active_function.result_type.size < int_size(self.operands[0]): raise ValueError("Value {0} can not be represented with return type {1}". format(str(self.operands[0]), str(active_function.result_type))) self.in_regs = (False,) self.out_regs = (False,) self.out_operands = (False,) elif isinstance(self.operands[0], GeneralPurposeRegister): if active_function.result_type.size < self.operands[0].size: raise ValueError("Register {0} can not be converted to return type {1}". format(str(self.operands[0]), str(active_function.result_type))) self.in_regs = (True,) self.out_regs = (False,) self.out_operands = (False,) else: raise TypeError("Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) elif active_function.result_type.is_floating_point: if isinstance(self.operands[0], XMMRegister): self.in_regs = (True,) self.out_regs = (False,) self.out_operands = (False,) else: raise TypeError("Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) elif active_function.result_type.is_vector: if isinstance(self.operands[0], (MMXRegister, XMMRegister, YMMRegister)) and \ active_function.result_type.size == self.operands[0].size: self.in_regs = (True,) self.out_regs = (False,) self.out_operands = (False,) else: raise TypeError("Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) else: raise SyntaxError("Invalid operand type: RETURN " + ", ".join(map(format_operand_type, self.operands))) else: raise SyntaxError("Pseudo-instruction \"RETURN\" requires 0 or 1 operands") if peachpy.stream.active_stream is not None: peachpy.stream.active_stream.add_instruction(self)
def __init__(self, *args, **kwargs): from peachpy.x86_64.function import active_function from peachpy.x86_64.registers import GeneralPurposeRegister, MMXRegister, XMMRegister, YMMRegister origin = kwargs.get("origin") prototype = kwargs.get("prototype") if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level( ) > 0: origin = inspect.stack() super(RETURN, self).__init__("RETURN", origin=origin) self.operands = tuple(map(check_operand, args)) if len(self.operands) == 0: # It is not an error to return nothing from a function with a return type self.in_regs = tuple() self.out_regs = tuple() self.out_operands = tuple() elif len(self.operands) == 1: # It is an error to return something from a void function from peachpy.util import is_int64, int_size if active_function.result_type is None: raise ValueError("Void function should not return a value") if active_function.result_type.is_integer or active_function.result_type.is_pointer: if is_int64(self.operands[0]): if active_function.result_type.size < int_size( self.operands[0]): raise ValueError( "Value {0} can not be represented with return type {1}" .format(str(self.operands[0]), str(active_function.result_type))) self.in_regs = (False, ) self.out_regs = (False, ) self.out_operands = (False, ) elif isinstance(self.operands[0], GeneralPurposeRegister): if active_function.result_type.size < self.operands[0].size: raise ValueError( "Register {0} can not be converted to return type {1}" .format(str(self.operands[0]), str(active_function.result_type))) self.in_regs = (True, ) self.out_regs = (False, ) self.out_operands = (False, ) else: raise TypeError( "Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) elif active_function.result_type.is_floating_point: if isinstance(self.operands[0], XMMRegister): self.in_regs = (True, ) self.out_regs = (False, ) self.out_operands = (False, ) else: raise TypeError( "Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) elif active_function.result_type.is_vector: if isinstance(self.operands[0], (MMXRegister, XMMRegister, YMMRegister)) and \ active_function.result_type.size == self.operands[0].size: self.in_regs = (True, ) self.out_regs = (False, ) self.out_operands = (False, ) else: raise TypeError( "Invalid operand type: RETURN {0} for {1} function". format(str(self.operands[0]), str(active_function.result_type))) else: raise SyntaxError( "Invalid operand type: RETURN " + ", ".join(map(format_operand_type, self.operands))) else: raise SyntaxError( "Pseudo-instruction \"RETURN\" requires 0 or 1 operands") if peachpy.stream.active_stream is not None: peachpy.stream.active_stream.add_instruction(self)