Пример #1
0
def work(agi, all_state_space, all_ops_widths, patterns):
    """
    Main entry point of the module.
    For each NT generate a capturing function.
    Then for each sequence of NTs in patterns generate a
    chain capturing function that would call single capturing functions
    for each NT.
    Then for each combination of operands generate operands chain captuirng
    function.
    Also generate lookup tables to obtain those chain capturing functions
    from inum (xed_inst_t index).
    """
    gendir = ild_gendir = agi.common.options.gendir
    logfn = mbuild.join(gendir, 'xed3_nt_cdicts.txt')
    log_f = open(logfn, 'w')

    #generate NT capturing functions
    capture_fn_list = []
    for nt_name in list(agi.nonterminal_dict.keys()):
        #skip nonterminals that we don't want to capture:
        #PREFIXES, AVX_SPLITTER, *ISA, etc.
        if _skip_nt(nt_name):
            continue

        _vlog(log_f, 'processing %s\n' % nt_name)
        #create a constraint_dict_t for each NT
        nt_cdict = _gen_cdict(agi, nt_name, all_state_space)
        _vlog(log_f, 'NT:%s:\n%s\n' % (nt_name, nt_cdict))
        gi = agi.generator_dict[nt_name]
        gi.xed3_cdict = nt_cdict  #just for transporting
        #create a function_object_t for the NT
        fo = _gen_capture_fo(agi, nt_name, all_ops_widths)
        gi.xed3_capture_fo = fo
        capture_fn_list.append(fo)
        _vlog(log_f, fo.emit())

    #dump NT capturing functions
    headers = [operand_storage.get_operand_accessors_fn(), ildutil.ild_header]
    ild_codegen.dump_flist_2_header(agi,
                                    _xed3_nt_capture_header,
                                    headers,
                                    capture_fn_list,
                                    is_private=True)

    #in each pattern we have a number of NTs,
    #now that we have a capturing function for each NT
    #we can create a create a function that would call
    #needed capturing functions for each pattern.
    #Also dump lookup tables from inum(xed_inst_t index) to
    #chain capturing functions
    _dump_capture_chain_fo_lu(agi, patterns)

    #do the same for operands of each xed_inst_t
    _dump_op_capture_chain_fo_lu(agi, patterns)

    #create chain capturing functions for the NTs that come from
    #spine, before the INSTRUCTIONS NT
    _dump_dynamic_part1_f(agi)

    log_f.close()
Пример #2
0
def _dump_dynamic_part1_f(agi):
    """
    Dumps the xed3_dynamic_decode_part1 function that captures all the
    NTs in the spine that come before INSTRUCTIONS NT.
    """
    fo = _gen_dynamic_part1_fo(agi)
    #dump the function
    headers = [_xed3_nt_capture_header]
    ild_codegen.dump_flist_2_header(agi,
                                    _xed3_dynamic_part1_header,
                                    headers, [fo],
                                    is_private=True)
Пример #3
0
def work(agi, united_lookup, eosz_nts, ild_gendir, debug):

    #dump lookup tables for each NT
    #just for debugging
    nt_arrays = []
    for nt_name in eosz_nts:
        array = ild_nt.gen_nt_lookup(agi, nt_name, 'EOSZ')
        if not array:
            return None
        nt_arrays.append(array)
    ild_nt.dump_lu_arrays(agi, nt_arrays, 'ild_eosz_debug.txt',
                          'ild_eosz_debug_header.txt')

    #get all sequences of NTs that set EOSZ
    #we will use these sequences to create EOSZ-computing functions
    all_eosz_seq = get_all_eosz_seq(united_lookup)
    debug.write('EOSZ SEQS: %s\n' % all_eosz_seq)

    #for each EOSZ sequence create a lookup array
    nt_seq_arrays = {}
    for nt_seq in all_eosz_seq:
        array = ild_nt.gen_nt_seq_lookup(agi, nt_seq, _eosz_token)
        if not array:
            return None
        nt_seq_arrays[tuple(nt_seq)] = array
    #init function calls all single init functions for the created tables
    init_f = ild_nt.gen_init_function(list(nt_seq_arrays.values()),
                                      'xed_ild_eosz_init')
    #dump init and lookup functions for EOSZ sequences
    ild_nt.dump_lu_arrays(agi, list(nt_seq_arrays.values()), _eosz_c_fn,
                          mbuild.join('include-private', _eosz_header_fn),
                          init_f)
    #generate EOSZ getter functions - they get xed_decoded_inst_t*
    #and return EOSZ value (corresponding to EOSZ NT sequence
    #that they represent)
    getter_fos = []
    for names in nt_seq_arrays.keys():
        arr = nt_seq_arrays[names]
        getter_fo = ild_codegen.gen_derived_operand_getter(
            agi, _eosz_token, arr, list(names))
        getter_fos.append(getter_fo)

    ild_codegen.dump_flist_2_header(agi, 'xed-ild-eosz-getters.h', [
        ildutil.ild_private_header, _eosz_header_fn,
        operand_storage.get_operand_accessors_fn()
    ], getter_fos)

    #getter_lookup = gen_getter_fn_lookup(agi, united_lookup, nt_seq_arrays)

    return nt_seq_arrays
