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 | 25 | #include <signal.h> |
26 | 26 | #include <assert.h> |
27 | 27 | |
28 | -#include "disas.h" | |
29 | - | |
30 | -#define DEBUG_DISAS | |
31 | - | |
32 | -#define IN_OP_I386 | |
33 | 28 | #include "cpu-i386.h" |
34 | 29 | #include "exec.h" |
30 | +#include "disas.h" | |
35 | 31 | |
36 | 32 | /* XXX: move that elsewhere */ |
37 | 33 | static uint16_t *gen_opc_ptr; |
38 | 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 | 36 | #define PREFIX_REPZ 0x01 |
121 | 37 | #define PREFIX_REPNZ 0x02 |
... | ... | @@ -142,7 +58,7 @@ typedef struct DisasContext { |
142 | 58 | int cpl; |
143 | 59 | int iopl; |
144 | 60 | int tf; /* TF cpu flag */ |
145 | - TranslationBlock *tb; | |
61 | + struct TranslationBlock *tb; | |
146 | 62 | } DisasContext; |
147 | 63 | |
148 | 64 | /* i386 arith/logic operations */ |
... | ... | @@ -176,8 +92,7 @@ enum { |
176 | 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 | 97 | /* operand size */ |
183 | 98 | enum { |
... | ... | @@ -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 | 3666 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
3803 | 3667 | basic block 'tb'. If search_pc is TRUE, also generate PC |
3804 | 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 | 3671 | DisasContext dc1, *dc = &dc1; |
3808 | 3672 | uint8_t *pc_ptr; |
... | ... | @@ -3833,7 +3697,7 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
3833 | 3697 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
3834 | 3698 | gen_opparam_ptr = gen_opparam_buf; |
3835 | 3699 | |
3836 | - dc->is_jmp = 0; | |
3700 | + dc->is_jmp = DISAS_NEXT; | |
3837 | 3701 | pc_ptr = pc_start; |
3838 | 3702 | lj = -1; |
3839 | 3703 | do { |
... | ... | @@ -3865,10 +3729,10 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
3865 | 3729 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
3866 | 3730 | (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32)); |
3867 | 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 | 3733 | if (dc->cc_op != CC_OP_DYNAMIC) |
3870 | 3734 | gen_op_set_cc_op(dc->cc_op); |
3871 | - if (dc->is_jmp != 1) { | |
3735 | + if (dc->is_jmp != DISAS_JUMP) { | |
3872 | 3736 | /* we add an additionnal jmp to update the simulated PC */ |
3873 | 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 | 3744 | /* indicate that the hash table must be used to find the next TB */ |
3881 | 3745 | gen_op_movl_T0_0(); |
3882 | 3746 | } |
3883 | - | |
3884 | 3747 | *gen_opc_ptr = INDEX_op_end; |
3885 | 3748 | |
3886 | 3749 | #ifdef DEBUG_DISAS |
3887 | 3750 | if (loglevel) { |
3888 | 3751 | fprintf(logfile, "----------------\n"); |
3889 | 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 | 3754 | fprintf(logfile, "\n"); |
3893 | 3755 | |
3894 | 3756 | fprintf(logfile, "OP:\n"); |
... | ... | @@ -3912,98 +3774,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
3912 | 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 | 3777 | CPUX86State *cpu_x86_init(void) |
4001 | 3778 | { |
4002 | 3779 | CPUX86State *env; |
4003 | 3780 | int i; |
4004 | 3781 | static int inited; |
4005 | 3782 | |
4006 | - cpu_x86_tblocks_init(); | |
3783 | + cpu_exec_init(); | |
4007 | 3784 | |
4008 | 3785 | env = malloc(sizeof(CPUX86State)); |
4009 | 3786 | if (!env) |
... | ... | @@ -4020,7 +3797,6 @@ CPUX86State *cpu_x86_init(void) |
4020 | 3797 | if (!inited) { |
4021 | 3798 | inited = 1; |
4022 | 3799 | optimize_flags_init(); |
4023 | - page_init(); | |
4024 | 3800 | } |
4025 | 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 | + | ... | ... |