示例#1
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)
示例#2
0
def _gen_capture_chain_fo(nt_names, fname=None):
    """
    Given a list of NT names, generate a function object (function_object_t)
    that calls corresponding xed3 NT capturing functions.
    Each such function captures everything that xed2 decode graph would
    capture for a given pattern with NTs (nt_names) in it.
    """
    if not fname:
        fname = _get_xed3_capture_chain_fn(nt_names)
    inst = 'd'
    fo = codegen.function_object_t(fname,
                                   return_type=_xed3_chain_return_t,
                                   static=True,
                                   inline=True)
    fo.add_arg(ildutil.xed3_decoded_inst_t + '* %s' % inst)

    for name in nt_names:
        capture_fn = _get_xed3_nt_capture_fn(name)
        capture_stmt = '%s(%s)' % (capture_fn, inst)
        fo.add_code_eol(capture_stmt)
        #now check if we have errors in current NT
        getter_fn = operand_storage.get_op_getter_fn(_xed3_err_op)
        errval = '%s(%s)' % (getter_fn, inst)
        fo.add_code('if (%s) {' % errval)
        fo.add_code_eol('return %s' % errval)
        fo.add_code('}')

    fo.add_code_eol('return %s' % _xed_no_err_val)
    return fo
示例#3
0
def gen_derived_operand_getter(agi, opname, op_arr, op_nt_names):
    return_type = agi.operand_storage.get_ctype(opname)

    op_lufn = ild_nt.get_lufn(op_nt_names, opname)
    getter_fn = get_derived_op_getter_fn(op_nt_names, opname)

    fo = codegen.function_object_t(getter_fn,
                                   return_type,
                                   static=True,
                                   inline=True)
    data_name = 'x'
    fo.add_arg('const ' + ildutil.ild_c_type + ' %s' % data_name)

    for range_tuple in op_arr.ranges:
        range_type, range_min, range_max, paramname = range_tuple
        param_name = '_%s' % paramname.lower()
        fo.add_code_eol(ildutil.ild_c_op_type + ' %s' % param_name)

    params = []
    for range_tuple in op_arr.ranges:
        range_type, range_min, range_max, paramname = range_tuple
        param_name = '_%s' % paramname.lower()
        access_call = emit_ild_access_call(paramname, data_name)

        fo.add_code_eol('%s = (%s)%s' %
                        (param_name, ildutil.ild_c_op_type, access_call))
        params.append(param_name)

    lu_fn = op_arr.lookup_fn.function_name

    lu_call = lu_fn + '(%s)'
    lu_call = lu_call % (', '.join(params))
    fo.add_code_eol('return %s' % lu_call)
    return fo
示例#4
0
def gen_init_function(arr_list, name):
    #make a function_object_t to call all the individual init routines
    overall_init_f = codegen.function_object_t(name, return_type='void')
    for array in arr_list:
        if not array.is_const_lookup_fun():
            overall_init_f.add_code_eol(array.init_fn.function_name + '()')
    return overall_init_f
示例#5
0
文件: ild_phash.py 项目: xelxebar/xed
    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
示例#6
0
    def _gen_generic_getter(self):
        ''' for xed's internal usage (printing) we need to be able to 
            get an operand based on its index.
            generating here a switch/case over the operand index to call the 
            correct getter function '''
        inst = 'd'
        fname = 'xed3_get_generic_operand'
        ret_arg = 'ret_arg'

        fo = codegen.function_object_t(fname,
                                       return_type='void',
                                       static=False,
                                       inline=False,
                                       dll_export=True)
        fo.add_arg('const xed_decoded_inst_t* %s' % inst)
        fo.add_arg('xed_operand_enum_t operand')
        fo.add_arg('void* %s' % ret_arg)

        switch_gen = codegen.c_switch_generator_t('operand', fo)
        op_names = sorted(self.operand_fields.keys())
        for op in op_names:
            switch_key = "XED_OPERAND_%s" % op
            ctype = self.get_ctype(op)
            func_getter = "%s(d)" % get_op_getter_fn(op)
            code = "*((%s*)%s)=%s;" % (ctype, ret_arg, func_getter)
            switch_gen.add_case(switch_key, [code])
        switch_gen.add_default(['xed_assert(0);'])
        switch_gen.finish()
        return fo
示例#7
0
    def _gen_generic_setter(self):
        ''' generating a switch/case over the operand index to call the 
            correct setter function '''
        inst = 'd'
        fname = 'xed3_set_generic_operand'
        in_value = 'val'

        fo = codegen.function_object_t(fname,
                                       return_type='void',
                                       static=False,
                                       inline=False,
                                       dll_export=True)
        fo.add_arg('xed_decoded_inst_t* %s' % inst)
        fo.add_arg('xed_operand_enum_t operand')
        fo.add_arg('xed_uint32_t %s' % in_value)

        switch_gen = codegen.c_switch_generator_t('operand', fo)
        op_names = sorted(self.operand_fields.keys())
        for op in op_names:
            switch_key = "XED_OPERAND_%s" % op
            ctype = self.get_ctype(op)
            func_setter = get_op_setter_fn(op)
            code = "%s(%s,(%s)%s);" % (func_setter, inst, ctype, in_value)
            switch_gen.add_case(switch_key, [code])
        switch_gen.add_default(['xed_assert(0);'])
        switch_gen.finish()
        return fo