Пример #4
0
def work(agi, united_lookup, easz_nts, ild_gendir, debug):
    
    #dump lookup tables for each NT
    #just for debugging
    nt_arrays = []
    for nt_name in easz_nts:
        array = ild_nt.gen_nt_lookup(agi, nt_name, 'EASZ')
        if not array:
            return
        nt_arrays.append(array)
    ild_nt.dump_lu_arrays(agi, nt_arrays, 'ild_easz_debug.txt',
                          'ild_easz_debug_header.txt')
        
    all_easz_seq = get_all_easz_seq(united_lookup)
    debug.write('EASZ SEQS: %s\n' % all_easz_seq)

    nt_seq_arrays = {}
    for nt_seq in all_easz_seq:
        array = ild_nt.gen_nt_seq_lookup(agi, nt_seq, _easz_token)
        if not array:
            return
        nt_seq_arrays[tuple(nt_seq)] = array
    #init function calls all single init functions for the created tables
    nt_seq_values = [v for (k,v) in sorted(nt_seq_arrays.items())]
    init_f = ild_nt.gen_init_function(nt_seq_values,
                                       'xed_ild_easz_init')
    ild_nt.dump_lu_arrays(agi, nt_seq_values, _easz_c_fn, 
                          mbuild.join('include-private', _easz_header_fn),
                          init_f)
    getter_fos = []
    for names in nt_seq_arrays.keys():
        arr = nt_seq_arrays[names]
        getter_fo = ild_codegen.gen_derived_operand_getter(agi, _easz_token,
                                                           arr, list(names))
        getter_fos.append(getter_fo)
    
    headers = [ildutil.ild_private_header,
               _easz_header_fn, 
               operand_storage.get_operand_accessors_fn()]
    ild_codegen.dump_flist_2_header(agi, 'xed-ild-easz-getters.h',
                                    headers, 
                                    getter_fos)
    
    #getter_lookup = gen_getter_fn_lookup(agi, united_lookup, nt_seq_arrays)
    
    return nt_seq_arrays
