File:  [Qemu by Fabrice Bellard] / qemu / translate-all.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:31 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.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, write to the Free Software
   18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
   19:  */
   20: #include <stdarg.h>
   21: #include <stdlib.h>
   22: #include <stdio.h>
   23: #include <string.h>
   24: #include <inttypes.h>
   25: 
   26: #include "config.h"
   27: 
   28: #define NO_CPU_IO_DEFS
   29: #include "cpu.h"
   30: #include "exec-all.h"
   31: #include "disas.h"
   32: #include "tcg.h"
   33: 
   34: /* code generation context */
   35: TCGContext tcg_ctx;
   36: 
   37: uint16_t gen_opc_buf[OPC_BUF_SIZE];
   38: TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
   39: 
   40: target_ulong gen_opc_pc[OPC_BUF_SIZE];
   41: uint16_t gen_opc_icount[OPC_BUF_SIZE];
   42: uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
   43: #if defined(TARGET_I386)
   44: uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
   45: #elif defined(TARGET_SPARC)
   46: target_ulong gen_opc_npc[OPC_BUF_SIZE];
   47: target_ulong gen_opc_jump_pc[2];
   48: #elif defined(TARGET_MIPS) || defined(TARGET_SH4)
   49: uint32_t gen_opc_hflags[OPC_BUF_SIZE];
   50: #endif
   51: 
   52: /* XXX: suppress that */
   53: unsigned long code_gen_max_block_size(void)
   54: {
   55:     static unsigned long max;
   56: 
   57:     if (max == 0) {
   58:         max = TCG_MAX_OP_SIZE;
   59: #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
   60: #include "tcg-opc.h"
   61: #undef DEF
   62:         max *= OPC_MAX_SIZE;
   63:     }
   64: 
   65:     return max;
   66: }
   67: 
   68: void cpu_gen_init(void)
   69: {
   70:     tcg_context_init(&tcg_ctx); 
   71:     tcg_set_frame(&tcg_ctx, TCG_AREG0, offsetof(CPUState, temp_buf),
   72:                   CPU_TEMP_BUF_NLONGS * sizeof(long));
   73: }
   74: 
   75: /* return non zero if the very first instruction is invalid so that
   76:    the virtual CPU can trigger an exception.
   77: 
   78:    '*gen_code_size_ptr' contains the size of the generated code (host
   79:    code).
   80: */
   81: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
   82: {
   83:     TCGContext *s = &tcg_ctx;
   84:     uint8_t *gen_code_buf;
   85:     int gen_code_size;
   86: #ifdef CONFIG_PROFILER
   87:     int64_t ti;
   88: #endif
   89: 
   90: #ifdef CONFIG_PROFILER
   91:     s->tb_count1++; /* includes aborted translations because of
   92:                        exceptions */
   93:     ti = profile_getclock();
   94: #endif
   95:     tcg_func_start(s);
   96: 
   97:     gen_intermediate_code(env, tb);
   98: 
   99:     /* generate machine code */
  100:     gen_code_buf = tb->tc_ptr;
  101:     tb->tb_next_offset[0] = 0xffff;
  102:     tb->tb_next_offset[1] = 0xffff;
  103:     s->tb_next_offset = tb->tb_next_offset;
  104: #ifdef USE_DIRECT_JUMP
  105:     s->tb_jmp_offset = tb->tb_jmp_offset;
  106:     s->tb_next = NULL;
  107:     /* the following two entries are optional (only used for string ops) */
  108:     /* XXX: not used ? */
  109:     tb->tb_jmp_offset[2] = 0xffff;
  110:     tb->tb_jmp_offset[3] = 0xffff;
  111: #else
  112:     s->tb_jmp_offset = NULL;
  113:     s->tb_next = tb->tb_next;
  114: #endif
  115: 
  116: #ifdef CONFIG_PROFILER
  117:     s->tb_count++;
  118:     s->interm_time += profile_getclock() - ti;
  119:     s->code_time -= profile_getclock();
  120: #endif
  121:     gen_code_size = tcg_gen_code(s, gen_code_buf);
  122:     *gen_code_size_ptr = gen_code_size;
  123: #ifdef CONFIG_PROFILER
  124:     s->code_time += profile_getclock();
  125:     s->code_in_len += tb->size;
  126:     s->code_out_len += gen_code_size;
  127: #endif
  128: 
  129: #ifdef DEBUG_DISAS
  130:     if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
  131:         qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
  132:         log_disas(tb->tc_ptr, *gen_code_size_ptr);
  133:         qemu_log("\n");
  134:         qemu_log_flush();
  135:     }
  136: #endif
  137:     return 0;
  138: }
  139: 
  140: /* The cpu state corresponding to 'searched_pc' is restored.
  141:  */
  142: int cpu_restore_state(TranslationBlock *tb,
  143:                       CPUState *env, unsigned long searched_pc,
  144:                       void *puc)
  145: {
  146:     TCGContext *s = &tcg_ctx;
  147:     int j;
  148:     unsigned long tc_ptr;
  149: #ifdef CONFIG_PROFILER
  150:     int64_t ti;
  151: #endif
  152: 
  153: #ifdef CONFIG_PROFILER
  154:     ti = profile_getclock();
  155: #endif
  156:     tcg_func_start(s);
  157: 
  158:     gen_intermediate_code_pc(env, tb);
  159: 
  160:     if (use_icount) {
  161:         /* Reset the cycle counter to the start of the block.  */
  162:         env->icount_decr.u16.low += tb->icount;
  163:         /* Clear the IO flag.  */
  164:         env->can_do_io = 0;
  165:     }
  166: 
  167:     /* find opc index corresponding to search_pc */
  168:     tc_ptr = (unsigned long)tb->tc_ptr;
  169:     if (searched_pc < tc_ptr)
  170:         return -1;
  171: 
  172:     s->tb_next_offset = tb->tb_next_offset;
  173: #ifdef USE_DIRECT_JUMP
  174:     s->tb_jmp_offset = tb->tb_jmp_offset;
  175:     s->tb_next = NULL;
  176: #else
  177:     s->tb_jmp_offset = NULL;
  178:     s->tb_next = tb->tb_next;
  179: #endif
  180:     j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
  181:     if (j < 0)
  182:         return -1;
  183:     /* now find start of instruction before */
  184:     while (gen_opc_instr_start[j] == 0)
  185:         j--;
  186:     env->icount_decr.u16.low -= gen_opc_icount[j];
  187: 
  188:     gen_pc_load(env, tb, searched_pc, j, puc);
  189: 
  190: #ifdef CONFIG_PROFILER
  191:     s->restore_time += profile_getclock() - ti;
  192:     s->restore_count++;
  193: #endif
  194:     return 0;
  195: }

unix.superglobalmegacorp.com