示例#8
0
文件: ins_emit.py 项目: zachlungu/xed
    def _make_fb_setter_fo(self, iform, i):
        ''' create the function object for pattern of fields bindings 
             
            @param iform: iform_t object 
            @param i: index of the pattern function
            @return: function_object_t 
        '''

        fname = "%s_%d" % (bind_function_prefix, i)
        fo = codegen.function_object_t(fname, return_type='void')

        obj_name = encutil.enc_strings['obj_str']
        enc_arg = "%s* %s" % (encutil.enc_strings['obj_type'], obj_name)
        fo.add_arg(enc_arg)

        if not iform.fbs:
            #no field binding we need to set, pacify the compiler
            fo.add_code_eol('(void)%s' % obj_name)
            return fo

        fo.add_code_eol('    const xed_uint8_t* val')
        fo.add_code_eol('    val = %s(%s)' % (get_field_value, obj_name))
        for i, fb_action in enumerate(iform.fbs):
            value_from_lu_table = '*(val+%d)' % i
            operand_setter = "%s_set_%s" % (encutil.enc_strings['op_accessor'],
                                            fb_action.field_name.lower())
            code = '    %s(%s,%s);' % (operand_setter, obj_name,
                                       value_from_lu_table)
            fo.add_code(code)

        return fo
示例#9
0
def gen_l1_bymode_resolution_function(agi, info_list, nt_dict, is_conflict_fun,
                                      gen_l2_fn_fun, fn_suffix):
    if len(info_list) < 1:
        ildutil.ild_warn("Trying to resolve conflict for empty info_list")
        return None
    insn_map = info_list[0].insn_map
    opcode = info_list[0].opcode
    ildutil.ild_warn('generating by mode fun_dict for opcode %s map %s' %
                     (opcode, insn_map))
    machine_modes = agi.common.get_state_space_values('MODE')
    fun_dict = _gen_bymode_fun_dict(machine_modes, info_list, nt_dict,
                                    is_conflict_fun, gen_l2_fn_fun)
    if not fun_dict:
        #it is not ild_err because we might have other conflict resolution
        #functions to try.
        #In general we have a list of different conflict resolution functions
        #that we iterate over and try to resolve the conflict
        ildutil.ild_warn('Failed to generate by mode fun_dict for opcode ' +
                         '%s map %s' % (opcode, insn_map))
        return None

    #if not all modrm.reg values have legal instructions defined, we don't
    #have full 0-7 dict for modrm.reg here, and we can't generate the interval
    #dict
    if len(list(fun_dict.keys())) == len(machine_modes):
        int_dict = _gen_intervals_dict(fun_dict)
    else:
        int_dict = None

    lufn = ild_nt.gen_lu_names(['RESOLVE_BYMODE'], fn_suffix)[2]
    lufn += '_map%s_op%s_l1' % (insn_map, opcode)
    operand_storage = agi.operand_storage
    return_type = 'void'
    fo = codegen.function_object_t(lufn, return_type, static=True, inline=True)
    data_name = 'x'
    fo.add_arg(ildutil.ild_c_type + ' %s' % data_name)

    mode_type = ildutil.ild_c_op_type
    mode_var = '_mode'
    fo.add_code_eol(mode_type + ' %s' % mode_var)
    #get MODE value
    access_call = emit_ild_access_call("MODE", data_name)
    if not access_call:
        return None

    fo.add_code_eol('%s = (%s)%s' % (mode_var, mode_type, access_call))

    #now emit the resolution code, that checks condtions from dict
    #(in this case the MODE value)
    #and calls appropriate L2 function for each condition

    #if we have an interval dict, we can emit several if statements
    if int_dict:
        _add_int_dict_dispatching(fo, int_dict, mode_var, data_name)
    #if we don't have interval dict, we emit switch statement
    else:
        _add_switch_dispatching(fo, fun_dict, mode_var, data_name)

    return fo
示例#10
0
def work(lines,   xeddir = '.',   gendir = 'obj'):
   tables = []
   _read_constant_tables(lines,tables)

       
   tables=list(filter(lambda x: x.valid() , tables))
   names= [  x.name  for x in  tables ]

   srcs = emit_convert_enum(['INVALID'] + names, xeddir, gendir)
   src_file_name = 'xed-convert-table-init.c'
   hdr_file_name = 'xed-convert-table-init.h'
   xfe = codegen.xed_file_emitter_t(xeddir, gendir, src_file_name)
   xfe.add_header(hdr_file_name)
   xfe.start()

   hfe = codegen.xed_file_emitter_t(xeddir,
                                    gendir,
                                    hdr_file_name)
   hfe.start()

   xfe.add_code('xed_convert_table_t xed_convert_table[XED_OPERAND_CONVERT_LAST];')
   
   for t in tables:
       l = t.emit_init()
       l = [  x+'\n' for x in  l]
       xfe.writelines(l)
   fo = codegen.function_object_t('xed_init_convert_tables', 'void')
   
   s1 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].table_name = %s;' % ('INVALID', '0')
   s2 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].limit      = %s;' % ('INVALID', '0')
   s3 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].opnd       = %s;' % ('INVALID', 'XED_OPERAND_INVALID')
   fo.add_code(s1)
   fo.add_code(s2)
   fo.add_code(s3)
   
   for t in tables:
       s1 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].table_name = %s;' % (t.name, t.string_table_name)
       s2 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].limit      = %s;' % (t.name, len(t.value_string_pairs))
       s3 = 'xed_convert_table[XED_OPERAND_CONVERT_%s].opnd       = %s;' % (t.name, t.operand)
       fo.add_code(s1)
       fo.add_code(s2)
       fo.add_code(s3)

   fo.emit_file_emitter(xfe)
   xfe.close()

   hdr = []
   hdr.append("typedef struct {\n")
   hdr.append("   const char** table_name;\n")
   hdr.append("   xed_operand_enum_t opnd;\n") # which operand indexes the table!
   hdr.append("   unsigned int limit;\n")
   hdr.append("} xed_convert_table_t;")
   hdr.append("extern xed_convert_table_t xed_convert_table[XED_OPERAND_CONVERT_LAST];")
   hfe.writelines( [  x+'\n' for x in hdr] )
   hfe.close()

   srcs.append(hfe.full_file_name)
   srcs.append(xfe.full_file_name)
   return srcs
