File:  [Qemu by Fabrice Bellard] / qemu / translate-all.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:56:00 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, qemu1000, qemu0151, HEAD
qemu 0.15.1

    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 "disas.h"
   30: #include "tcg.h"
   31: #include "qemu-timer.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: 
   43: void cpu_gen_init(void)
   44: {
   45:     tcg_context_init(&tcg_ctx); 
   46: }
   47: 
   48: /* return non zero if the very first instruction is invalid so that
   49:    the virtual CPU can trigger an exception.
   50: 
   51:    '*gen_code_size_ptr' contains the size of the generated code (host
   52:    code).
   53: */
   54: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
   55: {
   56:     TCGContext *s = &tcg_ctx;
   57:     uint8_t *gen_code_buf;
   58:     int gen_code_size;
   59: #ifdef CONFIG_PROFILER
   60:     int64_t ti;
   61: #endif
   62: 
   63: #ifdef CONFIG_PROFILER
   64:     s->tb_count1++; /* includes aborted translations because of
   65:                        exceptions */
   66:     ti = profile_getclock();
   67: #endif
   68:     tcg_func_start(s);
   69: 
   70:     gen_intermediate_code(env, tb);
   71: 
   72:     /* generate machine code */
   73:     gen_code_buf = tb->tc_ptr;
   74:     tb->tb_next_offset[0] = 0xffff;
   75:     tb->tb_next_offset[1] = 0xffff;
   76:     s->tb_next_offset = tb->tb_next_offset;
   77: #ifdef USE_DIRECT_JUMP
   78:     s->tb_jmp_offset = tb->tb_jmp_offset;
   79:     s->tb_next = NULL;
   80: #else
   81:     s->tb_jmp_offset = NULL;
   82:     s->tb_next = tb->tb_next;
   83: #endif
   84: 
   85: #ifdef CONFIG_PROFILER
   86:     s->tb_count++;
   87:     s->interm_time += profile_getclock() - ti;
   88:     s->code_time -= profile_getclock();
   89: #endif
   90:     gen_code_size = tcg_gen_code(s, gen_code_buf);
   91:     *gen_code_size_ptr = gen_code_size;
   92: #ifdef CONFIG_PROFILER
   93:     s->code_time += profile_getclock();
   94:     s->code_in_len += tb->size;
   95:     s->code_out_len += gen_code_size;
   96: #endif
   97: 
   98: #ifdef DEBUG_DISAS
   99:     if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
  100:         qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
  101:         log_disas(tb->tc_ptr, *gen_code_size_ptr);
  102:         qemu_log("\n");
  103:         qemu_log_flush();
  104:     }
  105: #endif
  106:     return 0;
  107: }
  108: 
  109: /* The cpu state corresponding to 'searched_pc' is restored.
  110:  */
  111: int cpu_restore_state(TranslationBlock *tb,
  112:                       CPUState *env, unsigned long searched_pc)
  113: {
  114:     TCGContext *s = &tcg_ctx;
  115:     int j;
  116:     unsigned long tc_ptr;
  117: #ifdef CONFIG_PROFILER
  118:     int64_t ti;
  119: #endif
  120: 
  121: #ifdef CONFIG_PROFILER
  122:     ti = profile_getclock();
  123: #endif
  124:     tcg_func_start(s);
  125: 
  126:     gen_intermediate_code_pc(env, tb);
  127: 
  128:     if (use_icount) {
  129:         /* Reset the cycle counter to the start of the block.  */
  130:         env->icount_decr.u16.low += tb->icount;
  131:         /* Clear the IO flag.  */
  132:         env->can_do_io = 0;
  133:     }
  134: 
  135:     /* find opc index corresponding to search_pc */
  136:     tc_ptr = (unsigned long)tb->tc_ptr;
  137:     if (searched_pc < tc_ptr)
  138:         return -1;
  139: 
  140:     s->tb_next_offset = tb->tb_next_offset;
  141: #ifdef USE_DIRECT_JUMP
  142:     s->tb_jmp_offset = tb->tb_jmp_offset;
  143:     s->tb_next = NULL;
  144: #else
  145:     s->tb_jmp_offset = NULL;
  146:     s->tb_next = tb->tb_next;
  147: #endif
  148:     j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
  149:     if (j < 0)
  150:         return -1;
  151:     /* now find start of instruction before */
  152:     while (gen_opc_instr_start[j] == 0)
  153:         j--;
  154:     env->icount_decr.u16.low -= gen_opc_icount[j];
  155: 
  156:     restore_state_to_opc(env, tb, j);
  157: 
  158: #ifdef CONFIG_PROFILER
  159:     s->restore_time += profile_getclock() - ti;
  160:     s->restore_count++;
  161: #endif
  162:     return 0;
  163: }

unix.superglobalmegacorp.com