Exemplo n.º 1
0
    def gen_find_fos(self, fname):  # L2 phash
        obj_str = self.cdict.strings_dict['obj_str']
        obj_type = self.cdict.strings_dict['obj_type']
        const = self.cdict.strings_dict['obj_const']
        hx2fo = {}
        for hx, phash in list(self.hx2phash.items()):
            fid = '%s_%d_l1' % (fname, hx)
            (hx2fo_list, operand_lu_fo) = phash.gen_find_fos(fid)
            if not operand_lu_fo:
                genutil.die("L2 hash cannot have trivial operand lu fn")
            hx2fo[hx] = hx2fo_list[0]

        fname = '%s' % fname
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            return_type = 'xed_uint32_t'
        else:
            return_type = self.cdict.action_codegen.get_return_type()

        static = self.cdict.strings_dict['static']
        fo = codegen.function_object_t(fname,
                                       return_type=return_type,
                                       static=static,
                                       inline=False)
        fo.add_arg('%s%s* %s' % (const, obj_type, obj_str))
        self.add_lu_table(fo, hx2fo)
        #we only need to override add_lookup_lines
        lu_fname = operand_lu_fo.function_name
        self.add_op_lu_function(fo, lu_fname)
        self.add_find_lines(fo)
        fos = list(hx2fo.values())
        fos.append(fo)
        #all the operand_lu_fo going to be the same so we just take the last one
        return fos, operand_lu_fo
Exemplo n.º 2
0
    def add_lookup_lines(self, fo):

        key_validation = self.hash_f.add_key_validation(
            self.cdict.strings_dict)
        fo.add_code('%s {' % key_validation)

        actions = self.cdict.action_codegen.emit_actions()
        for a in actions:
            fo.add_code_eol("    " + a)
        if self.cdict.action_codegen.has_fcall():
            fo.add_code_eol("    return res")
        #FIXME: this is a temporary, when we will implement the iform encoding
        # we will be able to remove this code
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            fo.add_code_eol("    return 1")
        fo.add_code('}')

        # get the default action that will executed when we did not hit valid
        # look up table entry
        default = self.cdict.action_codegen.emit_default()
        fo.add_code('else{')
        for line in default:
            fo.add_code_eol("    %s" % line)

        fo.add_code('}')
Exemplo n.º 3
0
    def gen_find_fos(self, fname):
        obj_str = self.cdict.strings_dict['obj_str']
        obj_type = self.cdict.strings_dict['obj_type']
        key_str= self.cdict.strings_dict['key_str']
        hidx_str = self.cdict.strings_dict['hidx_str']
        const = self.cdict.strings_dict['obj_const']
        lu_namespace = self.cdict.strings_dict['lu_namespace']
        
        #FIXME: this is a temporary, when we will implement the iform encoding
        # we will be able to remove this code
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            return_type = 'xed_uint32_t'
        else:
            return_type = self.cdict.action_codegen.get_return_type()
        static = self.cdict.strings_dict['static']
        fo = codegen.function_object_t(fname,
                                       return_type=return_type,
                                       static=static,
                                       inline=False)

        lu_operands = '_'.join(self.cdict.cnames)
        lu_operands_fn = 'xed_lu_%s' % lu_operands 
        key_ctype = self.cdict.strings_dict['key_type']
        operand_lu_fo = codegen.function_object_t(lu_operands_fn,
                                       return_type=key_ctype,
                                       static=False,
                                       inline=False,
                                       force_no_inline=True)
        ild_arg = "%s%s* %s" % (const,obj_type, obj_str)
        fo.add_arg(ild_arg)
        if genutil.field_check(self.cdict, 'ntluf'):
            fo.add_arg('xed_reg_enum_t arg_reg')
        operand_lu_fo.add_arg(ild_arg)
        #add key-computing code (constraints tuple to integer)
        nt_lups = self.add_cgen_key_lines(operand_lu_fo)
        #several non terminals has special getter functions
        #the add-cgen_kiet function returns a list of all the nt_lups and 
        #regular cnames  
        lu_operands_fn = 'xed_%s_lu_%s' % (lu_namespace,'_'.join(nt_lups))
        operand_lu_fo.set_function_name(lu_operands_fn)
        
        #add the operands lookup function
        self.add_lu_table(fo)
        self.add_op_lu_function(fo,lu_operands_fn)
        self.add_find_lines(fo)
        
        return ([fo],operand_lu_fo)
