def emit_ild_access_call(opname, data_name, eoasz_set=False): """ @param opname: the name of the operand of xed grammar. @type opname: string @param data_name: the name of xed_decoded_inst_t* pointer @type data_name: string @param eoasz_set: when doing static decoding EOSZ and EASZ are not yet set correctly in the operands structure and we have to use special ILD getters to get their correct value. After dynamic decoding (and before we do operands decoding) EOSZ and EASZ are already set and we can use regular getter for them. @type eoasz_set: boolean IMPORTANT: EASZ and EOSZ cannot be computed with this function, see how it's done in ild_imm and ild_disp for these two. @return: C statement (no semicolon, no eol) that returns the value of corresponding operand. """ if opname in ['EASZ', 'EOSZ'] and not eoasz_set: #EASZ and EOSZ should be computed in a special way #see how it's done in ild_phash.phash_t.add_cgen_lines ildutil.ild_err('No simple getter for %s operand' % opname) elif _is_special_op(opname): getter_fn = _get_special_op_getter_fn(opname) else: getter_fn = operand_storage.get_op_getter_fn(opname) call_str = '%s(%s)' % (getter_fn, data_name) return call_str
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
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
def get_compressed_op_getter_fn(opname): """ Compressed operands are special - we do not capture them in ILD and do not derive them in NTs. (though we could.. FIXME: is it worthy?), hence in order to get their value we can not use regular xed3_operand_get_* function - we use special getters for them. get_compressed_op_getter_fn(opname) returns a name of the special getter for a given compressed operand name. FIXME: right now we just use the same operand naming scheme as for regular operands. Do we need this function? """ return operand_storage.get_op_getter_fn(opname)
def _add_nt_rhs_assignments(fo, nt_name, gi, rule, inst='d'): #fo.add_code("/* %s */" % rule) #first if it's error, we set general_error and quit if _is_error_rule(rule): _add_op_assign_stmt(fo, _xed3_err_op, _xed3_gen_error, inst, indent=1) return #now check if there are NT calls in pattern, we need to call them first pattern_nts = _get_pattern_nts(rule) for nt_name in pattern_nts: _add_capture_nt_call(fo, nt_name, inst, indent=1) #now let's do the RHS - for each operand assign value #FIXME: if we assign ERROR_REG or INVALID_REG set also error? for op in rule.operands: if op.name == 'ENCODER_PREFERRED': #skip encoder preferred continue if op.type == 'imm': #skip prebindings continue if op.type == 'nt_lookup_fn': #NT as RHS, we call its capturing function #and then assign op.name to OUTREG _add_capture_nt_call(fo, op.lookupfn_name, inst, indent=1) #now copy the outreg to op.name (unless it is outreg too!) if op.name != 'OUTREG': getter_fn = operand_storage.get_op_getter_fn('outreg') outreg_expr = '%s(%s)' % (getter_fn, inst) _add_op_assign_stmt(fo, op.name, outreg_expr, inst, indent=1) else: #assignment of an operand to a constant _add_op_assign_stmt(fo, op.name, op.bits, inst, indent=1) if _is_reg_error_op(op): _add_op_assign_stmt(fo, _xed3_err_op, _xed_reg_error_val, inst, indent=1) fo.add_code('/*pacify the compiler */') fo.add_code_eol('(void)%s' % inst)