Example #1
0
    def __init__(self, name, **attrs):
        l.debug("Creating SimIROp(%s)", name)
        self.name = name
        self.op_attrs = attrs

        self._generic_name = None
        self._from_size = None
        self._from_side = None
        self._from_type = None
        self._from_signed = None
        self._to_size = None
        self._to_type = None
        self._to_signed = None
        self._conversion = None
        self._vector_size = None
        self._vector_signed = None
        self._vector_type = None
        self._vector_zero = None
        self._vector_count = None

        self._rounding_mode = None

        for k, v in self.op_attrs.items():
            if v is not None and ('size' in k or 'count' in k):
                v = int(v)
            setattr(self, '_%s' % k, v)

        # determine the output size
        #pylint:disable=no-member
        self._output_type = pyvex.typeOfIROp(name)
        #pylint:enable=no-member
        self._output_size_bits = size_bits(self._output_type)
        l.debug("... VEX says the output size should be %s",
                self._output_size_bits)

        size_check = self._to_size is None or (
            self._to_size * 2 if self._generic_name == 'DivMod' else
            self._to_size) == self._output_size_bits
        if not size_check:
            raise SimOperationError(
                "VEX output size doesn't match detected output size")

        #
        # Some categorization
        #

        generic_names.add(self._generic_name)
        if self._conversion is not None:
            conversions[(self._from_type, self._from_signed, self._to_type,
                         self._to_signed)].append(self)

        if len({self._vector_type, self._from_type, self._to_type}
               & {'F', 'D'}) != 0:
            # print self.op_attrs
            self._float = True

            if len({self._vector_type, self._from_type, self._to_type}
                   & {'D'}) != 0:
                l.debug('... aborting on BCD!')
                # fp_ops.add(self.name)
                raise UnsupportedIROpError("BCD ops aren't supported")
        else:
            self._float = False

        #
        # Now determine the operation
        #

        self._calculate = None

        # is it explicitly implemented?
        if hasattr(self, '_op_' + name):
            self._calculate = getattr(self, '_op_' + name)
        # if the generic name is None and there's a conversion present, this is a standard
        # widening or narrowing or sign-extension
        elif self._generic_name is None and self._conversion:
            # convert int to float
            if self._float and self._from_type == 'I':
                self._calculate = self._op_int_to_fp

            # convert float to differently-sized float
            elif self._from_type == 'F' and self._to_type == 'F':
                self._calculate = self._op_fp_to_fp

            elif self._from_type == 'F' and self._to_type == 'I':
                self._calculate = self._op_fp_to_int

            # this concatenates the args into the high and low halves of the result
            elif self._from_side == 'HL':
                l.debug("... using simple concat")
                self._calculate = self._op_concat

            # this just returns the high half of the first arg
            elif self._from_size > self._to_size and self._from_side == 'HI':
                l.debug("... using hi half")
                self._calculate = self._op_hi_half

            # this just returns the high half of the first arg
            elif self._from_size > self._to_size and self._from_side in ('L',
                                                                         'LO'):
                l.debug("... using lo half")
                self._calculate = self._op_lo_half

            elif self._from_size > self._to_size and self._from_side is None:
                l.debug("... just extracting")
                self._calculate = self._op_extract

            elif self._from_size < self._to_size and self.is_signed:
                l.debug("... using simple sign-extend")
                self._calculate = self._op_sign_extend

            elif self._from_size < self._to_size and not self.is_signed:
                l.debug("... using simple zero-extend")
                self._calculate = self._op_zero_extend

            else:
                l.error(
                    "%s is an unexpected conversion operation configuration",
                    self)
                assert False

        # other conversions
        elif self._conversion and self._generic_name != 'Round' and self._generic_name != 'Reinterp':
            if self._generic_name == "DivMod":
                l.debug("... using divmod")
                self._calculate = self._op_divmod
            else:
                unsupported_conversions.append(self.name)
                common_unsupported_generics[self._generic_name] += 1

        # generic bitwise
        elif self._generic_name in bitwise_operation_map:
            l.debug("... using generic mapping op")
            assert self._from_side is None
            self._calculate = self._op_mapped

        # generic mapping operations
        elif self._generic_name in arithmetic_operation_map or self._generic_name in shift_operation_map:
            l.debug("... using generic mapping op")
            assert self._from_side is None

            if self._float and self._vector_zero:
                self._calculate = self._op_float_op_just_low
            elif self._float and self._vector_count is None:
                self._calculate = self._op_float_mapped
            elif not self._float and self._vector_count is not None:
                self._calculate = self._op_vector_mapped
            else:
                self._calculate = self._op_mapped

        # TODO: clean up this mess
        # specifically-implemented generics
        elif self._float and hasattr(self,
                                     '_op_fgeneric_%s' % self._generic_name):
            l.debug("... using generic method")
            calculate = getattr(self, '_op_fgeneric_%s' % self._generic_name)
            if self._vector_size is not None and \
               not hasattr(calculate, 'supports_vector'):
                # unsupported vector ops
                vector_operations.append(name)
            else:
                self._calculate = calculate

        elif not self._float and hasattr(
                self, '_op_generic_%s' % self._generic_name):
            l.debug("... using generic method")
            calculate = getattr(self, '_op_generic_%s' % self._generic_name)
            if self._vector_size is not None and \
               not hasattr(calculate, 'supports_vector'):
                # unsupported vector ops
                vector_operations.append(name)
            else:
                self._calculate = calculate

        else:
            common_unsupported_generics[self._generic_name] += 1
            other_operations.append(name)

        # if we're here and calculate is None, we don't support this
        if self._calculate is None:
            l.debug("... can't support operations")
            raise UnsupportedIROpError(
                "no calculate function identified for %s" % self.name)
