Commit d19893dab57d29507ebec946f822a5894e873863

Authored by bellard
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 +