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