Annotation of qemu/translate-all.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  *  Host code generation
1.1.1.4   root        3:  *
1.1       root        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
1.1.1.6   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       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"
1.1.1.5   root       30: #include "tcg.h"
1.1.1.7   root       31: #include "qemu-timer.h"
1.1       root       32: 
1.1.1.5   root       33: /* code generation context */
                     34: TCGContext tcg_ctx;
1.1       root       35: 
                     36: uint16_t gen_opc_buf[OPC_BUF_SIZE];
1.1.1.5   root       37: TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
1.1       root       38: 
                     39: target_ulong gen_opc_pc[OPC_BUF_SIZE];
1.1.1.5   root       40: uint16_t gen_opc_icount[OPC_BUF_SIZE];
1.1       root       41: uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
1.1.1.4   root       42: 
1.1.1.5   root       43: void cpu_gen_init(void)
                     44: {
                     45:     tcg_context_init(&tcg_ctx); 
                     46: }
                     47: 
1.1       root       48: /* return non zero if the very first instruction is invalid so that
1.1.1.4   root       49:    the virtual CPU can trigger an exception.
1.1       root       50: 
                     51:    '*gen_code_size_ptr' contains the size of the generated code (host
                     52:    code).
                     53: */
1.1.1.4   root       54: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
1.1       root       55: {
1.1.1.5   root       56:     TCGContext *s = &tcg_ctx;
1.1       root       57:     uint8_t *gen_code_buf;
                     58:     int gen_code_size;
1.1.1.5   root       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);
1.1       root       71: 
1.1.1.4   root       72:     /* generate machine code */
1.1.1.5   root       73:     gen_code_buf = tb->tc_ptr;
1.1.1.4   root       74:     tb->tb_next_offset[0] = 0xffff;
                     75:     tb->tb_next_offset[1] = 0xffff;
1.1.1.5   root       76:     s->tb_next_offset = tb->tb_next_offset;
1.1       root       77: #ifdef USE_DIRECT_JUMP
1.1.1.5   root       78:     s->tb_jmp_offset = tb->tb_jmp_offset;
                     79:     s->tb_next = NULL;
1.1       root       80: #else
1.1.1.5   root       81:     s->tb_jmp_offset = NULL;
                     82:     s->tb_next = tb->tb_next;
1.1       root       83: #endif
1.1.1.5   root       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);
1.1       root       91:     *gen_code_size_ptr = gen_code_size;
1.1.1.5   root       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: 
1.1       root       98: #ifdef DEBUG_DISAS
1.1.1.5   root       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();
1.1       root      104:     }
                    105: #endif
                    106:     return 0;
                    107: }
                    108: 
1.1.1.4   root      109: /* The cpu state corresponding to 'searched_pc' is restored.
1.1       root      110:  */
1.1.1.4   root      111: int cpu_restore_state(TranslationBlock *tb,
1.1.1.8 ! root      112:                       CPUState *env, unsigned long searched_pc)
1.1       root      113: {
1.1.1.5   root      114:     TCGContext *s = &tcg_ctx;
                    115:     int j;
1.1       root      116:     unsigned long tc_ptr;
1.1.1.5   root      117: #ifdef CONFIG_PROFILER
                    118:     int64_t ti;
                    119: #endif
1.1       root      120: 
1.1.1.5   root      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:     }
1.1.1.4   root      134: 
1.1       root      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;
1.1.1.5   root      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;
1.1       root      151:     /* now find start of instruction before */
                    152:     while (gen_opc_instr_start[j] == 0)
                    153:         j--;
1.1.1.5   root      154:     env->icount_decr.u16.low -= gen_opc_icount[j];
                    155: 
1.1.1.8 ! root      156:     restore_state_to_opc(env, tb, j);
1.1.1.5   root      157: 
                    158: #ifdef CONFIG_PROFILER
                    159:     s->restore_time += profile_getclock() - ti;
                    160:     s->restore_count++;
1.1       root      161: #endif
                    162:     return 0;
                    163: }

unix.superglobalmegacorp.com