示例#11
0
def _make_test_function_object(env, enc_fn):
    encoder_fn = enc_fn.get_function_name()
    versions = env.test_function_names[encoder_fn]
    fname = 'test_{}_{}'.format(versions, encoder_fn)
    if env.test_checked_interface:
        fname = '{}_chk'.format(fname)
    env.test_function_names[encoder_fn] += 1

    fo = codegen.function_object_t(fname, return_type='xed_uint32_t')
    return fo
示例#12
0
    def _make_emit_fo(self, iform, i):
        ''' create the function object for this emit pattern
             
            @param iform: iform_t object
            @param i: index of the pattern function
            @return: function_object_t 
        '''

        fname = "%s_%d" % (emit_function_prefix, i)
        fo = codegen.function_object_t(fname, return_type='void')

        # obj_str is the function parameters for the emit function
        obj_str = encutil.enc_strings['obj_str']
        enc_arg = "%s* %s" % (encutil.enc_strings['obj_type'], obj_str)
        fo.add_arg(enc_arg)

        for action in iform.rule.actions:
            # MASSIVE HACK: we store the legacy_map as MAP0 in
            # xed_encode_iform_db[] (obj/xed-encoder-iforms-init.c)
            # for VEX/EVEX/XOP instr (see
            # _identify_map_and_nominal_opcode() ) to avoid emitting
            # any escape/map bytes at runtime.
            if action.field_name == 'MAP':
                if iform.encspace == 0:  # legacy
                    genutil.die("Should not see MAP here: {}".format(
                        iform.iclass))
                pass
            elif action.field_name and action.field_name in [
                    'LEGACY_MAP1', 'LEGACY_MAP2', 'LEGACY_MAP3',
                    'LEGACY_MAP3DNOW'
            ]:
                if iform.encspace != 0:  # legacy
                    genutil.die("This should only occur for legacy instr")
                self._emit_legacy_map(fo, iform)

            elif action.field_name and action.field_name == 'NOM_OPCODE':
                code = ''
                get_opcode = 'xed_encoder_get_nominal_opcode(%s)' % obj_str
                if action.nbits == 8:
                    emit_func = 'xed_encoder_request_emit_bytes'
                else:
                    emit_func = 'xed_encoder_request_encode_emit'
                code = ' ' * 4
                code += '%s(%s,%d,%s)' % (emit_func, obj_str, action.nbits,
                                          get_opcode)
                fo.add_code_eol(code)
            else:
                code = action.emit_code('EMIT')
                for c in code:
                    fo.add_code(c)

        return fo
示例#13
0
 def _gen_op_getter_fo(self, opname):
     ''' generate the function object for the getter accessors
         adding cast to the C type according to the data files(ctype)'''
     inst = 'd'
     fname = get_op_getter_fn(opname)
     ret_type = self.get_ctype(opname)
     fo = codegen.function_object_t(fname,
                                    return_type=ret_type,
                                    static=True,
                                    inline=True)
     fo.add_arg('const xed_decoded_inst_t* %s' % inst)
     op = opname.lower()
     fo.add_code_eol('return (%s)%s->_operands.%s' % (ret_type, inst, op))
     return fo
示例#14
0
def gen_scalable_l2_function(agi, nt_name, target_opname,
                             ild_t_member,
                             arg_arr, arg_nt_names):
    return_type = 'void'
    l3_fn = ild_nt.get_lufn([nt_name], target_opname, flevel='l3')
    arg_name = arg_arr.get_target_opname()
    l2_fn = get_l2_fn([nt_name], target_opname, arg_nt_names, arg_name,
              None, False)

    fo = codegen.function_object_t(l2_fn, return_type,
                                       static=True, inline=True)
    data_name = 'x'
    fo.add_arg(ildutil.ild_c_type + ' %s' % data_name)
    arg_type = agi.operand_storage.get_ctype(arg_name)
    arg_var = '_%s' % arg_name.lower()
    fo.add_code_eol('%s %s' % (arg_type, arg_var))

    temp_var = '_%s' % ild_t_member
    ctype = ildutil.ild_c_op_type
    fo.add_code_eol('%s %s' % (ctype, temp_var))



    for range_tuple in arg_arr.ranges:
        range_type, range_min, range_max, paramname = range_tuple
        param_name = '_%s' % paramname.lower()
        fo.add_code_eol(ildutil.ild_c_op_type + ' %s' % param_name)

    params = []
    for range_tuple in arg_arr.ranges:
        range_type, range_min, range_max, paramname = range_tuple
        param_name = '_%s' % paramname.lower()
        access_call = emit_ild_access_call(paramname, data_name)

        fo.add_code_eol('%s = (%s)%s' %(param_name, ildutil.ild_c_op_type,
                                        access_call))
        params.append(param_name)

    arg_fn = arg_arr.lookup_fn.function_name

    arg_call = arg_fn + '(%s)'
    arg_call = arg_call % (', '.join(params))
    fo.add_code_eol('%s = %s' % (arg_var, arg_call))

    fcall = '%s(%s)' % (l3_fn, arg_var)

    fo.add_code_eol('%s = (%s)%s' % (temp_var, ctype, fcall))
    setter_fn = operand_storage.get_op_setter_fn(ild_t_member)
    fo.add_code_eol('%s(%s, %s)' % (setter_fn, data_name,temp_var))
    return fo