Exemplo n.º 4
0
    def add_lu_type(self, fo):
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            ret_type = 'xed_uint32_t'
        else:
            ret_type = self.cdict.action_codegen.get_return_type()
        fname = self.cdict.strings_dict['luf_name']
        param_name = "%s%s*" % (self.cdict.strings_dict['obj_const'],
                                self.cdict.strings_dict['obj_type'])
        luf_type = "typedef %s (*%s)(%s)" % (ret_type, fname, param_name)
        fo.add_code_eol(luf_type)

        lu_entry = self.cdict.strings_dict['lu_entry']
        entry_desc = 'typedef struct {xed_uint32_t key;'
        entry_desc += ' %s l2_func;} %s' % (fname, lu_entry)
        fo.add_code_eol(entry_desc)
Exemplo n.º 5
0
def _is_amd3dnow(agi):
    for g in agi.generator_list:
        ii = g.parser_output.instructions[0]
        if genutil.field_check(ii, 'iclass'):
            for ii in g.parser_output.instructions:
                if ii.category == _xed_3dnow_category:
                    return True
    return False
Exemplo n.º 6
0
def _get_nested_nts(agi):
    nested_nts = set()
    for nt_name in agi.nonterminal_dict.keys():
        g = agi.generator_dict[nt_name]
        ii = g.parser_output.instructions[0]
        if genutil.field_check(ii,'iclass'):
            continue #only real NTs, not instructions
        for rule in g.parser_output.instructions:
            for bt in rule.ipattern.bits:
                if bt.is_nonterminal():
                    nested_nts.add(nt_name)
            for op in rule.operands:
                if op.type == 'nt_lookup_fn':
                    nested_nts.add(nt_name)
    return nested_nts
Exemplo n.º 7
0
def get_patterns(agi, is_3dnow, eosz_nts, easz_nts, imm_nts, disp_nts,
                 brdisp_nts, all_state_space):
    """
    This function generates the pattern_t objects that have all the necessary
    information for the ILD. Returns these objects as a list.
    """
    patterns = []
    for g in agi.generator_list:
        ii = g.parser_output.instructions[0]
        if genutil.field_check(ii, 'iclass'):
            for ii in g.parser_output.instructions:
                ptrn = pattern_t(ii, is_3dnow, eosz_nts, easz_nts, imm_nts,
                                 disp_nts, brdisp_nts, ildutil.mode_space,
                                 all_state_space)
                patterns.append(ptrn)
                if ptrn.incomplete_opcode:
                    expanded_ptrns = ptrn.expand_opcode()
                    patterns.extend(expanded_ptrns)
    return patterns