Example #2
0
    def __init__(self, name, **attrs):
        l.debug("Creating SimIROp(%s)", name)
        self.name = name
        self.op_attrs = attrs

        self._generic_name = None
        self._from_size = None
        self._from_side = None
        self._from_type = None
        self._from_signed = None
        self._to_size = None
        self._to_type = None
        self._to_signed = None
        self._conversion = None
        self._vector_size = None
        self._vector_signed = None
        self._vector_type = None
        self._vector_zero = None
        self._vector_count = None

        self._rounding_mode = None

        for k,v in self.op_attrs.items():
            if v is not None and ('size' in k or 'count' in k):
                v = int(v)
            setattr(self, '_%s'%k, v)

        # determine the output size
        #pylint:disable=no-member
        self._output_type = pyvex.typeOfIROp(name)
        #pylint:enable=no-member
        self._output_size_bits = size_bits(self._output_type)
        l.debug("... VEX says the output size should be %s", self._output_size_bits)

        size_check = self._to_size is None or (self._to_size*2 if self._generic_name == 'DivMod' else self._to_size) == self._output_size_bits
        if not size_check:
            raise SimOperationError("VEX output size doesn't match detected output size")


        #
        # Some categorization
        #

        generic_names.add(self._generic_name)
        if self._conversion is not None:
            conversions[(self._from_type, self._from_signed, self._to_type, self._to_signed)].append(self)

        if len({self._vector_type, self._from_type, self._to_type} & {'F', 'D'}) != 0:
            # print self.op_attrs
            self._float = True

            if len({self._vector_type, self._from_type, self._to_type} & {'D'}) != 0:
                l.debug('... aborting on BCD!')
                # fp_ops.add(self.name)
                raise UnsupportedIROpError("BCD ops aren't supported")
        else:
            self._float = False

        #
        # Now determine the operation
        #

        self._calculate = None

        # is it explicitly implemented?
        if hasattr(self, '_op_' + name):
            self._calculate = getattr(self, '_op_' + name)
        # if the generic name is None and there's a conversion present, this is a standard
        # widening or narrowing or sign-extension
        elif self._generic_name is None and self._conversion:
            # convert int to float
            if self._float and self._from_type == 'I':
                self._calculate = self._op_int_to_fp

            # convert float to differently-sized float
            elif self._from_type == 'F' and self._to_type == 'F':
                self._calculate = self._op_fp_to_fp

            elif self._from_type == 'F' and self._to_type == 'I':
                self._calculate = self._op_fp_to_int

            # this concatenates the args into the high and low halves of the result
            elif self._from_side == 'HL':
                l.debug("... using simple concat")
                self._calculate = self._op_concat

            # this just returns the high half of the first arg
            elif self._from_size > self._to_size and self._from_side == 'HI':
                l.debug("... using hi half")
                self._calculate = self._op_hi_half

            # this just returns the high half of the first arg
            elif self._from_size > self._to_size and self._from_side in ('L', 'LO'):
                l.debug("... using lo half")
                self._calculate = self._op_lo_half

            elif self._from_size > self._to_size and self._from_side is None:
                l.debug("... just extracting")
                self._calculate = self._op_extract

            elif self._from_size < self._to_size and self.is_signed:
                l.debug("... using simple sign-extend")
                self._calculate = self._op_sign_extend

            elif self._from_size < self._to_size and not self.is_signed:
                l.debug("... using simple zero-extend")
                self._calculate = self._op_zero_extend

            else:
                l.error("%s is an unexpected conversion operation configuration", self)
                assert False

        # other conversions
        elif self._conversion and self._generic_name != 'Round' and self._generic_name != 'Reinterp':
            if self._generic_name == "DivMod":
                l.debug("... using divmod")
                self._calculate = self._op_divmod
            else:
                unsupported_conversions.append(self.name)
                common_unsupported_generics[self._generic_name] += 1

        # generic bitwise
        elif self._generic_name in bitwise_operation_map:
            l.debug("... using generic mapping op")
            assert self._from_side is None
            self._calculate = self._op_mapped

        # generic mapping operations
        elif self._generic_name in arithmetic_operation_map or self._generic_name in shift_operation_map:
            l.debug("... using generic mapping op")
            assert self._from_side is None

            if self._float and self._vector_zero:
                self._calculate = self._op_float_op_just_low
            elif self._float and self._vector_count is None:
                self._calculate = self._op_float_mapped
            elif not self._float and self._vector_count is not None:
                self._calculate = self._op_vector_mapped
            else:
                self._calculate = self._op_mapped

        # TODO: clean up this mess
        # specifically-implemented generics
        elif self._float and hasattr(self, '_op_fgeneric_%s' % self._generic_name):
            l.debug("... using generic method")
            calculate = getattr(self, '_op_fgeneric_%s' % self._generic_name)
            if self._vector_size is not None and \
               not hasattr(calculate, 'supports_vector'):
                # unsupported vector ops
                vector_operations.append(name)
            else:
                self._calculate = calculate

        elif not self._float and hasattr(self, '_op_generic_%s' % self._generic_name):
            l.debug("... using generic method")
            calculate = getattr(self, '_op_generic_%s' % self._generic_name)
            if self._vector_size is not None and \
               not hasattr(calculate, 'supports_vector'):
                # unsupported vector ops
                vector_operations.append(name)
            else:
                self._calculate = calculate

        else:
            common_unsupported_generics[self._generic_name] += 1
            other_operations.append(name)


        # if we're here and calculate is None, we don't support this
        if self._calculate is None:
            l.debug("... can't support operations")
            raise UnsupportedIROpError("no calculate function identified for %s" % self.name)