示例#15
0
    def _make_emit_fo(self, iform, i):
        ''' create the function object for this emit pattern
             
            @param iform: iform_t object
            @param i: index of the pattern function
            @return: function_object_t 
        '''
        
        fname = "%s_%d" % (emit_function_prefix,i)
        fo = codegen.function_object_t(fname,
                                       return_type='void')
        
        # obj_str is the function parameters for the emit function
        obj_str = encutil.enc_strings['obj_str']
        enc_arg = "%s* %s" % (encutil.enc_strings['obj_type'],
                              obj_str)
        fo.add_arg(enc_arg)
      
        for action in iform.rule.actions:
            # MASSIVE HACK: we store the legacy_map as MAP0 in
            # xed_encode_iform_db[] (obj/xed-encoder-iforms-init.c)
            # for VEX/EVEX/XOP instr (see
            # _identify_map_and_nominal_opcode() ) to avoid emitting
            # any escape/map bytes at runtime.

            # FIXME: We could avoid ths call to emit legacy map for
            # non-legacy stuff and speed up encoder slightly.
            if action.field_name and action.field_name == 'MAP':
                emit_map = 'xed_encoder_request_emit_legacy_map'
                code = "    %s(%s)" % (emit_map,obj_str)
                fo.add_code_eol(code)
                    
            elif action.field_name and action.field_name == 'NOM_OPCODE':
                code = ''
                get_opcode = 'xed_encoder_get_nominal_opcode(%s)' % obj_str
                if action.nbits == 8:
                    emit_func = 'xed_encoder_request_emit_bytes'
                else:
                    emit_func = 'xed_encoder_request_encode_emit'
                code = ' '*4
                code += '%s(%s,%d,%s)' % (emit_func,obj_str,
                                          action.nbits,get_opcode) 
                fo.add_code_eol(code)     
            else:
                code = action.emit_code('EMIT')
                for c in code:
                    fo.add_code(c)
        
        return fo     
示例#16
0
def _gen_imm0_function(agi):
    """
    for patterns that don't set IMM_WIDTH token
    these patterns have has_im==0
    and we define a L2 lookup function that returns 0
    """
    #return_type = operand_storage.get_ctype(_imm_token)
    return_type = 'void'
    fo = codegen.function_object_t(_imm0_fn, return_type,
                                       static=True, inline=True)
    data_name = 'x'
    fo.add_arg(ildutil.ild_c_type + ' %s' % data_name)
    setter_fn = operand_storage.get_op_setter_fn(_ild_t_imm_member)
    fo.add_code_eol('%s(%s, %s)' % (setter_fn, data_name,'0'))
    return fo
示例#17
0
 def _gen_op_setter_fo(self, opname):
     ''' generate the function object for the setter accessors
         adding cast to the C type according to the data files(ctype)'''
     inst = 'd'
     opval = 'opval'
     fname = get_op_setter_fn(opname)
     fo = codegen.function_object_t(fname,
                                    return_type='void',
                                    static=True,
                                    inline=True)
     fo.add_arg('xed_decoded_inst_t* %s' % inst)
     fo.add_arg('%s %s' % (self.get_ctype(opname), opval))
     op = opname.lower()
     type = self.get_storage_type(opname)
     fo.add_code_eol('%s->_operands.%s = (%s)%s' % (inst, op, type, opval))
     return fo
示例#18
0
def _emit_function(fe, isa_sets, name):
    fo = codegen.function_object_t('xed_classify_{}'.format(name))
    fo.add_arg('const xed_decoded_inst_t* d')
    fo.add_code_eol(
        '    const xed_isa_set_enum_t isa_set = xed_decoded_inst_get_isa_set(d)'
    )
    # FIXME: 2017-07-14 optimization: could use a static array for faster checking, smaller code
    switch = codegen.c_switch_generator_t('isa_set', fo)
    for c in isa_sets:
        switch.add_case('XED_ISA_SET_{}'.format(c.upper()), [], do_break=False)
    if len(isa_sets) > 0:
        switch.add('return 1;')
    switch.add_default(['return 0;'], do_break=False)
    switch.finish()

    fo.emit_file_emitter(fe)