Exemplo n.º 8
0
def get_all_constraints_state_space(agi):
    """Returns a 2D dictionary state_space.

    state_space[OPNAME][OPVAL] == True if there is an operand with
    name OPNAME and value OPVAL.

    The dictionary contains all legal values for operands in grammar.

    Only operands that appear as operand deciders, prebindings, or
    instruction operands are added to the returned dictionary.    """
    
    state_space = collections.defaultdict(dict)
    for g in agi.generator_list:
        for ii in g.parser_output.instructions:
            _set_state_space_from_ii(agi, ii, state_space)
    #set state_space from operands
    #These are NTs partition tables right parts
    for g in agi.generator_list:
        ii = g.parser_output.instructions[0]
        if genutil.field_check(ii,'iclass'):
            continue #only real NTs, not instructions
        for ii in g.parser_output.instructions:
            _set_space_from_operands(agi, ii.operands, state_space)

    # in some configurations xed can be build without any AVX
    # instructions, in this case the operand VEXVALID will no be added.
    # the ild relies on this operand so we add it manually
    if 'VEXVALID' not in state_space:
        state_space['VEXVALID'][0] = True 
    else: # KNC/AVX/EVEX builds...
        # 2014-10-10: when I got rid of the NTs for decoding the
        # VEX/EVEX/XOP prefixes, I ended up losing the only NTs that
        # mention ZEROING=1 and VLBAD (VL=3). So we add them here.
        # They are required for proper splattering of don't care
        # cases.  in the hash function generation.  For example when,
        # EVEX.RC is rounding control and co-opting the EVEX.LL field,
        # we need to have the value of VL=3 because it is not
        # "corrected" when we are still picking an instruction (aka
        # 'static decode').
        state_space['ZEROING'][1] = True 
        state_space['VL'][3] = True 

    return state_space
Exemplo n.º 9
0
    def add_op_lu_function(self, fo, lu_function):
        if hasattr(self.hash_f, 'emit_cvar_decl'):
            fo.add_code_eol(self.hash_f.emit_cvar_decl())

        fo.add_code_eol('%s %s = 0' % (self.cdict.strings_dict['key_type'],
                                       self.cdict.strings_dict['key_str']))
        fo.add_code_eol('%s %s = 0' % (self.cdict.strings_dict['hidx_type'],
                                       self.cdict.strings_dict['hidx_str']))

        #Initializing res to 1 since it will not always be read.
        if self.cdict.action_codegen.has_fcall():
            fo.add_code_eol('%s %s = 1' %
                            (self.cdict.strings_dict['hidx_type'], 'res'))
        obj_str = self.cdict.strings_dict['obj_str']
        #FIXME: this is a temporary, when we will implement the iform encoding
        # we will be able to remove this code
        if genutil.field_check(self.cdict, 'ntluf'):
            fo.add_code_eol('xed3_operand_set_outreg(%s,arg_reg)' % obj_str)

        lu_code = 'key = %s(%s)' % (lu_function, obj_str)
        fo.add_code_eol(lu_code)
Exemplo n.º 10
0
def get_patterns(agi, eosz_nts, easz_nts,
                 imm_nts, disp_nts, brdisp_nts, all_state_space):
    """
    This function generates the pattern_t objects that have all the necessary
    information for the ILD. Returns these objects as a list.
    """
    machine_modes = agi.common.get_state_space_values('MODE')
    patterns = []
    pattern_t.map_info_g = agi.map_info
    for g in agi.generator_list:
        ii = g.parser_output.instructions[0]
        if genutil.field_check(ii,'iclass'):
            for ii in g.parser_output.instructions:
                ptrn = pattern_t(ii, eosz_nts,
                                 easz_nts, imm_nts, disp_nts, brdisp_nts,
                                 machine_modes, all_state_space)
                patterns.append(ptrn)
                if ptrn.incomplete_opcode:
                    expanded_ptrns = ptrn.expand_partial_opcode()
                    patterns.extend(expanded_ptrns)
    return patterns
