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 + -
显示快捷键?