示例#19
0
def _gen_ntluf_capture_chain_fo(nt_names, ii):
    """
    Given a list of OP_NAME_NT_NAME strings(nt_names), generate a function 
    object (function_object_t)
    that calls corresponding xed3 NT capturing functions.
    Each such function captures everything that xed2 decode graph would
    capture for a given pattern with operands that have nt_lokkupfns.
    The difference between this function and  _gen_capture_chain_fo
    is that this function creates chain capturing functions for
    operand decoding - assigns the REG[0,1] operands, etc.
    """
    fname = get_xed3_capture_chain_fn(nt_names, is_ntluf=True)
    inst = 'd'
    fo = fo = codegen.function_object_t(fname,
                                       return_type=_xed3_chain_return_t, 
                                       static=True, 
                                       inline=True)
    fo.add_arg(ildutil.xed3_decoded_inst_t + '* %s' % inst)
    
    for op in ii.operands:
        if op.type == 'nt_lookup_fn':
            nt_name = op.lookupfn_name
            capture_fn = get_xed3_nt_capture_fn(nt_name)
            capture_stmt = '%s(%s)' % (capture_fn, inst)
            fo.add_code_eol(capture_stmt)
            #if we have NTLUF functions, we need to assign OUTREG
            getter_fn = operand_storage.get_op_getter_fn('outreg')
            outreg_expr = '%s(%s)' % (getter_fn, inst) 
            fo.add_code('/*opname %s */' % op.name)
            _add_op_assign_stmt(fo, op.name, outreg_expr, inst)
            #now check if we have errors in current NT
            #we don't need to check if there was a reg_error because
            #we assign error operand inside the called nt_capture function
            #if there was a reg_error
            getter_fn = operand_storage.get_op_getter_fn(_xed3_err_op)
            errval = '%s(%s)' % (getter_fn, inst)
            fo.add_code('if (%s) {' % errval)
            fo.add_code_eol('return %s' % errval)
            fo.add_code('}')
        elif op.type in ['imm_const', 'reg']:
            opval = op.bits
            _add_op_assign_stmt(fo, op.name, opval, inst)
            
    
    fo.add_code_eol('return %s' % _xed_no_err_val)
    return fo
示例#20
0
def _gen_empty_function(agi):
    """This function is for patterns that don't set [BR]DISP_WIDTH tokens.
    These patterns have disp_bytes set earlier in xed-ild.c and we
    define a L2 lookup function that does nothing    """
    
    operand_storage = agi.operand_storage
    return_type = 'void'
    fo = codegen.function_object_t(_empty_fn, return_type,
                                   static=True, inline=True)
    data_name = 'x'
    fo.add_arg(ildutil.ild_c_type + ' %s' % data_name)
    fo.add_code('/*This function does nothing for map-opcodes whose')
    fo.add_code('disp_bytes value is set earlier in xed-ild.c')
    fo.add_code('(regular displacement resolution by modrm/sib)*/\n')
    fo.add_code('/*pacify the compiler*/')
    fo.add_code_eol('(void)%s' % data_name)
    return fo
示例#21
0
def _gen_empty_capture_fo(is_ntluf=False):
    """
    Generate capture function that does nothing. 
    For patterns without NTs.
    """
    inst = 'd'
    if is_ntluf:
        fname = '%s_ntluf' % _xed3_empty_capture_func
    else:
        fname = _xed3_empty_capture_func
    fo = codegen.function_object_t(fname,
                                   return_type=_xed3_chain_return_t,
                                   static=True,
                                   inline=True)
    fo.add_arg(ildutil.xed3_decoded_inst_t + '* %s' % inst)
    fo.add_code_eol('(void)%s' % inst)
    fo.add_code_eol('return %s' % _xed_no_err_val)
    return fo
示例#22
0
def gen_const_l2_function(agi, nt_name, target_opname, ild_t_member):
    return_type = 'void'
    l3_fn = ild_nt.get_lufn([nt_name], target_opname, flevel='l3')
    l2_fn = get_l2_fn([nt_name], target_opname, [], None,
              None, True)

    fo = codegen.function_object_t(l2_fn, return_type,
                                       static=True, inline=True)
    data_name = 'x'
    fo.add_arg(ildutil.ild_c_type + ' %s' % data_name)

    temp_var = '_%s' % ild_t_member
    ctype = ildutil.ild_c_op_type
    fo.add_code_eol('%s %s' % (ctype, temp_var))

    fcall = l3_fn + '()'
    fo.add_code_eol('%s = (%s)%s' % (temp_var, ctype, fcall))
    setter_fn = operand_storage.get_op_setter_fn(ild_t_member)
    fo.add_code_eol('%s(%s, %s)' % (setter_fn, data_name,temp_var))
    return fo
示例#23
0
文件: ins_emit.py 项目: yshalabi/xed
 def _make_emit_fo(self, iform, i):
     ''' create the function object for this emit pattern
          
         @param iform: iform_t object
         @param i: index of the pattern function
         @return: function_object_t 
     '''
     
     fname = "%s_%d" % (emit_function_prefix,i)
     fo = codegen.function_object_t(fname,
                                    return_type='void')
     
     # obj_str is the function parameters for the emit function
     obj_str = encutil.enc_strings['obj_str']
     enc_arg = "%s* %s" % (encutil.enc_strings['obj_type'],
                           obj_str)
     fo.add_arg(enc_arg)
   
     for action in iform.rule.actions:
         if action.field_name and action.field_name == 'MAP':
                 emit_map = 'xed_encoder_request_emit_legacy_map'
                 code = "    %s(%s)" % (emit_map,obj_str)
                 fo.add_code_eol(code)
                 
         elif action.field_name and action.field_name == 'NOM_OPCODE':
             code = ''
             get_opcode = 'xed_encoder_get_nominal_opcode(%s)' % obj_str
             if action.nbits == 8:
                 emit_func = 'xed_encoder_request_emit_bytes'
             else:
                 emit_func = 'xed_encoder_request_encode_emit'
             code = ' '*4
             code += '%s(%s,%d,%s)' % (emit_func,obj_str,
                                       action.nbits,get_opcode) 
             fo.add_code_eol(code)     
         else:
             code = action.emit_code('EMIT')
             for c in code:
                 fo.add_code(c)
     
     return fo     