Exemplo n.º 11
0
def work(agi):
    sse_isa_sets = set([])
    avx_isa_sets = set([])
    avx512_isa_sets = set([])
    avx512_kmask_op = set([])
    for generator in agi.generator_list:
        for ii in generator.parser_output.instructions:
            if genutil.field_check(ii, 'iclass'):
                if re.search('AVX512', ii.isa_set):
                    avx512_isa_sets.add(ii.isa_set)
                    if re.search('KOP', ii.isa_set):
                        avx512_kmask_op.add(ii.isa_set)
                elif re.search('AVX',
                               ii.isa_set) or ii.isa_set in ['F16C', 'FMA']:
                    avx_isa_sets.add(ii.isa_set)
                elif re.search('SSE', ii.isa_set) or ii.isa_set in [
                        'AES', 'PCLMULQDQ'
                ]:
                    # Exclude MMX instructions that come in with SSE2 &
                    # SSSE3. The several purely MMX instr in SSE are
                    # "SSE-opcodes" with memop operands. One can look for
                    # those with SSE2MMX and SSSE3MMX xed isa_sets.
                    #
                    # Also exclude the SSE_PREFETCH operations; Those are
                    # just memops.
                    if (not re.search('MMX', ii.isa_set)
                            and not re.search('PREFETCH', ii.isa_set)
                            and not re.search('X87', ii.isa_set)
                            and not re.search('MWAIT', ii.isa_set)):
                        sse_isa_sets.add(ii.isa_set)

    fe = agi.open_file('xed-classifiers.c')  # xed_file_emitter_t
    _emit_function(fe, avx512_isa_sets, 'avx512')
    _emit_function(fe, avx512_kmask_op, 'avx512_maskop')
    _emit_function(fe, avx_isa_sets, 'avx')
    _emit_function(fe, sse_isa_sets, 'sse')
    fe.close()
    return
Exemplo n.º 12
0
    def gen_find_fos(self, fname):  # phash_t
        obj_str = self.cdict.strings_dict['obj_str']
        obj_type = self.cdict.strings_dict['obj_type']
        key_str = self.cdict.strings_dict['key_str']
        hidx_str = self.cdict.strings_dict['hidx_str']
        const = self.cdict.strings_dict['obj_const']
        lu_namespace = self.cdict.strings_dict['lu_namespace']

        #FIXME: this is a temporary, when we will implement the iform encoding
        # we will be able to remove this code
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            return_type = 'xed_uint32_t'
        elif self.hash_f.kind() == 'trivial':
            return_type = 'xed_uint32_t'
        else:
            return_type = self.cdict.action_codegen.get_return_type()
        static = self.cdict.strings_dict['static']
        fo = codegen.function_object_t(fname,
                                       return_type=return_type,
                                       static=static,
                                       inline=False)

        lu_operands = '_'.join(self.cdict.cnames)
        # temporary function name. we override this later
        lu_operands_fn = 'xed_lu_%s' % lu_operands
        key_ctype = self.cdict.strings_dict['key_type']

        ild_arg = "%s%s* %s" % (const, obj_type, obj_str)
        fo.add_arg(ild_arg)

        if self.hash_f.kind() == 'trivial':
            operand_lu_fo = None
            # rule is a pattern_t
            fo.add_code_eol("return {}".format(self.cdict.rule.ii.inum))
            # avoid parmameter-not-used warnings with compilers that
            # care (like MSVS)
            fo.add_code_eol("(void)d")
        else:
            operand_lu_fo = codegen.function_object_t(lu_operands_fn,
                                                      return_type=key_ctype,
                                                      static=False,
                                                      inline=False,
                                                      force_no_inline=True)
            operand_lu_fo.add_arg(ild_arg)
            if genutil.field_check(self.cdict, 'ntluf'):
                fo.add_arg('xed_reg_enum_t arg_reg')

            #add key-computing code (constraints tuple to integer)
            nt_lups = self.add_cgen_key_lines(operand_lu_fo)
            #Several nonterminals have special getter functions.  The
            #add_cgen_key_lines function returns a list of all the
            #nt_lups and regular cnames.  (lu_operands is not always
            #the same as the underscore-joined nt_lups.)
            lu_operands_fn = 'xed_%s_lu_%s' % (lu_namespace, '_'.join(nt_lups))
            operand_lu_fo.set_function_name(lu_operands_fn)

            #add the operands lookup function
            self.add_lu_table(fo)
            self.add_op_lu_function(fo, lu_operands_fn)
            self.add_find_lines(fo)

        return ([fo], operand_lu_fo)