tcg.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,895 行 · 第 1/4 页
C
1,895 行
int idx; idx = s->nb_temps;#if TCG_TARGET_REG_BITS == 32 tcg_temp_alloc(s, idx + 2); ts = &s->temps[idx]; ts->base_type = TCG_TYPE_I64; ts->type = TCG_TYPE_I32; ts->val_type = TEMP_VAL_CONST; ts->name = NULL; ts->val = val; ts++; ts->base_type = TCG_TYPE_I32; ts->type = TCG_TYPE_I32; ts->val_type = TEMP_VAL_CONST; ts->name = NULL; ts->val = val >> 32; s->nb_temps += 2;#else tcg_temp_alloc(s, idx + 1); ts = &s->temps[idx]; ts->base_type = ts->type = TCG_TYPE_I64; ts->val_type = TEMP_VAL_CONST; ts->name = NULL; ts->val = val; s->nb_temps++;#endif return MAKE_TCGV(idx);}void tcg_register_helper(void *func, const char *name){ TCGContext *s = &tcg_ctx; int n; if ((s->nb_helpers + 1) > s->allocated_helpers) { n = s->allocated_helpers; if (n == 0) { n = 4; } else { n *= 2; } s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo)); s->allocated_helpers = n; } s->helpers[s->nb_helpers].func = func; s->helpers[s->nb_helpers].name = name; s->nb_helpers++;}const char *tcg_helper_get_name(TCGContext *s, void *func){ int i; for(i = 0; i < s->nb_helpers; i++) { if (s->helpers[i].func == func) return s->helpers[i].name; } return NULL;}static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg){ return s->temps[GET_TCGV(arg)].base_type;}static void tcg_gen_call_internal(TCGContext *s, TCGv func, unsigned int flags, unsigned int nb_rets, const TCGv *rets, unsigned int nb_params, const TCGv *params){ int i; *gen_opc_ptr++ = INDEX_op_call; *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1); for(i = 0; i < nb_rets; i++) { *gen_opparam_ptr++ = GET_TCGV(rets[i]); } for(i = 0; i < nb_params; i++) { *gen_opparam_ptr++ = GET_TCGV(params[i]); } *gen_opparam_ptr++ = GET_TCGV(func); *gen_opparam_ptr++ = flags; /* total parameters, needed to go backward in the instruction stream */ *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;}#if TCG_TARGET_REG_BITS < 64/* Note: we convert the 64 bit args to 32 bit */void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, unsigned int nb_rets, const TCGv *rets, unsigned int nb_params, const TCGv *args1){ TCGv ret, *args2, rets_2[2], arg; int j, i, call_type; if (nb_rets == 1) { ret = rets[0]; if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) { nb_rets = 2; rets_2[0] = ret; rets_2[1] = TCGV_HIGH(ret); rets = rets_2; } } args2 = alloca((nb_params * 2) * sizeof(TCGv)); j = 0; call_type = (flags & TCG_CALL_TYPE_MASK); for(i = 0; i < nb_params; i++) { arg = args1[i]; if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {#ifdef TCG_TARGET_I386 /* REGPARM case: if the third parameter is 64 bit, it is allocated on the stack */ if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) { call_type = TCG_CALL_TYPE_REGPARM_2; flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type; } args2[j++] = arg; args2[j++] = TCGV_HIGH(arg);#else#ifdef TCG_TARGET_WORDS_BIGENDIAN args2[j++] = TCGV_HIGH(arg); args2[j++] = arg;#else args2[j++] = arg; args2[j++] = TCGV_HIGH(arg);#endif#endif } else { args2[j++] = arg; } } tcg_gen_call_internal(s, func, flags, nb_rets, rets, j, args2);}#elsevoid tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, unsigned int nb_rets, const TCGv *rets, unsigned int nb_params, const TCGv *args1){ tcg_gen_call_internal(s, func, flags, nb_rets, rets, nb_params, args1);}#endif#if TCG_TARGET_REG_BITS == 32void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, int c, int right, int arith){ if (c == 0) return; if (c >= 32) { c -= 32; if (right) { if (arith) { tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c); tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); } else { tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c); tcg_gen_movi_i32(TCGV_HIGH(ret), 0); } } else { tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c); tcg_gen_movi_i32(ret, 0); } } else { TCGv t0, t1; t0 = tcg_temp_new(TCG_TYPE_I32); t1 = tcg_temp_new(TCG_TYPE_I32); if (right) { tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c); if (arith) tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c); else tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c); tcg_gen_shri_i32(ret, arg1, c); tcg_gen_or_i32(ret, ret, t0); tcg_gen_mov_i32(TCGV_HIGH(ret), t1); } else { tcg_gen_shri_i32(t0, arg1, 32 - c); /* Note: ret can be the same as arg1, so we use t1 */ tcg_gen_shli_i32(t1, arg1, c); tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0); tcg_gen_mov_i32(ret, t1); } }}#endifvoid tcg_reg_alloc_start(TCGContext *s){ int i; TCGTemp *ts; for(i = 0; i < s->nb_globals; i++) { ts = &s->temps[i]; if (ts->fixed_reg) { ts->val_type = TEMP_VAL_REG; } else { ts->val_type = TEMP_VAL_MEM; } } for(i = 0; i < TCG_TARGET_NB_REGS; i++) { s->reg_to_temp[i] = -1; }}static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size, int idx){ TCGTemp *ts; ts = &s->temps[idx]; if (idx < s->nb_globals) { pstrcpy(buf, buf_size, ts->name); } else { if (ts->val_type == TEMP_VAL_CONST) { snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val); } else { snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); } } return buf;}char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg){ return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));}void tcg_dump_ops(TCGContext *s, FILE *outfile){ const uint16_t *opc_ptr; const TCGArg *args; TCGArg arg; int c, i, k, nb_oargs, nb_iargs, nb_cargs; const TCGOpDef *def; char buf[128]; opc_ptr = gen_opc_buf; args = gen_opparam_buf; while (opc_ptr < gen_opc_ptr) { c = *opc_ptr++; def = &tcg_op_defs[c]; fprintf(outfile, " %s ", def->name); if (c == INDEX_op_call) { TCGArg arg; /* variable number of arguments */ arg = *args++; nb_oargs = arg >> 16; nb_iargs = arg & 0xffff; nb_cargs = def->nb_cargs; /* function name */ /* XXX: dump helper name for call */ fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1])); /* flags */ fprintf(outfile, ",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]); /* nb out args */ fprintf(outfile, ",$%d", nb_oargs); for(i = 0; i < nb_oargs; i++) { fprintf(outfile, ","); fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i])); } for(i = 0; i < (nb_iargs - 1); i++) { fprintf(outfile, ","); fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); } } else { if (c == INDEX_op_nopn) { /* variable number of arguments */ nb_cargs = *args; nb_oargs = 0; nb_iargs = 0; } else { nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; } k = 0; for(i = 0; i < nb_oargs; i++) { if (k != 0) fprintf(outfile, ","); fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); } for(i = 0; i < nb_iargs; i++) { if (k != 0) fprintf(outfile, ","); fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); } for(i = 0; i < nb_cargs; i++) { if (k != 0) fprintf(outfile, ","); arg = args[k++]; fprintf(outfile, "$0x%" TCG_PRIlx, arg); } } fprintf(outfile, "\n"); args += nb_iargs + nb_oargs + nb_cargs; }}/* we give more priority to constraints with less registers */static int get_constraint_priority(const TCGOpDef *def, int k){ const TCGArgConstraint *arg_ct; int i, n; arg_ct = &def->args_ct[k]; if (arg_ct->ct & TCG_CT_ALIAS) { /* an alias is equivalent to a single register */ n = 1; } else { if (!(arg_ct->ct & TCG_CT_REG)) return 0; n = 0; for(i = 0; i < TCG_TARGET_NB_REGS; i++) { if (tcg_regset_test_reg(arg_ct->u.regs, i)) n++; } } return TCG_TARGET_NB_REGS - n + 1;}/* sort from highest priority to lowest */static void sort_constraints(TCGOpDef *def, int start, int n){ int i, j, p1, p2, tmp; for(i = 0; i < n; i++) def->sorted_args[start + i] = start + i; if (n <= 1) return; for(i = 0; i < n - 1; i++) { for(j = i + 1; j < n; j++) { p1 = get_constraint_priority(def, def->sorted_args[start + i]); p2 = get_constraint_priority(def, def->sorted_args[start + j]); if (p1 < p2) { tmp = def->sorted_args[start + i]; def->sorted_args[start + i] = def->sorted_args[start + j]; def->sorted_args[start + j] = tmp; } } }}void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs){ int op; TCGOpDef *def; const char *ct_str; int i, nb_args; for(;;) { if (tdefs->op < 0) break; op = tdefs->op; assert(op >= 0 && op < NB_OPS); def = &tcg_op_defs[op]; nb_args = def->nb_iargs + def->nb_oargs; for(i = 0; i < nb_args; i++) { ct_str = tdefs->args_ct_str[i]; tcg_regset_clear(def->args_ct[i].u.regs); def->args_ct[i].ct = 0; if (ct_str[0] >= '0' && ct_str[0] <= '9') { int oarg; oarg = ct_str[0] - '0'; assert(oarg < def->nb_oargs); assert(def->args_ct[oarg].ct & TCG_CT_REG); /* TCG_CT_ALIAS is for the output arguments. The input argument is tagged with TCG_CT_IALIAS. */ def->args_ct[i] = def->args_ct[oarg]; def->args_ct[oarg].ct = TCG_CT_ALIAS; def->args_ct[oarg].alias_index = i; def->args_ct[i].ct |= TCG_CT_IALIAS; def->args_ct[i].alias_index = oarg; } else { for(;;) { if (*ct_str == '\0') break; switch(*ct_str) { case 'i': def->args_ct[i].ct |= TCG_CT_CONST; ct_str++; break; default: if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) { fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n", ct_str, i, def->name); exit(1); } } } } } /* sort the constraints (XXX: this is just an heuristic) */ sort_constraints(def, 0, def->nb_oargs); sort_constraints(def, def->nb_oargs, def->nb_iargs);#if 0 { int i; printf("%s: sorted=", def->name); for(i = 0; i < def->nb_oargs + def->nb_iargs; i++) printf(" %d", def->sorted_args[i]); printf("\n"); }#endif tdefs++; }}#ifdef USE_LIVENESS_ANALYSIS/* set a nop for an operation using 'nb_args' */static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, TCGArg *args, int nb_args){ if (nb_args == 0) { *opc_ptr = INDEX_op_nop; } else { *opc_ptr = INDEX_op_nopn; args[0] = nb_args; args[nb_args - 1] = nb_args; }}/* liveness analysis: end of basic block: globals are live, temps are dead */static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps){ memset(dead_temps, 0, s->nb_globals); memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);}/* Liveness analysis : update the opc_dead_iargs array to tell if a given input arguments is dead. Instructions updating dead temporaries are removed. */void tcg_liveness_analysis(TCGContext *s){ int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops; TCGArg *args; const TCGOpDef *def; uint8_t *dead_temps; unsigned int dead_iargs; gen_opc_ptr++; /* skip end */ nb_ops = gen_opc_ptr - gen_opc_buf; /* XXX: make it really dynamic */ s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t)); dead_temps = tcg_malloc(s->nb_temps); memset(dead_temps, 1, s->nb_temps); args = gen_opparam_ptr; op_index = nb_ops - 1; while (op_index >= 0) { op = gen_opc_buf[op_index]; def = &tcg_op_defs[op]; switch(op) { case INDEX_op_call:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?