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 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 +
... ...