Commit d19893dab57d29507ebec946f822a5894e873863
1 parent
2521d698
extracted generic code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@242 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
176 additions
and
233 deletions
translate-i386.c
@@ -25,97 +25,13 @@ | @@ -25,97 +25,13 @@ | ||
25 | #include <signal.h> | 25 | #include <signal.h> |
26 | #include <assert.h> | 26 | #include <assert.h> |
27 | 27 | ||
28 | -#include "disas.h" | ||
29 | - | ||
30 | -#define DEBUG_DISAS | ||
31 | - | ||
32 | -#define IN_OP_I386 | ||
33 | #include "cpu-i386.h" | 28 | #include "cpu-i386.h" |
34 | #include "exec.h" | 29 | #include "exec.h" |
30 | +#include "disas.h" | ||
35 | 31 | ||
36 | /* XXX: move that elsewhere */ | 32 | /* XXX: move that elsewhere */ |
37 | static uint16_t *gen_opc_ptr; | 33 | static uint16_t *gen_opc_ptr; |
38 | static uint32_t *gen_opparam_ptr; | 34 | static uint32_t *gen_opparam_ptr; |
39 | -int __op_param1, __op_param2, __op_param3; | ||
40 | -#ifdef USE_DIRECT_JUMP | ||
41 | -int __op_jmp0, __op_jmp1; | ||
42 | -#endif | ||
43 | - | ||
44 | -#ifdef __i386__ | ||
45 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
46 | -{ | ||
47 | -} | ||
48 | -#endif | ||
49 | - | ||
50 | -#ifdef __s390__ | ||
51 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
52 | -{ | ||
53 | -} | ||
54 | -#endif | ||
55 | - | ||
56 | -#ifdef __ia64__ | ||
57 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
58 | -{ | ||
59 | -} | ||
60 | -#endif | ||
61 | - | ||
62 | -#ifdef __powerpc__ | ||
63 | - | ||
64 | -#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ | ||
65 | - | ||
66 | -static void inline flush_icache_range(unsigned long start, unsigned long stop) | ||
67 | -{ | ||
68 | - unsigned long p; | ||
69 | - | ||
70 | - p = start & ~(MIN_CACHE_LINE_SIZE - 1); | ||
71 | - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); | ||
72 | - | ||
73 | - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | ||
74 | - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); | ||
75 | - } | ||
76 | - asm volatile ("sync" : : : "memory"); | ||
77 | - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | ||
78 | - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); | ||
79 | - } | ||
80 | - asm volatile ("sync" : : : "memory"); | ||
81 | - asm volatile ("isync" : : : "memory"); | ||
82 | -} | ||
83 | -#endif | ||
84 | - | ||
85 | -#ifdef __alpha__ | ||
86 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
87 | -{ | ||
88 | - asm ("imb"); | ||
89 | -} | ||
90 | -#endif | ||
91 | - | ||
92 | -#ifdef __sparc__ | ||
93 | - | ||
94 | -static void inline flush_icache_range(unsigned long start, unsigned long stop) | ||
95 | -{ | ||
96 | - unsigned long p; | ||
97 | - | ||
98 | - p = start & ~(8UL - 1UL); | ||
99 | - stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL); | ||
100 | - | ||
101 | - for (; p < stop; p += 8) | ||
102 | - __asm__ __volatile__("flush\t%0" : : "r" (p)); | ||
103 | -} | ||
104 | - | ||
105 | -#endif | ||
106 | - | ||
107 | -#ifdef __arm__ | ||
108 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
109 | -{ | ||
110 | - register unsigned long _beg __asm ("a1") = start; | ||
111 | - register unsigned long _end __asm ("a2") = stop; | ||
112 | - register unsigned long _flg __asm ("a3") = 0; | ||
113 | - __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); | ||
114 | -} | ||
115 | -#endif | ||
116 | - | ||
117 | -extern FILE *logfile; | ||
118 | -extern int loglevel; | ||
119 | 35 | ||
120 | #define PREFIX_REPZ 0x01 | 36 | #define PREFIX_REPZ 0x01 |
121 | #define PREFIX_REPNZ 0x02 | 37 | #define PREFIX_REPNZ 0x02 |
@@ -142,7 +58,7 @@ typedef struct DisasContext { | @@ -142,7 +58,7 @@ typedef struct DisasContext { | ||
142 | int cpl; | 58 | int cpl; |
143 | int iopl; | 59 | int iopl; |
144 | int tf; /* TF cpu flag */ | 60 | int tf; /* TF cpu flag */ |
145 | - TranslationBlock *tb; | 61 | + struct TranslationBlock *tb; |
146 | } DisasContext; | 62 | } DisasContext; |
147 | 63 | ||
148 | /* i386 arith/logic operations */ | 64 | /* i386 arith/logic operations */ |
@@ -176,8 +92,7 @@ enum { | @@ -176,8 +92,7 @@ enum { | ||
176 | NB_OPS, | 92 | NB_OPS, |
177 | }; | 93 | }; |
178 | 94 | ||
179 | -#include "dyngen.h" | ||
180 | -#include "op-i386.h" | 95 | +#include "gen-op-i386.h" |
181 | 96 | ||
182 | /* operand size */ | 97 | /* operand size */ |
183 | enum { | 98 | enum { |
@@ -3748,61 +3663,10 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | @@ -3748,61 +3663,10 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | ||
3748 | } | 3663 | } |
3749 | } | 3664 | } |
3750 | 3665 | ||
3751 | - | ||
3752 | -#ifdef DEBUG_DISAS | ||
3753 | -static const char *op_str[] = { | ||
3754 | -#define DEF(s, n, copy_size) #s, | ||
3755 | -#include "opc-i386.h" | ||
3756 | -#undef DEF | ||
3757 | -}; | ||
3758 | - | ||
3759 | -static uint8_t op_nb_args[] = { | ||
3760 | -#define DEF(s, n, copy_size) n, | ||
3761 | -#include "opc-i386.h" | ||
3762 | -#undef DEF | ||
3763 | -}; | ||
3764 | - | ||
3765 | -static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | ||
3766 | -{ | ||
3767 | - const uint16_t *opc_ptr; | ||
3768 | - const uint32_t *opparam_ptr; | ||
3769 | - int c, n, i; | ||
3770 | - | ||
3771 | - opc_ptr = opc_buf; | ||
3772 | - opparam_ptr = opparam_buf; | ||
3773 | - for(;;) { | ||
3774 | - c = *opc_ptr++; | ||
3775 | - n = op_nb_args[c]; | ||
3776 | - fprintf(logfile, "0x%04x: %s", | ||
3777 | - (int)(opc_ptr - opc_buf - 1), op_str[c]); | ||
3778 | - for(i = 0; i < n; i++) { | ||
3779 | - fprintf(logfile, " 0x%x", opparam_ptr[i]); | ||
3780 | - } | ||
3781 | - fprintf(logfile, "\n"); | ||
3782 | - if (c == INDEX_op_end) | ||
3783 | - break; | ||
3784 | - opparam_ptr += n; | ||
3785 | - } | ||
3786 | -} | ||
3787 | - | ||
3788 | -#endif | ||
3789 | - | ||
3790 | -/* XXX: make safe guess about sizes */ | ||
3791 | -#define MAX_OP_PER_INSTR 32 | ||
3792 | -#define OPC_BUF_SIZE 512 | ||
3793 | -#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) | ||
3794 | - | ||
3795 | -#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3) | ||
3796 | - | ||
3797 | -static uint16_t gen_opc_buf[OPC_BUF_SIZE]; | ||
3798 | -static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | ||
3799 | -static uint32_t gen_opc_pc[OPC_BUF_SIZE]; | ||
3800 | -static uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | ||
3801 | - | ||
3802 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 3666 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
3803 | basic block 'tb'. If search_pc is TRUE, also generate PC | 3667 | basic block 'tb'. If search_pc is TRUE, also generate PC |
3804 | information for each intermediate instruction. */ | 3668 | information for each intermediate instruction. */ |
3805 | -static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | 3669 | +int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
3806 | { | 3670 | { |
3807 | DisasContext dc1, *dc = &dc1; | 3671 | DisasContext dc1, *dc = &dc1; |
3808 | uint8_t *pc_ptr; | 3672 | uint8_t *pc_ptr; |
@@ -3833,7 +3697,7 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3833,7 +3697,7 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3833 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | 3697 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
3834 | gen_opparam_ptr = gen_opparam_buf; | 3698 | gen_opparam_ptr = gen_opparam_buf; |
3835 | 3699 | ||
3836 | - dc->is_jmp = 0; | 3700 | + dc->is_jmp = DISAS_NEXT; |
3837 | pc_ptr = pc_start; | 3701 | pc_ptr = pc_start; |
3838 | lj = -1; | 3702 | lj = -1; |
3839 | do { | 3703 | do { |
@@ -3865,10 +3729,10 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3865,10 +3729,10 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3865 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && | 3729 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
3866 | (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32)); | 3730 | (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32)); |
3867 | /* we must store the eflags state if it is not already done */ | 3731 | /* we must store the eflags state if it is not already done */ |
3868 | - if (dc->is_jmp != 3) { | 3732 | + if (dc->is_jmp != DISAS_TB_JUMP) { |
3869 | if (dc->cc_op != CC_OP_DYNAMIC) | 3733 | if (dc->cc_op != CC_OP_DYNAMIC) |
3870 | gen_op_set_cc_op(dc->cc_op); | 3734 | gen_op_set_cc_op(dc->cc_op); |
3871 | - if (dc->is_jmp != 1) { | 3735 | + if (dc->is_jmp != DISAS_JUMP) { |
3872 | /* we add an additionnal jmp to update the simulated PC */ | 3736 | /* we add an additionnal jmp to update the simulated PC */ |
3873 | gen_op_jmp_im(ret - (unsigned long)dc->cs_base); | 3737 | gen_op_jmp_im(ret - (unsigned long)dc->cs_base); |
3874 | } | 3738 | } |
@@ -3880,15 +3744,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3880,15 +3744,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3880 | /* indicate that the hash table must be used to find the next TB */ | 3744 | /* indicate that the hash table must be used to find the next TB */ |
3881 | gen_op_movl_T0_0(); | 3745 | gen_op_movl_T0_0(); |
3882 | } | 3746 | } |
3883 | - | ||
3884 | *gen_opc_ptr = INDEX_op_end; | 3747 | *gen_opc_ptr = INDEX_op_end; |
3885 | 3748 | ||
3886 | #ifdef DEBUG_DISAS | 3749 | #ifdef DEBUG_DISAS |
3887 | if (loglevel) { | 3750 | if (loglevel) { |
3888 | fprintf(logfile, "----------------\n"); | 3751 | fprintf(logfile, "----------------\n"); |
3889 | fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); | 3752 | fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
3890 | - disas(logfile, pc_start, pc_ptr - pc_start, | ||
3891 | - dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086); | 3753 | + disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32); |
3892 | fprintf(logfile, "\n"); | 3754 | fprintf(logfile, "\n"); |
3893 | 3755 | ||
3894 | fprintf(logfile, "OP:\n"); | 3756 | fprintf(logfile, "OP:\n"); |
@@ -3912,98 +3774,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | @@ -3912,98 +3774,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | ||
3912 | return 0; | 3774 | return 0; |
3913 | } | 3775 | } |
3914 | 3776 | ||
3915 | - | ||
3916 | -/* return non zero if the very first instruction is invalid so that | ||
3917 | - the virtual CPU can trigger an exception. | ||
3918 | - | ||
3919 | - '*gen_code_size_ptr' contains the size of the generated code (host | ||
3920 | - code). | ||
3921 | -*/ | ||
3922 | -int cpu_x86_gen_code(TranslationBlock *tb, | ||
3923 | - int max_code_size, int *gen_code_size_ptr) | ||
3924 | -{ | ||
3925 | - uint8_t *gen_code_buf; | ||
3926 | - int gen_code_size; | ||
3927 | - | ||
3928 | - if (gen_intermediate_code(tb, 0) < 0) | ||
3929 | - return -1; | ||
3930 | - | ||
3931 | - /* generate machine code */ | ||
3932 | - tb->tb_next_offset[0] = 0xffff; | ||
3933 | - tb->tb_next_offset[1] = 0xffff; | ||
3934 | - gen_code_buf = tb->tc_ptr; | ||
3935 | - gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, | ||
3936 | -#ifdef USE_DIRECT_JUMP | ||
3937 | - tb->tb_jmp_offset, | ||
3938 | -#else | ||
3939 | - NULL, | ||
3940 | -#endif | ||
3941 | - gen_opc_buf, gen_opparam_buf); | ||
3942 | - flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size)); | ||
3943 | - | ||
3944 | - *gen_code_size_ptr = gen_code_size; | ||
3945 | -#ifdef DEBUG_DISAS | ||
3946 | - if (loglevel) { | ||
3947 | - fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | ||
3948 | - disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET); | ||
3949 | - fprintf(logfile, "\n"); | ||
3950 | - fflush(logfile); | ||
3951 | - } | ||
3952 | -#endif | ||
3953 | - return 0; | ||
3954 | -} | ||
3955 | - | ||
3956 | -static const unsigned short opc_copy_size[] = { | ||
3957 | -#define DEF(s, n, copy_size) copy_size, | ||
3958 | -#include "opc-i386.h" | ||
3959 | -#undef DEF | ||
3960 | -}; | ||
3961 | - | ||
3962 | -/* The simulated PC corresponding to | ||
3963 | - 'searched_pc' in the generated code is searched. 0 is returned if | ||
3964 | - found. *found_pc contains the found PC. | ||
3965 | - */ | ||
3966 | -int cpu_x86_search_pc(TranslationBlock *tb, | ||
3967 | - uint32_t *found_pc, unsigned long searched_pc) | ||
3968 | -{ | ||
3969 | - int j, c; | ||
3970 | - unsigned long tc_ptr; | ||
3971 | - uint16_t *opc_ptr; | ||
3972 | - | ||
3973 | - if (gen_intermediate_code(tb, 1) < 0) | ||
3974 | - return -1; | ||
3975 | - | ||
3976 | - /* find opc index corresponding to search_pc */ | ||
3977 | - tc_ptr = (unsigned long)tb->tc_ptr; | ||
3978 | - if (searched_pc < tc_ptr) | ||
3979 | - return -1; | ||
3980 | - j = 0; | ||
3981 | - opc_ptr = gen_opc_buf; | ||
3982 | - for(;;) { | ||
3983 | - c = *opc_ptr; | ||
3984 | - if (c == INDEX_op_end) | ||
3985 | - return -1; | ||
3986 | - tc_ptr += opc_copy_size[c]; | ||
3987 | - if (searched_pc < tc_ptr) | ||
3988 | - break; | ||
3989 | - opc_ptr++; | ||
3990 | - } | ||
3991 | - j = opc_ptr - gen_opc_buf; | ||
3992 | - /* now find start of instruction before */ | ||
3993 | - while (gen_opc_instr_start[j] == 0) | ||
3994 | - j--; | ||
3995 | - *found_pc = gen_opc_pc[j]; | ||
3996 | - return 0; | ||
3997 | -} | ||
3998 | - | ||
3999 | - | ||
4000 | CPUX86State *cpu_x86_init(void) | 3777 | CPUX86State *cpu_x86_init(void) |
4001 | { | 3778 | { |
4002 | CPUX86State *env; | 3779 | CPUX86State *env; |
4003 | int i; | 3780 | int i; |
4004 | static int inited; | 3781 | static int inited; |
4005 | 3782 | ||
4006 | - cpu_x86_tblocks_init(); | 3783 | + cpu_exec_init(); |
4007 | 3784 | ||
4008 | env = malloc(sizeof(CPUX86State)); | 3785 | env = malloc(sizeof(CPUX86State)); |
4009 | if (!env) | 3786 | if (!env) |
@@ -4020,7 +3797,6 @@ CPUX86State *cpu_x86_init(void) | @@ -4020,7 +3797,6 @@ CPUX86State *cpu_x86_init(void) | ||
4020 | if (!inited) { | 3797 | if (!inited) { |
4021 | inited = 1; | 3798 | inited = 1; |
4022 | optimize_flags_init(); | 3799 | optimize_flags_init(); |
4023 | - page_init(); | ||
4024 | } | 3800 | } |
4025 | return env; | 3801 | return env; |
4026 | } | 3802 | } |
translate.c
0 โ 100644
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 | +#define IN_OP_I386 | ||
28 | +#include "cpu-" TARGET_ARCH ".h" | ||
29 | +#include "exec.h" | ||
30 | +#include "disas.h" | ||
31 | + | ||
32 | +enum { | ||
33 | +#define DEF(s, n, copy_size) INDEX_op_ ## s, | ||
34 | +#include "opc-" TARGET_ARCH ".h" | ||
35 | +#undef DEF | ||
36 | + NB_OPS, | ||
37 | +}; | ||
38 | + | ||
39 | +#include "dyngen.h" | ||
40 | +#include "op-" TARGET_ARCH ".h" | ||
41 | + | ||
42 | +uint16_t gen_opc_buf[OPC_BUF_SIZE]; | ||
43 | +uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | ||
44 | +uint32_t gen_opc_pc[OPC_BUF_SIZE]; | ||
45 | +uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | ||
46 | + | ||
47 | + | ||
48 | +#ifdef DEBUG_DISAS | ||
49 | +static const char *op_str[] = { | ||
50 | +#define DEF(s, n, copy_size) #s, | ||
51 | +#include "opc-" TARGET_ARCH ".h" | ||
52 | +#undef DEF | ||
53 | +}; | ||
54 | + | ||
55 | +static uint8_t op_nb_args[] = { | ||
56 | +#define DEF(s, n, copy_size) n, | ||
57 | +#include "opc-" TARGET_ARCH ".h" | ||
58 | +#undef DEF | ||
59 | +}; | ||
60 | + | ||
61 | +void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | ||
62 | +{ | ||
63 | + const uint16_t *opc_ptr; | ||
64 | + const uint32_t *opparam_ptr; | ||
65 | + int c, n, i; | ||
66 | + | ||
67 | + opc_ptr = opc_buf; | ||
68 | + opparam_ptr = opparam_buf; | ||
69 | + for(;;) { | ||
70 | + c = *opc_ptr++; | ||
71 | + n = op_nb_args[c]; | ||
72 | + fprintf(logfile, "0x%04x: %s", | ||
73 | + (int)(opc_ptr - opc_buf - 1), op_str[c]); | ||
74 | + for(i = 0; i < n; i++) { | ||
75 | + fprintf(logfile, " 0x%x", opparam_ptr[i]); | ||
76 | + } | ||
77 | + fprintf(logfile, "\n"); | ||
78 | + if (c == INDEX_op_end) | ||
79 | + break; | ||
80 | + opparam_ptr += n; | ||
81 | + } | ||
82 | +} | ||
83 | + | ||
84 | +#endif | ||
85 | + | ||
86 | +/* return non zero if the very first instruction is invalid so that | ||
87 | + the virtual CPU can trigger an exception. | ||
88 | + | ||
89 | + '*gen_code_size_ptr' contains the size of the generated code (host | ||
90 | + code). | ||
91 | +*/ | ||
92 | +int cpu_gen_code(TranslationBlock *tb, | ||
93 | + int max_code_size, int *gen_code_size_ptr) | ||
94 | +{ | ||
95 | + uint8_t *gen_code_buf; | ||
96 | + int gen_code_size; | ||
97 | + | ||
98 | + if (gen_intermediate_code(tb, 0) < 0) | ||
99 | + return -1; | ||
100 | + | ||
101 | + /* generate machine code */ | ||
102 | + tb->tb_next_offset[0] = 0xffff; | ||
103 | + tb->tb_next_offset[1] = 0xffff; | ||
104 | + gen_code_buf = tb->tc_ptr; | ||
105 | + gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, | ||
106 | +#ifdef USE_DIRECT_JUMP | ||
107 | + tb->tb_jmp_offset, | ||
108 | +#else | ||
109 | + NULL, | ||
110 | +#endif | ||
111 | + gen_opc_buf, gen_opparam_buf); | ||
112 | + *gen_code_size_ptr = gen_code_size; | ||
113 | +#ifdef DEBUG_DISAS | ||
114 | + if (loglevel) { | ||
115 | + fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | ||
116 | + disas(logfile, gen_code_buf, *gen_code_size_ptr, 1, 0); | ||
117 | + fprintf(logfile, "\n"); | ||
118 | + fflush(logfile); | ||
119 | + } | ||
120 | +#endif | ||
121 | + return 0; | ||
122 | +} | ||
123 | + | ||
124 | +static const unsigned short opc_copy_size[] = { | ||
125 | +#define DEF(s, n, copy_size) copy_size, | ||
126 | +#include "opc-i386.h" | ||
127 | +#undef DEF | ||
128 | +}; | ||
129 | + | ||
130 | +/* The simulated PC corresponding to | ||
131 | + 'searched_pc' in the generated code is searched. 0 is returned if | ||
132 | + found. *found_pc contains the found PC. | ||
133 | + */ | ||
134 | +int cpu_search_pc(TranslationBlock *tb, | ||
135 | + uint32_t *found_pc, unsigned long searched_pc) | ||
136 | +{ | ||
137 | + int j, c; | ||
138 | + unsigned long tc_ptr; | ||
139 | + uint16_t *opc_ptr; | ||
140 | + | ||
141 | + if (gen_intermediate_code(tb, 1) < 0) | ||
142 | + return -1; | ||
143 | + | ||
144 | + /* find opc index corresponding to search_pc */ | ||
145 | + tc_ptr = (unsigned long)tb->tc_ptr; | ||
146 | + if (searched_pc < tc_ptr) | ||
147 | + return -1; | ||
148 | + j = 0; | ||
149 | + opc_ptr = gen_opc_buf; | ||
150 | + for(;;) { | ||
151 | + c = *opc_ptr; | ||
152 | + if (c == INDEX_op_end) | ||
153 | + return -1; | ||
154 | + tc_ptr += opc_copy_size[c]; | ||
155 | + if (searched_pc < tc_ptr) | ||
156 | + break; | ||
157 | + opc_ptr++; | ||
158 | + } | ||
159 | + j = opc_ptr - gen_opc_buf; | ||
160 | + /* now find start of instruction before */ | ||
161 | + while (gen_opc_instr_start[j] == 0) | ||
162 | + j--; | ||
163 | + *found_pc = gen_opc_pc[j]; | ||
164 | + return 0; | ||
165 | +} | ||
166 | + | ||
167 | + |