示例#24
0
def _gen_capture_fo(agi, nt_name, all_ops_widths):
    """
    Generate xed3 capturing function for a given NT name.
    """
    gi = agi.generator_dict[nt_name]
    cdict = gi.xed3_cdict
    fname = _get_xed3_nt_capture_fn(nt_name)
    inst = 'd'
    keystr = 'key'
    fo = codegen.function_object_t(fname,
                                   return_type='void',
                                   static=True,
                                   inline=True)
    fo.add_arg(ildutil.xed3_decoded_inst_t + '* %s' % inst)
    if len(cdict.cnames) > 0:
        _add_cgen_key_lines(fo, nt_name, gi, all_ops_widths, keystr, inst)
        fo.add_code('/* now switch code..*/')
        _add_switchcase_lines(fo, nt_name, gi, all_ops_widths, keystr, inst)
    else:
        rule = cdict.rule
        _add_nt_rhs_assignments(fo, nt_name, gi, rule)
    return fo
示例#25
0
    def _gen_empty_function(self,fname):
        ''' generate a function without constraints  '''
        
        return_type = 'xed_uint32_t'
        fo = codegen.function_object_t(fname,
                                       return_type=return_type,
                                       static=False,
                                       inline=False)

        obj_type = self.cvg.strings_dict['obj_type']
        obj_str =  self.cvg.strings_dict['obj_str']
        arg = "%s* %s" % (obj_type, obj_str)
        fo.add_arg(arg)
        
        lines = self.cvg.action_codegen.emit_default()
        for line in lines:
            if line == 'return ':
                fo.add_code_eol('return 1')
            else:
                fo.add_code_eol(line)
        fo.add_code_eol('(void)%s' % obj_str)
        fo.add_code_eol('return 1')
        return fo
示例#26
0
def _make_arg_check_function_object(env, enc_fn):
    encoder_fn = enc_fn.get_function_name()
    fname = '{}_chk'.format(encoder_fn)
    fo = codegen.function_object_t(fname, return_type='void', dll_export=True)
    return fo
示例#27
0
文件: ild_phash.py 项目: xelxebar/xed
    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)
示例#28
0
def work(arg):
    (chips, chip_features_dict) = read_database(arg.input_file_name)

    isa_set_per_chip_fn = dump_chip_hierarchy(arg, chips, chip_features_dict)
    # the XED_CHIP_ enum
    chips.append("ALL")
    chip_enum = enum_txt_writer.enum_info_t(['INVALID'] + chips,
                                            arg.xeddir,
                                            arg.gendir,
                                            'xed-chip',
                                            'xed_chip_enum_t',
                                            'XED_CHIP_',
                                            cplusplus=False)
    chip_enum.print_enum()
    chip_enum.run_enumer()

    # Add the "ALL" chip

    # the XED_ISA_SET_ enum
    isa_set = set()
    for vl in chip_features_dict.values():
        for v in vl:
            isa_set.add(v.upper())
    isa_set = list(isa_set)
    isa_set.sort()

    chip_features_dict['ALL'] = isa_set

    isa_set = ['INVALID'] + isa_set
    isa_set_enum = enum_txt_writer.enum_info_t(isa_set,
                                               arg.xeddir,
                                               arg.gendir,
                                               'xed-isa-set',
                                               'xed_isa_set_enum_t',
                                               'XED_ISA_SET_',
                                               cplusplus=False)
    isa_set_enum.print_enum()
    isa_set_enum.run_enumer()

    # the initialization file and header
    chip_features_cfn = 'xed-chip-features-table.c'
    chip_features_hfn = 'xed-chip-features-table.h'
    cfe = codegen.xed_file_emitter_t(arg.xeddir,
                                     arg.gendir,
                                     chip_features_cfn,
                                     shell_file=False)
    private_gendir = os.path.join(arg.gendir, 'include-private')
    hfe = codegen.xed_file_emitter_t(arg.xeddir,
                                     private_gendir,
                                     chip_features_hfn,
                                     shell_file=False)
    for header in ['xed-isa-set-enum.h', 'xed-chip-enum.h']:
        cfe.add_header(header)
        hfe.add_header(header)
    cfe.start()
    hfe.start()

    cfe.write("xed_uint64_t xed_chip_features[XED_CHIP_LAST][4];\n")
    hfe.write("extern xed_uint64_t xed_chip_features[XED_CHIP_LAST][4];\n")

    fo = codegen.function_object_t('xed_init_chip_model_info', 'void')
    fo.add_code_eol("const xed_uint64_t one=1")
    # make a set for each machine name
    spacing = "\n      |"
    for c in chips:
        s0 = ['0']
        s1 = ['0']
        s2 = ['0']
        s3 = ['0']
        # loop over the features
        for f in chip_features_dict[c]:
            feature_index = _feature_index(isa_set, f)

            if feature_index < 64:
                s0.append('(one<<XED_ISA_SET_%s)' % (f))
            elif feature_index < 128:
                s1.append('(one<<(XED_ISA_SET_%s-64))' % (f))
            elif feature_index < 192:
                s2.append('(one<<(XED_ISA_SET_%s-128))' % (f))
            elif feature_index < 256:
                s3.append('(one<<(XED_ISA_SET_%s-192))' % (f))
            else:
                _die("Feature index > 256. Need anotehr features array")

        s0s = spacing.join(s0)
        s1s = spacing.join(s1)
        s2s = spacing.join(s2)
        s3s = spacing.join(s3)

        for i, x in enumerate([s0s, s1s, s2s, s3s]):
            fo.add_code_eol("xed_chip_features[XED_CHIP_{}][{}] = {}".format(
                c, i, x))

    cfe.write(fo.emit())
    cfe.close()
    hfe.write(fo.emit_header())
    hfe.close()

    return ([
        isa_set_per_chip_fn, chip_enum.hdr_full_file_name,
        chip_enum.src_full_file_name, isa_set_enum.hdr_full_file_name,
        isa_set_enum.src_full_file_name, hfe.full_file_name, cfe.full_file_name
    ], chips, isa_set)
