]> git.proxmox.com Git - mirror_qemu.git/blame - translate-all.c
same PCI parameters as PIIX3
[mirror_qemu.git] / translate-all.c
CommitLineData
d19893da
FB
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"
2054396a 27
af5ad107 28#define NO_CPU_IO_DEFS
d3eead2e
FB
29#include "cpu.h"
30#include "exec-all.h"
d19893da
FB
31#include "disas.h"
32
4f716dc6
FB
33extern int dyngen_code(uint8_t *gen_code_buf,
34 uint16_t *label_offsets, uint16_t *jmp_offsets,
35 const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
36
d19893da
FB
37enum {
38#define DEF(s, n, copy_size) INDEX_op_ ## s,
d3eead2e 39#include "opc.h"
d19893da
FB
40#undef DEF
41 NB_OPS,
42};
43
d19893da
FB
44uint16_t gen_opc_buf[OPC_BUF_SIZE];
45uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
c4687878
FB
46long gen_labels[OPC_BUF_SIZE];
47int nb_gen_labels;
48
49target_ulong gen_opc_pc[OPC_BUF_SIZE];
d19893da 50uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
f76af4b3
FB
51#if defined(TARGET_I386)
52uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
e95c8d51 53#elif defined(TARGET_SPARC)
c4687878 54target_ulong gen_opc_npc[OPC_BUF_SIZE];
c3278b7b 55target_ulong gen_opc_jump_pc[2];
f76af4b3 56#endif
d19893da 57
58fe2f10
FB
58int code_copy_enabled = 1;
59
d19893da
FB
60#ifdef DEBUG_DISAS
61static const char *op_str[] = {
62#define DEF(s, n, copy_size) #s,
d3eead2e 63#include "opc.h"
d19893da
FB
64#undef DEF
65};
66
67static uint8_t op_nb_args[] = {
68#define DEF(s, n, copy_size) n,
d3eead2e 69#include "opc.h"
d19893da
FB
70#undef DEF
71};
72
c4687878
FB
73static const unsigned short opc_copy_size[] = {
74#define DEF(s, n, copy_size) copy_size,
75#include "opc.h"
76#undef DEF
77};
78
d19893da
FB
79void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
80{
81 const uint16_t *opc_ptr;
82 const uint32_t *opparam_ptr;
83 int c, n, i;
84
85 opc_ptr = opc_buf;
86 opparam_ptr = opparam_buf;
87 for(;;) {
88 c = *opc_ptr++;
89 n = op_nb_args[c];
90 fprintf(logfile, "0x%04x: %s",
91 (int)(opc_ptr - opc_buf - 1), op_str[c]);
92 for(i = 0; i < n; i++) {
93 fprintf(logfile, " 0x%x", opparam_ptr[i]);
94 }
95 fprintf(logfile, "\n");
96 if (c == INDEX_op_end)
97 break;
98 opparam_ptr += n;
99 }
100}
101
102#endif
103
c4687878
FB
104/* compute label info */
105static void dyngen_labels(long *gen_labels, int nb_gen_labels,
106 uint8_t *gen_code_buf, const uint16_t *opc_buf)
107{
108 uint8_t *gen_code_ptr;
109 int c, i;
110 unsigned long gen_code_addr[OPC_BUF_SIZE];
111
112 if (nb_gen_labels == 0)
113 return;
114 /* compute the address of each op code */
115
116 gen_code_ptr = gen_code_buf;
117 i = 0;
118 for(;;) {
119 c = opc_buf[i];
120 gen_code_addr[i] =(unsigned long)gen_code_ptr;
121 if (c == INDEX_op_end)
122 break;
123 gen_code_ptr += opc_copy_size[c];
124 i++;
125 }
126
127 /* compute the address of each label */
128 for(i = 0; i < nb_gen_labels; i++) {
129 gen_labels[i] = gen_code_addr[gen_labels[i]];
130 }
131}
132
d19893da
FB
133/* return non zero if the very first instruction is invalid so that
134 the virtual CPU can trigger an exception.
135
136 '*gen_code_size_ptr' contains the size of the generated code (host
137 code).
138*/
4c3a88a2 139int cpu_gen_code(CPUState *env, TranslationBlock *tb,
d19893da
FB
140 int max_code_size, int *gen_code_size_ptr)
141{
142 uint8_t *gen_code_buf;
143 int gen_code_size;
144
58fe2f10
FB
145#ifdef USE_CODE_COPY
146 if (code_copy_enabled &&
147 cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
148 /* nothing more to do */
149 } else
150#endif
151 {
152 if (gen_intermediate_code(env, tb) < 0)
153 return -1;
d19893da 154
58fe2f10
FB
155 /* generate machine code */
156 tb->tb_next_offset[0] = 0xffff;
157 tb->tb_next_offset[1] = 0xffff;
158 gen_code_buf = tb->tc_ptr;
4cbb86e1 159#ifdef USE_DIRECT_JUMP
58fe2f10
FB
160 /* the following two entries are optional (only used for string ops) */
161 tb->tb_jmp_offset[2] = 0xffff;
162 tb->tb_jmp_offset[3] = 0xffff;
4cbb86e1 163#endif
c4687878
FB
164 dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
165
58fe2f10 166 gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
d19893da 167#ifdef USE_DIRECT_JUMP
58fe2f10 168 tb->tb_jmp_offset,
d19893da 169#else
58fe2f10 170 NULL,
d19893da 171#endif
c4687878 172 gen_opc_buf, gen_opparam_buf, gen_labels);
58fe2f10 173 }
d19893da
FB
174 *gen_code_size_ptr = gen_code_size;
175#ifdef DEBUG_DISAS
f193c797 176 if (loglevel & CPU_LOG_TB_OUT_ASM) {
d19893da 177 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
c4687878 178 disas(logfile, tb->tc_ptr, *gen_code_size_ptr);
d19893da
FB
179 fprintf(logfile, "\n");
180 fflush(logfile);
181 }
182#endif
183 return 0;
184}
185
f76af4b3 186/* The cpu state corresponding to 'searched_pc' is restored.
d19893da 187 */
f76af4b3 188int cpu_restore_state(TranslationBlock *tb,
58fe2f10
FB
189 CPUState *env, unsigned long searched_pc,
190 void *puc)
d19893da
FB
191{
192 int j, c;
193 unsigned long tc_ptr;
194 uint16_t *opc_ptr;
195
58fe2f10
FB
196#ifdef USE_CODE_COPY
197 if (tb->cflags & CF_CODE_COPY) {
198 return cpu_restore_state_copy(tb, env, searched_pc, puc);
199 }
200#endif
4c3a88a2 201 if (gen_intermediate_code_pc(env, tb) < 0)
d19893da
FB
202 return -1;
203
204 /* find opc index corresponding to search_pc */
205 tc_ptr = (unsigned long)tb->tc_ptr;
206 if (searched_pc < tc_ptr)
207 return -1;
208 j = 0;
209 opc_ptr = gen_opc_buf;
210 for(;;) {
211 c = *opc_ptr;
212 if (c == INDEX_op_end)
213 return -1;
214 tc_ptr += opc_copy_size[c];
215 if (searched_pc < tc_ptr)
216 break;
217 opc_ptr++;
218 }
219 j = opc_ptr - gen_opc_buf;
220 /* now find start of instruction before */
221 while (gen_opc_instr_start[j] == 0)
222 j--;
f76af4b3
FB
223#if defined(TARGET_I386)
224 {
225 int cc_op;
3c1cf9fa 226#ifdef DEBUG_DISAS
f193c797 227 if (loglevel & CPU_LOG_TB_OP) {
3c1cf9fa 228 int i;
6e0374f6 229 fprintf(logfile, "RESTORE:\n");
3c1cf9fa
FB
230 for(i=0;i<=j; i++) {
231 if (gen_opc_instr_start[i]) {
c4687878 232 fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
3c1cf9fa
FB
233 }
234 }
c4687878
FB
235 fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
236 searched_pc, j, gen_opc_pc[j] - tb->cs_base,
237 (uint32_t)tb->cs_base);
3c1cf9fa
FB
238 }
239#endif
f76af4b3
FB
240 env->eip = gen_opc_pc[j] - tb->cs_base;
241 cc_op = gen_opc_cc_op[j];
242 if (cc_op != CC_OP_DYNAMIC)
243 env->cc_op = cc_op;
244 }
245#elif defined(TARGET_ARM)
246 env->regs[15] = gen_opc_pc[j];
d3eead2e 247#elif defined(TARGET_SPARC)
c3278b7b
FB
248 {
249 target_ulong npc;
250 env->pc = gen_opc_pc[j];
251 npc = gen_opc_npc[j];
252 if (npc == 1) {
253 /* dynamic NPC: already stored */
254 } else if (npc == 2) {
255 target_ulong t2 = (target_ulong)puc;
256 /* jump PC: use T2 and the jump targets of the translation */
257 if (t2)
258 env->npc = gen_opc_jump_pc[0];
259 else
260 env->npc = gen_opc_jump_pc[1];
261 } else {
262 env->npc = npc;
263 }
264 }
6dca2016 265#elif defined(TARGET_PPC)
af5ad107
FB
266 {
267 int type;
268 /* for PPC, we need to look at the micro operation to get the
269 access type */
270 env->nip = gen_opc_pc[j];
271 switch(c) {
272#if defined(CONFIG_USER_ONLY)
273#define CASE3(op)\
274 case INDEX_op_ ## op ## _raw
275#else
276#define CASE3(op)\
af5ad107
FB
277 case INDEX_op_ ## op ## _user:\
278 case INDEX_op_ ## op ## _kernel
279#endif
280
281 CASE3(stfd):
282 CASE3(stfs):
283 CASE3(lfd):
284 CASE3(lfs):
285 type = ACCESS_FLOAT;
286 break;
a541f297
FB
287 CASE3(lwarx):
288 type = ACCESS_RES;
289 break;
af5ad107
FB
290 CASE3(stwcx):
291 type = ACCESS_RES;
292 break;
293 CASE3(eciwx):
294 CASE3(ecowx):
295 type = ACCESS_EXT;
296 break;
297 default:
298 type = ACCESS_INT;
299 break;
300 }
301 env->access_type = type;
302 }
6af0bf9c
FB
303#elif defined(TARGET_MIPS)
304 env->PC = gen_opc_pc[j];
f76af4b3 305#endif
d19893da
FB
306 return 0;
307}