def _gen_byreg_fun_dict(info_list, nt_dict, is_conflict_fun, gen_l2_fn_fun): fun_dict = {} insn_map = info_list[0].insn_map opcode = info_list[0].opcode for reg in range(0, 8): #get info objects with the same modrm.reg bits infos = list(filter(lambda info: info.ext_opcode == reg, info_list)) if len(infos) == 0: ildutil.ild_warn('BYREG resolving: No infos for reg' + '%s opcode %s map %s' % (reg, opcode, insn_map)) #we need to allow incomplete modrm.reg mappings for the #case of map 0 opcode 0xC7 where we have infos only for #reg 0 (MOV) and 7 continue #if these info objects conflict, we cannot refine by modrm.reg is_conflict = is_conflict_fun(infos, nt_dict) if is_conflict == None: return None if is_conflict: ildutil.ild_warn('BYREG resolving:Still conflict for reg' + '%s opcode %s map %s' % (reg, opcode, insn_map)) return None l2_fn = gen_l2_fn_fun(infos[0], nt_dict) if not l2_fn: return None fun_dict[reg] = l2_fn return fun_dict
def _find_l2_phash(cdict): """Find a 2 level hash table for more complex cases""" # try hashmul first for the first level of the 2 level # hash function. hash_f = _find_l2_hash_mul(cdict) if hash_f: return l2_phash_t(cdict, hash_f) # otherwise try a FKS for the first level of the 2 level hash # function. hash_f = hashfks.find_fks_well_distributed(cdict.tuple2int) if hash_f: return l2_phash_t(cdict, hash_f) ildutil.ild_warn("Failed to find L2 hash function for %s" % cdict) return None
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