Пример #5
0
def work(agi, united_lookup, imm_nts, ild_gendir, eosz_dict, 
         debug):
    """
    main entry point of the module.
    """
    #dump lookup functions for each NT
    #Let's call these function Level3 functions (L3)
    nt_dict = {}
    
    #generate the L3 functions
    #Every NT, that changes IMM_WIDTH, defines a L3 function.
    #For example SIMM8() NT defines a L3 function that returns 1 (1 byte).
    #And SIMMv() NT defines a function that gets EOSZ and returns IMM_WIDTH
    #value depending on EOSZ.
    
    #UIMM8_1 doesn't bind IMM_WIDTH operand, it is a special case
    #there is nothing to generate for it. 
    for nt_name in _filter_uimm1_nt(imm_nts):
        array = ild_nt.gen_nt_lookup(agi, nt_name, _imm_token, 
                                     target_type=ildutil.ild_c_op_type,
                                     level='l3')
        nt_dict[nt_name] = array

    #create function that calls all initialization functions for L3
    init_f = ild_nt.gen_init_function(list(nt_dict.values()),
                                      'xed_ild_imm_l3_init')
    
    #dump L3 functions
    ild_nt.dump_lu_arrays(agi, list(nt_dict.values()), _l3_c_fn,
                          mbuild.join('include-private',_l3_header_fn),
                          init_f)
    
    #get all IMM NT sequences that are used in patterns
    #The only case of IMM sequence is when we have UIMM1() NT - the second
    #immediate NT.    
    all_imm_seq = get_all_imm_seq(united_lookup)
    debug.write('IMM SEQS: %s\n' % all_imm_seq)

    # L2 / Level2 functions: set imm_width
    # Now we define functions that compute EOSZ value (using one of
    # the EOSZ-resolution functions) and then use 
    # one of the L3 functions(that need EOSZ) to set IMM_WIDTH.

    # The names of these functions should be something like 
    # xed_ild_SIMMz_OSZ_NONTERM_DF64 - to define the imm-binding nonterm 
    # and to define the EOSZ-resolution NT sequence.
    # L2 functions are defined by single ild_info_t object - by its
    # eosz_nt_seq and imm_nt_seq
    l2_functions = ild_codegen.gen_l2_func_list(agi, nt_dict, eosz_dict,
                                                _ild_t_imm_member)
    #append function for imm_bytes==0
    l2_functions.append(_gen_imm0_function(agi))
    
    l2_headers = [ild_eosz.get_ntseq_header_fn(),
                  _l3_header_fn, ildutil.ild_header,
                  operand_storage.get_operand_accessors_fn()]
    ild_codegen.dump_flist_2_header(agi, _l2_header_fn, l2_headers, 
                                    l2_functions)

    # L1 / Level1 functions:
    # Now we define functions that resolve conflicts (if any)
    # using modrm.reg bits, and that way decide which L2 function to
    # call to set the IMM value.
    # These functions will be the value of map,opcode lookup tables.
    
    # These functions should be dumped after we have a look on the
    # united_lookup mapping in order to know what conflicts exist and
    # for each conflict to create a resolution lookup table.
    
    # L1 functions are defined by a list of ild_info_t objects that
    # have same map,opcode.
    res = gen_l1_functions_and_lookup(agi, united_lookup, nt_dict)

    l1_functions,l1_lookup = res

    ild_codegen.dump_flist_2_header(agi, _l1_header_fn, [_l2_header_fn], 
                                    l1_functions)
    
    headers = [_l1_header_fn, ildutil.ild_private_header, 
               operand_storage.get_operand_accessors_fn()]
    ild_codegen.dump_lookup(agi, l1_lookup, _ild_t_imm_member, 
                            _imm_lu_header_fn, headers, 
                            ildutil.l1_ptr_typename)
Пример #6
0
def work(agi, united_lookup, disp_nts, brdisp_nts, ild_gendir, eosz_dict,
         easz_dict, debug):
    """
    Main entry point of the module.
    Generates all the L1-3 functions and dumps disp_bytes lookup
    tables.
    """

    #get all used DISP NT sequences that appear in patterns
    #we are going to generate L1-3 functions only for these sequences
    all_disp_seq = get_all_disp_seq(united_lookup)

    #check that all sequences are actually single NTs
    #(each sequence has only one NT)
    #my observation is that they really are. This simplifies things
    #and we are going to rely on that.
    all_nts = []
    for ntseq in all_disp_seq:
        if len(ntseq) > 1:
            ildutil.ild_err("Unexpected DISP NT SEQ %s" % ntseq)
        if len(ntseq) == 0:
            continue  #the empty NT sequence
        all_nts.append(ntseq[0])

    #get only those NTs that actually appear in PATTERNs
    disp_nts = list(filter(lambda nt: nt in all_nts, disp_nts))
    brdisp_nts = list(filter(lambda nt: nt in all_nts, brdisp_nts))

    debug.write('DISP SEQS: %s\n' % all_disp_seq)
    debug.write('DISP NTs: %s\n' % disp_nts)
    debug.write('BRDISP NTs: %s\n' % brdisp_nts)

    brdisp_dict = _gen_l3_array_dict(agi, brdisp_nts, _brdisp_token)
    disp_dict = _gen_l3_array_dict(agi, disp_nts, _disp_token)

    nt_arr_list = list(brdisp_dict.values()) + list(disp_dict.values())
    #create function that calls all initialization functions
    init_f = ild_nt.gen_init_function(nt_arr_list, 'xed_ild_disp_l3_init')

    #dump L3 functions
    ild_nt.dump_lu_arrays(agi, nt_arr_list, _l3_c_fn,
                          mbuild.join('include-private', _l3_header_fn),
                          init_f)

    #create L2 functions

    #The thing is that we need to know for each
    #DISP NT whether it depends on EOSZ or EASZ and supply appropriate arg_dict
    #to gen_l2_func_list()
    l2_functions = []
    eosz_op = ild_eosz.get_target_opname()
    easz_op = ild_easz.get_target_opname()
    for nt_name, array in list(disp_dict.items()) + list(brdisp_dict.items()):
        #Some DISP NTs depend on EOSZ, others on EASZ, we need to know
        #that when we generate L2 functions
        if eosz_op in array.get_arg_names():
            arg_dict = eosz_dict
        else:
            arg_dict = easz_dict
        flist = ild_codegen.gen_l2_func_list(agi, {nt_name: array}, arg_dict,
                                             _ild_t_disp_member)
        l2_functions.extend(flist)

    #create the doing-nothing L2 function for map-opcodes
    #with regular displacement resolution
    l2_functions.append(_gen_empty_function(agi))

    #dump L2 functions
    l2_headers = [
        ild_eosz.get_ntseq_header_fn(),
        ild_easz.get_ntseq_header_fn(), _l3_header_fn,
        ildutil.ild_private_header,
        operand_storage.get_operand_accessors_fn()
    ]
    ild_codegen.dump_flist_2_header(agi, _l2_header_fn, l2_headers,
                                    l2_functions)

    #create the L1 functions and lookup tables

    #unite brdisp and dips dictionaries
    disp_dict.update(brdisp_dict)

    #generate L1 functions and lookup tables
    res = gen_l1_functions_and_lookup(agi, united_lookup, disp_dict)

    l1_functions, l1_lookup = res
    #dump L1 functions
    ild_codegen.dump_flist_2_header(agi, _l1_header_fn, [_l2_header_fn],
                                    l1_functions)
    #dump lookup tables
    headers = [
        _l1_header_fn, ildutil.ild_private_header,
        operand_storage.get_operand_accessors_fn()
    ]
    ild_codegen.dump_lookup(agi, l1_lookup, _ild_t_disp_member,
                            _disp_lu_header_fn, headers,
                            ildutil.l1_ptr_typename)
