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