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

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
                     17:  * License along with this library; if not, write to the Free Software
1.1.1.5 ! root       18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
1.1       root       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"
1.1.1.5 ! root       32: #include "tcg.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];
                     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];
1.1.1.4   root       48: #elif defined(TARGET_MIPS) || defined(TARGET_SH4)
1.1.1.2   root       49: uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1.1       root       50: #endif
                     51: 
1.1.1.5 ! root       52: /* XXX: suppress that */
1.1.1.4   root       53: unsigned long code_gen_max_block_size(void)
                     54: {
                     55:     static unsigned long max;
                     56: 
                     57:     if (max == 0) {
1.1.1.5 ! root       58:         max = TCG_MAX_OP_SIZE;
1.1.1.4   root       59: #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
1.1.1.5 ! root       60: #include "tcg-opc.h"
1.1.1.4   root       61: #undef DEF
                     62:         max *= OPC_MAX_SIZE;
                     63:     }
                     64: 
                     65:     return max;
                     66: }
                     67: 
1.1.1.5 ! root       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: 
1.1       root       75: /* return non zero if the very first instruction is invalid so that
1.1.1.4   root       76:    the virtual CPU can trigger an exception.
1.1       root       77: 
                     78:    '*gen_code_size_ptr' contains the size of the generated code (host
                     79:    code).
                     80: */
1.1.1.4   root       81: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
1.1       root       82: {
1.1.1.5 ! root       83:     TCGContext *s = &tcg_ctx;
1.1       root       84:     uint8_t *gen_code_buf;
                     85:     int gen_code_size;
1.1.1.5 ! root       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);
1.1       root       98: 
1.1.1.4   root       99:     /* generate machine code */
1.1.1.5 ! root      100:     gen_code_buf = tb->tc_ptr;
1.1.1.4   root      101:     tb->tb_next_offset[0] = 0xffff;
                    102:     tb->tb_next_offset[1] = 0xffff;
1.1.1.5 ! root      103:     s->tb_next_offset = tb->tb_next_offset;
1.1       root      104: #ifdef USE_DIRECT_JUMP
1.1.1.5 ! root      105:     s->tb_jmp_offset = tb->tb_jmp_offset;
        !           106:     s->tb_next = NULL;
1.1.1.4   root      107:     /* the following two entries are optional (only used for string ops) */
1.1.1.5 ! root      108:     /* XXX: not used ? */
1.1.1.4   root      109:     tb->tb_jmp_offset[2] = 0xffff;
                    110:     tb->tb_jmp_offset[3] = 0xffff;
1.1       root      111: #else
1.1.1.5 ! root      112:     s->tb_jmp_offset = NULL;
        !           113:     s->tb_next = tb->tb_next;
1.1       root      114: #endif
1.1.1.5 ! root      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);
1.1       root      122:     *gen_code_size_ptr = gen_code_size;
1.1.1.5 ! root      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: 
1.1       root      129: #ifdef DEBUG_DISAS
1.1.1.5 ! root      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();
1.1       root      135:     }
                    136: #endif
                    137:     return 0;
                    138: }
                    139: 
1.1.1.4   root      140: /* The cpu state corresponding to 'searched_pc' is restored.
1.1       root      141:  */
1.1.1.4   root      142: int cpu_restore_state(TranslationBlock *tb,
1.1       root      143:                       CPUState *env, unsigned long searched_pc,
                    144:                       void *puc)
                    145: {
1.1.1.5 ! root      146:     TCGContext *s = &tcg_ctx;
        !           147:     int j;
1.1       root      148:     unsigned long tc_ptr;
1.1.1.5 ! root      149: #ifdef CONFIG_PROFILER
        !           150:     int64_t ti;
        !           151: #endif
1.1       root      152: 
1.1.1.5 ! root      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:     }
1.1.1.4   root      166: 
1.1       root      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;
1.1.1.5 ! root      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;
1.1       root      183:     /* now find start of instruction before */
                    184:     while (gen_opc_instr_start[j] == 0)
                    185:         j--;
1.1.1.5 ! root      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++;
1.1       root      193: #endif
                    194:     return 0;
                    195: }

unix.superglobalmegacorp.com