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

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

unix.superglobalmegacorp.com