File:  [Qemu by Fabrice Bellard] / qemu / translate-all.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:20:37 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, qemu0111, qemu0110, HEAD
qemu 0.11.0

    1: /*
    2:  *  Host code generation
    3:  *
    4:  *  Copyright (c) 2003 Fabrice Bellard
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library is distributed in the hope that it will be useful,
   12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
   18:  */
   19: #include <stdarg.h>
   20: #include <stdlib.h>
   21: #include <stdio.h>
   22: #include <string.h>
   23: #include <inttypes.h>
   24: 
   25: #include "config.h"
   26: 
   27: #define NO_CPU_IO_DEFS
   28: #include "cpu.h"
   29: #include "exec-all.h"
   30: #include "disas.h"
   31: #include "tcg.h"
   32: 
   33: /* code generation context */
   34: TCGContext tcg_ctx;
   35: 
   36: uint16_t gen_opc_buf[OPC_BUF_SIZE];
   37: TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
   38: 
   39: target_ulong gen_opc_pc[OPC_BUF_SIZE];
   40: uint16_t gen_opc_icount[OPC_BUF_SIZE];
   41: uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
   42: #if defined(TARGET_I386)
   43: uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
   44: #elif defined(TARGET_SPARC)
   45: target_ulong gen_opc_npc[OPC_BUF_SIZE];
   46: target_ulong gen_opc_jump_pc[2];
   47: #elif defined(TARGET_MIPS) || defined(TARGET_SH4)
   48: uint32_t gen_opc_hflags[OPC_BUF_SIZE];
   49: #endif
   50: 
   51: /* XXX: suppress that */
   52: unsigned long code_gen_max_block_size(void)
   53: {
   54:     static unsigned long max;
   55: 
   56:     if (max == 0) {
   57:         max = TCG_MAX_OP_SIZE;
   58: #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
   59: #include "tcg-opc.h"
   60: #undef DEF
   61:         max *= OPC_MAX_SIZE;
   62:     }
   63: 
   64:     return max;
   65: }
   66: 
   67: void cpu_gen_init(void)
   68: {
   69:     tcg_context_init(&tcg_ctx); 
   70:     tcg_set_frame(&tcg_ctx, TCG_AREG0, offsetof(CPUState, temp_buf),
   71:                   CPU_TEMP_BUF_NLONGS * sizeof(long));
   72: }
   73: 
   74: /* return non zero if the very first instruction is invalid so that
   75:    the virtual CPU can trigger an exception.
   76: 
   77:    '*gen_code_size_ptr' contains the size of the generated code (host
   78:    code).
   79: */
   80: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
   81: {
   82:     TCGContext *s = &tcg_ctx;
   83:     uint8_t *gen_code_buf;
   84:     int gen_code_size;
   85: #ifdef CONFIG_PROFILER
   86:     int64_t ti;
   87: #endif
   88: 
   89: #ifdef CONFIG_PROFILER
   90:     s->tb_count1++; /* includes aborted translations because of
   91:                        exceptions */
   92:     ti = profile_getclock();
   93: #endif
   94:     tcg_func_start(s);
   95: 
   96:     gen_intermediate_code(env, tb);
   97: 
   98:     /* generate machine code */
   99:     gen_code_buf = tb->tc_ptr;
  100:     tb->tb_next_offset[0] = 0xffff;
  101:     tb->tb_next_offset[1] = 0xffff;
  102:     s->tb_next_offset = tb->tb_next_offset;
  103: #ifdef USE_DIRECT_JUMP
  104:     s->tb_jmp_offset = tb->tb_jmp_offset;
  105:     s->tb_next = NULL;
  106:     /* the following two entries are optional (only used for string ops) */
  107:     /* XXX: not used ? */
  108:     tb->tb_jmp_offset[2] = 0xffff;
  109:     tb->tb_jmp_offset[3] = 0xffff;
  110: #else
  111:     s->tb_jmp_offset = NULL;
  112:     s->tb_next = tb->tb_next;
  113: #endif
  114: 
  115: #ifdef CONFIG_PROFILER
  116:     s->tb_count++;
  117:     s->interm_time += profile_getclock() - ti;
  118:     s->code_time -= profile_getclock();
  119: #endif
  120:     gen_code_size = tcg_gen_code(s, gen_code_buf);
  121:     *gen_code_size_ptr = gen_code_size;
  122: #ifdef CONFIG_PROFILER
  123:     s->code_time += profile_getclock();
  124:     s->code_in_len += tb->size;
  125:     s->code_out_len += gen_code_size;
  126: #endif
  127: 
  128: #ifdef DEBUG_DISAS
  129:     if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
  130:         qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
  131:         log_disas(tb->tc_ptr, *gen_code_size_ptr);
  132:         qemu_log("\n");
  133:         qemu_log_flush();
  134:     }
  135: #endif
  136:     return 0;
  137: }
  138: 
  139: /* The cpu state corresponding to 'searched_pc' is restored.
  140:  */
  141: int cpu_restore_state(TranslationBlock *tb,
  142:                       CPUState *env, unsigned long searched_pc,
  143:                       void *puc)
  144: {
  145:     TCGContext *s = &tcg_ctx;
  146:     int j;
  147:     unsigned long tc_ptr;
  148: #ifdef CONFIG_PROFILER
  149:     int64_t ti;
  150: #endif
  151: 
  152: #ifdef CONFIG_PROFILER
  153:     ti = profile_getclock();
  154: #endif
  155:     tcg_func_start(s);
  156: 
  157:     gen_intermediate_code_pc(env, tb);
  158: 
  159:     if (use_icount) {
  160:         /* Reset the cycle counter to the start of the block.  */
  161:         env->icount_decr.u16.low += tb->icount;
  162:         /* Clear the IO flag.  */
  163:         env->can_do_io = 0;
  164:     }
  165: 
  166:     /* find opc index corresponding to search_pc */
  167:     tc_ptr = (unsigned long)tb->tc_ptr;
  168:     if (searched_pc < tc_ptr)
  169:         return -1;
  170: 
  171:     s->tb_next_offset = tb->tb_next_offset;
  172: #ifdef USE_DIRECT_JUMP
  173:     s->tb_jmp_offset = tb->tb_jmp_offset;
  174:     s->tb_next = NULL;
  175: #else
  176:     s->tb_jmp_offset = NULL;
  177:     s->tb_next = tb->tb_next;
  178: #endif
  179:     j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
  180:     if (j < 0)
  181:         return -1;
  182:     /* now find start of instruction before */
  183:     while (gen_opc_instr_start[j] == 0)
  184:         j--;
  185:     env->icount_decr.u16.low -= gen_opc_icount[j];
  186: 
  187:     gen_pc_load(env, tb, searched_pc, j, puc);
  188: 
  189: #ifdef CONFIG_PROFILER
  190:     s->restore_time += profile_getclock() - ti;
  191:     s->restore_count++;
  192: #endif
  193:     return 0;
  194: }

unix.superglobalmegacorp.com