示例#29
0
def emit_map_info_tables(agi):
    '''variable modrm,disp,imm tables, per encoding space using natural
       map ids. returns list of files generated'''
    map_features_cfn = 'xed-map-feature-tables.c'
    map_features_hfn = 'xed-map-feature-tables.h'
    private_gendir = os.path.join(agi.common.options.gendir, 'include-private')
    hfe = codegen.xed_file_emitter_t(agi.common.options.xeddir, private_gendir,
                                     map_features_hfn)

    for h in ['xed-map-info.h']:
        hfe.add_header(h)
    hfe.start()

    sorted_list = sorted(agi.map_info, key=lambda x: x.map_name)

    spaces = list(set([mi.space for mi in sorted_list]))
    sorted_spaces = sorted(spaces, key=lambda x: encoding_space_to_vexvalid(x))
    max_space_id = _encoding_space_max()  # legacy,vex,evex,xop,knc
    #max_space_id = encoding_space_to_vexvalid(sorted_spaces[-1])

    max_map_id = max([mi.map_id for mi in agi.map_info])  #0...31

    fields = ['modrm', 'disp', 'imm']

    cvt_yes_no_var = {'yes': 1, 'no': 0, 'var': 2}
    cvt_imm = {'0': 0, '1': 1, '2': 2, '4': 4, 'var': 7}

    field_to_cvt = {
        'modrm': cvt_yes_no_var,
        'disp': cvt_yes_no_var,
        'imm': cvt_imm
    }

    bits_per_chunk = 64

    # The field width in bits must be a power of 2 for current design,
    # otherwise the bits of interest can span the 64b chunks we are
    # using to store the values.
    field_to_bits = {'modrm': 2, 'disp': 2, 'imm': 4}

    def collect_codes(field, space_maps):
        '''cvt is dict converting strings to integers. the codes are indexed by map id.'''
        cvt = field_to_cvt[field]
        codes = {key: 0 for key in range(0, max_map_id + 1)}

        for mi in space_maps:
            codes[mi.map_id] = cvt[getattr(mi, field)]

        codes_as_list = [codes[i] for i in range(0, max_map_id + 1)]
        return codes_as_list

    def convert_list_to_integer(lst, bits_per_field):
        '''return an integer or a list of integer if more than 64b'''
        integers = []
        tot = 0
        shift = 0
        for v in lst:
            if shift >= 64:
                integers.append(tot)
                tot = 0
                shift = 0
            tot = tot + (v << shift)
            shift = shift + bits_per_field
        integers.append(tot)

        if len(integers) == 1:
            return integers[0]
        return integers

    for space_id in _encoding_space_range():

        space = _space_id_to_name[space_id]
        space_maps = [mi for mi in sorted_list if mi.space == space]

        for field in fields:
            bits_per_field = field_to_bits[field]
            total_bits = max_map_id * bits_per_field
            required_chunks = math.ceil(total_bits / bits_per_chunk)
            values_per_chunk = bits_per_chunk // bits_per_field
            ilog2_values_per_chunk = int(math.log2(values_per_chunk))
            mask = (1 << bits_per_field) - 1

            f = codegen.function_object_t('xed_ild_has_{}_{}'.format(
                field, space),
                                          'xed_bool_t',
                                          static=True,
                                          inline=True)
            f.add_arg('xed_uint_t m')
            if space_maps:
                codes = collect_codes(field, space_maps)
                constant = convert_list_to_integer(codes, bits_per_field)
            else:
                codes = [0]
                constant = 0
            f.add_code('/* {} */'.format(codes))
            if set(codes) == {0}:  # all zero values...
                f.add_code_eol('return 0')
                f.add_code_eol('(void)m')
            else:
                if required_chunks <= 1:
                    f.add_code_eol(
                        'const xed_uint64_t data_const = 0x{:x}ULL'.format(
                            constant))
                    f.add_code_eol(
                        'return (xed_bool_t)((data_const >> ({}*m)) & {})'.
                        format(bits_per_field, mask))
                else:
                    f.add_code('const xed_uint64_t data_const[{}] = {{'.format(
                        required_chunks))
                    ln = ['0x{:x}ULL'.format(c) for c in constant]
                    f.add_code_eol(' {} }}'.format(", ".join(ln)))

                    f.add_code_eol(
                        'const xed_uint64_t chunkno = m >> {}'.format(
                            ilog2_values_per_chunk))
                    f.add_code_eol(
                        'const xed_uint64_t offset = m & ({}-1)'.format(
                            values_per_chunk))
                    f.add_code_eol(
                        'return (xed_bool_t)((data_const[chunkno] >> ({}*offset)) & {})'
                        .format(bits_per_field, mask))

            hfe.write(f.emit())  # emit the inline function in the header

    # emit a function that covers all spaces
    for field in fields:
        bits_per_field = field_to_bits[field]
        total_bits = max_map_id * bits_per_field
        required_chunks = math.ceil(total_bits / bits_per_chunk)
        values_per_chunk = bits_per_chunk // bits_per_field
        ilog2_values_per_chunk = int(math.log2(values_per_chunk))
        mask = (1 << bits_per_field) - 1

        f = codegen.function_object_t('xed_ild_has_{}'.format(field),
                                      'xed_bool_t',
                                      static=True,
                                      inline=True)
        f.add_arg('xed_uint_t vv')
        f.add_arg('xed_uint_t m')
        if required_chunks <= 1:
            f.add_code(
                'const xed_uint64_t data_const[{}] = {{'.format(max_space_id +
                                                                1))
        else:
            f.add_code('const xed_uint64_t data_const[{}][{}] = {{'.format(
                max_space_id + 1, required_chunks))

        for space_id in _encoding_space_range():
            space = _space_id_to_name[space_id]
            space_maps = [mi for mi in sorted_list if mi.space == space]
            if space_maps:
                codes = collect_codes(field, space_maps)
                constant = convert_list_to_integer(codes, bits_per_field)
            else:
                codes = [0] * required_chunks
                if required_chunks <= 1:
                    constant = 0
                else:
                    constant = [0] * required_chunks

            f.add_code('/* {} {} */'.format(codes, space))
            if required_chunks <= 1:
                f.add_code(' 0x{:x}ULL,'.format(constant))
            else:
                ln = ['0x{:x}ULL'.format(c) for c in constant]
                f.add_code('{{ {} }},'.format(", ".join(ln)))

        f.add_code_eol('}')
        f.add_code_eol('xed_assert(vv < {})'.format(max_space_id + 1))
        if required_chunks <= 1:
            f.add_code_eol(
                'return (xed_bool_t)((data_const[vv] >> ({}*m)) & {})'.format(
                    bits_per_field, mask))
        else:
            f.add_code_eol('const xed_uint64_t chunkno = m >> {}'.format(
                ilog2_values_per_chunk))
            f.add_code_eol('const xed_uint64_t offset = m & ({}-1)'.format(
                values_per_chunk))
            f.add_code_eol(
                'return (xed_bool_t)((data_const[vv][chunkno] >> ({}*offset)) & {})'
                .format(bits_per_field, mask))

        hfe.write(f.emit())  # emit the inline function in the header

    # emit a set of functions for determining the valid maps in each encoding space
    if max_map_id > 64:
        genutil.die("Need to make this work with multiple chunks of u64")
    for space_id in _encoding_space_range():
        space = _space_id_to_name[space_id]

        space_maps = [mi for mi in sorted_list if mi.space == space]
        f = codegen.function_object_t('xed_ild_map_valid_{}'.format(space),
                                      'xed_bool_t',
                                      static=True,
                                      inline=True)
        f.add_arg('xed_uint_t m')
        max_id = _encoding_space_max()
        #max_id = max( [mi.map_id for mi in space_maps ] )
        codes_dict = {key: 0 for key in range(0, max_map_id + 1)}
        for mi in space_maps:
            codes_dict[mi.map_id] = 1
        codes = [codes_dict[i] for i in range(0, max_map_id + 1)]

        f.add_code('/* {} */'.format(codes))
        constant = convert_list_to_integer(codes, 1)
        f.add_code_eol(
            'const xed_uint64_t data_const = 0x{:x}ULL'.format(constant))
        # no need for a max-map test since, the upper bits of the
        # constant will be zero already
        f.add_code_eol('return (xed_bool_t)((data_const >> m) & 1)')
        hfe.write(f.emit())  # emit the inline function in the header

    # emit a table filling in "xed_map_info_t xed_legacy_maps[] = { ... }"

    legacy_maps = [mi for mi in sorted_list if mi.space == 'legacy']
    legacy_maps = sorted(legacy_maps,
                         key=lambda x: -len(x.search_pattern) * 10 + x.map_id)

    hfe.add_code('const xed_map_info_t xed_legacy_maps[] = {')
    for mi in legacy_maps:
        if mi.map_id == 0:
            continue
        has_legacy_opcode = 1 if mi.legacy_opcode != 'N/A' else 0
        legacy_opcode = mi.legacy_opcode if mi.legacy_opcode != 'N/A' else 0
        legacy_escape = mi.legacy_escape if mi.legacy_escape != 'N/A' else 0

        hfe.add_code('{{ {}, {}, {}, {}, {} }},'.format(
            legacy_escape, has_legacy_opcode, legacy_opcode, mi.map_id,
            mi.opcpos))
    hfe.add_code_eol('}')

    hfe.close()
    return [hfe.full_file_name]