Пример #7
0
def _dump_capture_chain_fo_lu(agi, patterns):
    """
    Creates chain capturing functions - for each pattern,
    dumps those functions definitions, dumps a mapping
    from inum(xed_inst_t index) to those functions.
    """
    fn_2_fo = {}
    inum_2_fn = {}

    nop_fo = _gen_empty_capture_fo()
    fn_2_fo[nop_fo.function_name] = nop_fo
    for ptrn in patterns:
        ii = ptrn.ii
        nt_names = _get_nt_names_from_ii(ii)
        if len(nt_names) == 0:
            #if no NTs we use empty capturing function
            fn = nop_fo.function_name
        else:
            fn = _get_xed3_capture_chain_fn(nt_names)
        if fn not in fn_2_fo:
            fo = _gen_capture_chain_fo(nt_names)
            fn_2_fo[fn] = fo
        inum_2_fn[ii.inum] = (fn, ptrn.ptrn)

    #dump chain functions
    headers = [_xed3_nt_capture_header]
    ild_codegen.dump_flist_2_header(agi,
                                    _xed3_chain_header,
                                    headers,
                                    list(fn_2_fo.values()),
                                    is_private=True)

    lu_size = max(inum_2_fn.keys()) + 1

    xeddir = os.path.abspath(agi.common.options.xeddir)
    gendir = mbuild.join(agi.common.options.gendir, 'include-private')

    h_file = codegen.xed_file_emitter_t(xeddir,
                                        gendir,
                                        _xed3_chain_lu_header,
                                        shell_file=False,
                                        is_private=True)
    h_file.add_header(_xed3_chain_header)
    h_file.start()
    lu_name = 'xed3_chain_fptr_lu'
    xed3_chain_f_t = 'xed3_chain_function_t'

    fptr_typedef = 'typedef %s(*%s)(%s*);' % (
        _xed3_chain_return_t, xed3_chain_f_t, ildutil.xed3_decoded_inst_t)

    h_file.add_code(fptr_typedef)

    h_file.add_code('static {} {}[{}] = {{'.format(xed3_chain_f_t, lu_name,
                                                   lu_size))

    empty_line = '/*NO PATTERN*/ (%s)0,' % xed3_chain_f_t

    for inum in range(0, lu_size):
        if inum in inum_2_fn:
            (fn, ptrn_str) = inum_2_fn[inum]
            entry_str = '/*\n%s\ninum=%s*/ %s,' % (ptrn_str, inum, fn)
        else:
            entry_str = empty_line
        h_file.add_code(entry_str)
    h_file.add_code('};')
    h_file.close()