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)
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)