tcg.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,895 行 · 第 1/4 页

C
1,895
字号
/* * Tiny Code Generator for QEMU * * Copyright (c) 2008 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//* define it to suppress various consistency checks (faster) */#define NDEBUG/* define it to use liveness analysis (better code) */#define USE_LIVENESS_ANALYSIS#include <assert.h>#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#ifdef _WIN32#include <malloc.h>#endif#include "config.h"#include "qemu-common.h"/* Note: the long term plan is to reduce the dependancies on the QEMU   CPU definitions. Currently they are used for qemu_ld/st   instructions */#define NO_CPU_IO_DEFS#include "cpu.h"#include "exec-all.h"#include "tcg-op.h"#include "elf.h"static void patch_reloc(uint8_t *code_ptr, int type,                         tcg_target_long value, tcg_target_long addend);TCGOpDef tcg_op_defs[] = {#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },#include "tcg-opc.h"#undef DEF#undef DEF2};TCGRegSet tcg_target_available_regs[2];TCGRegSet tcg_target_call_clobber_regs;/* XXX: move that inside the context */uint16_t *gen_opc_ptr;TCGArg *gen_opparam_ptr;static inline void tcg_out8(TCGContext *s, uint8_t v){    *s->code_ptr++ = v;}static inline void tcg_out16(TCGContext *s, uint16_t v){    *(uint16_t *)s->code_ptr = v;    s->code_ptr += 2;}static inline void tcg_out32(TCGContext *s, uint32_t v){    *(uint32_t *)s->code_ptr = v;    s->code_ptr += 4;}/* label relocation processing */void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,                    int label_index, long addend){    TCGLabel *l;    TCGRelocation *r;    l = &s->labels[label_index];    if (l->has_value) {        /* FIXME: This may break relocations on RISC targets that           modify instruction fields in place.  The caller may not have            written the initial value.  */        patch_reloc(code_ptr, type, l->u.value, addend);    } else {        /* add a new relocation entry */        r = tcg_malloc(sizeof(TCGRelocation));        r->type = type;        r->ptr = code_ptr;        r->addend = addend;        r->next = l->u.first_reloc;        l->u.first_reloc = r;    }}static void tcg_out_label(TCGContext *s, int label_index,                           tcg_target_long value){    TCGLabel *l;    TCGRelocation *r;    l = &s->labels[label_index];    if (l->has_value)        tcg_abort();    r = l->u.first_reloc;    while (r != NULL) {        patch_reloc(r->ptr, r->type, value, r->addend);        r = r->next;    }    l->has_value = 1;    l->u.value = value;}int gen_new_label(void){    TCGContext *s = &tcg_ctx;    int idx;    TCGLabel *l;    if (s->nb_labels >= TCG_MAX_LABELS)        tcg_abort();    idx = s->nb_labels++;    l = &s->labels[idx];    l->has_value = 0;    l->u.first_reloc = NULL;    return idx;}#include "tcg-target.c"/* pool based memory allocation */void *tcg_malloc_internal(TCGContext *s, int size){    TCGPool *p;    int pool_size;        if (size > TCG_POOL_CHUNK_SIZE) {        /* big malloc: insert a new pool (XXX: could optimize) */        p = qemu_malloc(sizeof(TCGPool) + size);        p->size = size;        if (s->pool_current)            s->pool_current->next = p;        else            s->pool_first = p;        p->next = s->pool_current;    } else {        p = s->pool_current;        if (!p) {            p = s->pool_first;            if (!p)                goto new_pool;        } else {            if (!p->next) {            new_pool:                pool_size = TCG_POOL_CHUNK_SIZE;                p = qemu_malloc(sizeof(TCGPool) + pool_size);                p->size = pool_size;                p->next = NULL;                if (s->pool_current)                     s->pool_current->next = p;                else                    s->pool_first = p;            } else {                p = p->next;            }        }    }    s->pool_current = p;    s->pool_cur = p->data + size;    s->pool_end = p->data + p->size;    return p->data;}void tcg_pool_reset(TCGContext *s){    s->pool_cur = s->pool_end = NULL;    s->pool_current = NULL;}/* free all the pool */void tcg_pool_free(TCGContext *s){    TCGPool *p, *p1;    for(p = s->pool_first; p != NULL; p = p1) {        p1 = p->next;        qemu_free(p);    }    s->pool_first = NULL;    s->pool_cur = s->pool_end = NULL;}void tcg_context_init(TCGContext *s){    int op, total_args, n;    TCGOpDef *def;    TCGArgConstraint *args_ct;    int *sorted_args;    memset(s, 0, sizeof(*s));    s->temps = s->static_temps;    s->nb_globals = 0;        /* Count total number of arguments and allocate the corresponding       space */    total_args = 0;    for(op = 0; op < NB_OPS; op++) {        def = &tcg_op_defs[op];        n = def->nb_iargs + def->nb_oargs;        total_args += n;    }    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);    sorted_args = qemu_malloc(sizeof(int) * total_args);    for(op = 0; op < NB_OPS; op++) {        def = &tcg_op_defs[op];        def->args_ct = args_ct;        def->sorted_args = sorted_args;        n = def->nb_iargs + def->nb_oargs;        sorted_args += n;        args_ct += n;    }        tcg_target_init(s);    /* init global prologue and epilogue */    s->code_buf = code_gen_prologue;    s->code_ptr = s->code_buf;    tcg_target_qemu_prologue(s);    flush_icache_range((unsigned long)s->code_buf,                        (unsigned long)s->code_ptr);}void tcg_set_frame(TCGContext *s, int reg,                   tcg_target_long start, tcg_target_long size){    s->frame_start = start;    s->frame_end = start + size;    s->frame_reg = reg;}void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func){    s->macro_func = func;}void tcg_func_start(TCGContext *s){    tcg_pool_reset(s);    s->nb_temps = s->nb_globals;    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);    s->nb_labels = 0;    s->current_frame_offset = s->frame_start;    gen_opc_ptr = gen_opc_buf;    gen_opparam_ptr = gen_opparam_buf;}static inline void tcg_temp_alloc(TCGContext *s, int n){    if (n > TCG_MAX_TEMPS)        tcg_abort();}TCGv tcg_global_reg_new(TCGType type, int reg, const char *name){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;    int idx;#if TCG_TARGET_REG_BITS == 32    if (type != TCG_TYPE_I32)        tcg_abort();#endif    if (tcg_regset_test_reg(s->reserved_regs, reg))        tcg_abort();    idx = s->nb_globals;    tcg_temp_alloc(s, s->nb_globals + 1);    ts = &s->temps[s->nb_globals];    ts->base_type = type;    ts->type = type;    ts->fixed_reg = 1;    ts->reg = reg;    ts->val_type = TEMP_VAL_REG;    ts->name = name;    s->nb_globals++;    tcg_regset_set_reg(s->reserved_regs, reg);    return MAKE_TCGV(idx);}#if TCG_TARGET_REG_BITS == 32/* temporary hack to avoid register shortage for tcg_qemu_st64() */TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,                               const char *name){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;    int idx;    char buf[64];    if (type != TCG_TYPE_I64)        tcg_abort();    idx = s->nb_globals;    tcg_temp_alloc(s, s->nb_globals + 2);    ts = &s->temps[s->nb_globals];    ts->base_type = type;    ts->type = TCG_TYPE_I32;    ts->fixed_reg = 1;    ts->reg = reg1;    ts->val_type = TEMP_VAL_REG;    pstrcpy(buf, sizeof(buf), name);    pstrcat(buf, sizeof(buf), "_0");    ts->name = strdup(buf);    ts++;    ts->base_type = type;    ts->type = TCG_TYPE_I32;    ts->fixed_reg = 1;    ts->reg = reg2;    ts->val_type = TEMP_VAL_REG;    pstrcpy(buf, sizeof(buf), name);    pstrcat(buf, sizeof(buf), "_1");    ts->name = strdup(buf);    s->nb_globals += 2;    return MAKE_TCGV(idx);}#endifTCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,                        const char *name){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;    int idx;    idx = s->nb_globals;#if TCG_TARGET_REG_BITS == 32    if (type == TCG_TYPE_I64) {        char buf[64];        tcg_temp_alloc(s, s->nb_globals + 1);        ts = &s->temps[s->nb_globals];        ts->base_type = type;        ts->type = TCG_TYPE_I32;        ts->fixed_reg = 0;        ts->mem_allocated = 1;        ts->mem_reg = reg;#ifdef TCG_TARGET_WORDS_BIGENDIAN        ts->mem_offset = offset + 4;#else        ts->mem_offset = offset;#endif        ts->val_type = TEMP_VAL_MEM;        pstrcpy(buf, sizeof(buf), name);        pstrcat(buf, sizeof(buf), "_0");        ts->name = strdup(buf);        ts++;        ts->base_type = type;        ts->type = TCG_TYPE_I32;        ts->fixed_reg = 0;        ts->mem_allocated = 1;        ts->mem_reg = reg;#ifdef TCG_TARGET_WORDS_BIGENDIAN        ts->mem_offset = offset;#else        ts->mem_offset = offset + 4;#endif        ts->val_type = TEMP_VAL_MEM;        pstrcpy(buf, sizeof(buf), name);        pstrcat(buf, sizeof(buf), "_1");        ts->name = strdup(buf);        s->nb_globals += 2;    } else#endif    {        tcg_temp_alloc(s, s->nb_globals + 1);        ts = &s->temps[s->nb_globals];        ts->base_type = type;        ts->type = type;        ts->fixed_reg = 0;        ts->mem_allocated = 1;        ts->mem_reg = reg;        ts->mem_offset = offset;        ts->val_type = TEMP_VAL_MEM;        ts->name = name;        s->nb_globals++;    }    return MAKE_TCGV(idx);}TCGv tcg_temp_new(TCGType type){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;    int idx;    idx = s->nb_temps;#if TCG_TARGET_REG_BITS == 32    if (type == TCG_TYPE_I64) {        tcg_temp_alloc(s, s->nb_temps + 1);        ts = &s->temps[s->nb_temps];        ts->base_type = type;        ts->type = TCG_TYPE_I32;        ts->fixed_reg = 0;        ts->val_type = TEMP_VAL_DEAD;        ts->mem_allocated = 0;        ts->name = NULL;        ts++;        ts->base_type = TCG_TYPE_I32;        ts->type = TCG_TYPE_I32;        ts->val_type = TEMP_VAL_DEAD;        ts->fixed_reg = 0;        ts->mem_allocated = 0;        ts->name = NULL;        s->nb_temps += 2;    } else#endif    {        tcg_temp_alloc(s, s->nb_temps + 1);        ts = &s->temps[s->nb_temps];        ts->base_type = type;        ts->type = type;        ts->fixed_reg = 0;        ts->val_type = TEMP_VAL_DEAD;        ts->mem_allocated = 0;        ts->name = NULL;        s->nb_temps++;    }    return MAKE_TCGV(idx);}TCGv tcg_const_i32(int32_t val){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;    int idx;    idx = s->nb_temps;    tcg_temp_alloc(s, idx + 1);    ts = &s->temps[idx];    ts->base_type = ts->type = TCG_TYPE_I32;    ts->val_type = TEMP_VAL_CONST;    ts->name = NULL;    ts->val = val;    s->nb_temps++;    return MAKE_TCGV(idx);}TCGv tcg_const_i64(int64_t val){    TCGContext *s = &tcg_ctx;    TCGTemp *ts;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?