use the TCG code generator
[qemu] / exec-all.h
1 /*
2  * internal execution defines for qemu
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
21 /* allow to see translation results - the slowdown should be negligible, so we leave it */
22 #define DEBUG_DISAS
23
24 /* is_jmp field values */
25 #define DISAS_NEXT    0 /* next instruction can be analyzed */
26 #define DISAS_JUMP    1 /* only pc was modified dynamically */
27 #define DISAS_UPDATE  2 /* cpu state was modified dynamically */
28 #define DISAS_TB_JUMP 3 /* only pc was modified statically */
29
30 struct TranslationBlock;
31
32 /* XXX: make safe guess about sizes */
33 #define MAX_OP_PER_INSTR 32
34 #define OPC_BUF_SIZE 512
35 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
36
37 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
38
39 extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
40 extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
41 extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
42 extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
43 extern target_ulong gen_opc_jump_pc[2];
44 extern uint32_t gen_opc_hflags[OPC_BUF_SIZE];
45
46 typedef void (GenOpFunc)(void);
47 typedef void (GenOpFunc1)(long);
48 typedef void (GenOpFunc2)(long, long);
49 typedef void (GenOpFunc3)(long, long, long);
50
51 #if defined(TARGET_I386)
52
53 void optimize_flags_init(void);
54
55 #endif
56
57 extern FILE *logfile;
58 extern int loglevel;
59
60 int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
61 int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
62 unsigned long code_gen_max_block_size(void);
63 void cpu_gen_init(void);
64 int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
65                  int *gen_code_size_ptr);
66 int cpu_restore_state(struct TranslationBlock *tb,
67                       CPUState *env, unsigned long searched_pc,
68                       void *puc);
69 int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
70                       int max_code_size, int *gen_code_size_ptr);
71 int cpu_restore_state_copy(struct TranslationBlock *tb,
72                            CPUState *env, unsigned long searched_pc,
73                            void *puc);
74 void cpu_resume_from_signal(CPUState *env1, void *puc);
75 void cpu_exec_init(CPUState *env);
76 int page_unprotect(target_ulong address, unsigned long pc, void *puc);
77 void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
78                                    int is_cpu_write_access);
79 void tb_invalidate_page_range(target_ulong start, target_ulong end);
80 void tlb_flush_page(CPUState *env, target_ulong addr);
81 void tlb_flush(CPUState *env, int flush_global);
82 int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
83                       target_phys_addr_t paddr, int prot,
84                       int mmu_idx, int is_softmmu);
85 static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
86                                target_phys_addr_t paddr, int prot,
87                                int mmu_idx, int is_softmmu)
88 {
89     if (prot & PAGE_READ)
90         prot |= PAGE_EXEC;
91     return tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
92 }
93
94 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
95
96 #define CODE_GEN_PHYS_HASH_BITS     15
97 #define CODE_GEN_PHYS_HASH_SIZE     (1 << CODE_GEN_PHYS_HASH_BITS)
98
99 /* maximum total translate dcode allocated */
100
101 /* NOTE: the translated code area cannot be too big because on some
102    archs the range of "fast" function calls is limited. Here is a
103    summary of the ranges:
104
105    i386  : signed 32 bits
106    arm   : signed 26 bits
107    ppc   : signed 24 bits
108    sparc : signed 32 bits
109    alpha : signed 23 bits
110 */
111
112 #if defined(__alpha__)
113 #define CODE_GEN_BUFFER_SIZE     (2 * 1024 * 1024)
114 #elif defined(__ia64)
115 #define CODE_GEN_BUFFER_SIZE     (4 * 1024 * 1024)      /* range of addl */
116 #elif defined(__powerpc__)
117 #define CODE_GEN_BUFFER_SIZE     (6 * 1024 * 1024)
118 #else
119 /* XXX: make it dynamic on x86 */
120 #define CODE_GEN_BUFFER_SIZE     (16 * 1024 * 1024)
121 #endif
122
123 //#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
124
125 /* estimated block size for TB allocation */
126 /* XXX: use a per code average code fragment size and modulate it
127    according to the host CPU */
128 #if defined(CONFIG_SOFTMMU)
129 #define CODE_GEN_AVG_BLOCK_SIZE 128
130 #else
131 #define CODE_GEN_AVG_BLOCK_SIZE 64
132 #endif
133
134 #define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
135
136 #if defined(__powerpc__) || defined(__x86_64__)
137 #define USE_DIRECT_JUMP
138 #endif
139 #if defined(__i386__) && !defined(_WIN32)
140 #define USE_DIRECT_JUMP
141 #endif
142
143 typedef struct TranslationBlock {
144     target_ulong pc;   /* simulated PC corresponding to this block (EIP + CS base) */
145     target_ulong cs_base; /* CS base for this block */
146     uint64_t flags; /* flags defining in which context the code was generated */
147     uint16_t size;      /* size of target code for this block (1 <=
148                            size <= TARGET_PAGE_SIZE) */
149     uint16_t cflags;    /* compile flags */
150 #define CF_CODE_COPY   0x0001 /* block was generated in code copy mode */
151 #define CF_TB_FP_USED  0x0002 /* fp ops are used in the TB */
152 #define CF_FP_USED     0x0004 /* fp ops are used in the TB or in a chained TB */
153 #define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
154
155     uint8_t *tc_ptr;    /* pointer to the translated code */
156     /* next matching tb for physical address. */
157     struct TranslationBlock *phys_hash_next;
158     /* first and second physical page containing code. The lower bit
159        of the pointer tells the index in page_next[] */
160     struct TranslationBlock *page_next[2];
161     target_ulong page_addr[2];
162
163     /* the following data are used to directly call another TB from
164        the code of this one. */
165     uint16_t tb_next_offset[2]; /* offset of original jump target */
166 #ifdef USE_DIRECT_JUMP
167     uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
168 #else
169     unsigned long tb_next[2]; /* address of jump generated code */
170 #endif
171     /* list of TBs jumping to this one. This is a circular list using
172        the two least significant bits of the pointers to tell what is
173        the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
174        jmp_first */
175     struct TranslationBlock *jmp_next[2];
176     struct TranslationBlock *jmp_first;
177 } TranslationBlock;
178
179 static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
180 {
181     target_ulong tmp;
182     tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
183     return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
184 }
185
186 static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
187 {
188     target_ulong tmp;
189     tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
190     return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
191             (tmp & TB_JMP_ADDR_MASK));
192 }
193
194 static inline unsigned int tb_phys_hash_func(unsigned long pc)
195 {
196     return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
197 }
198
199 TranslationBlock *tb_alloc(target_ulong pc);
200 void tb_flush(CPUState *env);
201 void tb_link_phys(TranslationBlock *tb,
202                   target_ulong phys_pc, target_ulong phys_page2);
203
204 extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
205
206 extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
207 extern uint8_t *code_gen_ptr;
208
209 #if defined(USE_DIRECT_JUMP)
210
211 #if defined(__powerpc__)
212 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
213 {
214     uint32_t val, *ptr;
215
216     /* patch the branch destination */
217     ptr = (uint32_t *)jmp_addr;
218     val = *ptr;
219     val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
220     *ptr = val;
221     /* flush icache */
222     asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
223     asm volatile ("sync" : : : "memory");
224     asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
225     asm volatile ("sync" : : : "memory");
226     asm volatile ("isync" : : : "memory");
227 }
228 #elif defined(__i386__) || defined(__x86_64__)
229 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
230 {
231     /* patch the branch destination */
232     *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
233     /* no need to flush icache explicitely */
234 }
235 #endif
236
237 static inline void tb_set_jmp_target(TranslationBlock *tb,
238                                      int n, unsigned long addr)
239 {
240     unsigned long offset;
241
242     offset = tb->tb_jmp_offset[n];
243     tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
244     offset = tb->tb_jmp_offset[n + 2];
245     if (offset != 0xffff)
246         tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
247 }
248
249 #else
250
251 /* set the jump target */
252 static inline void tb_set_jmp_target(TranslationBlock *tb,
253                                      int n, unsigned long addr)
254 {
255     tb->tb_next[n] = addr;
256 }
257
258 #endif
259
260 static inline void tb_add_jump(TranslationBlock *tb, int n,
261                                TranslationBlock *tb_next)
262 {
263     /* NOTE: this test is only needed for thread safety */
264     if (!tb->jmp_next[n]) {
265         /* patch the native jump address */
266         tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
267
268         /* add in TB jmp circular list */
269         tb->jmp_next[n] = tb_next->jmp_first;
270         tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
271     }
272 }
273
274 TranslationBlock *tb_find_pc(unsigned long pc_ptr);
275
276 #ifndef offsetof
277 #define offsetof(type, field) ((size_t) &((type *)0)->field)
278 #endif
279
280 #if defined(_WIN32)
281 #define ASM_DATA_SECTION ".section \".data\"\n"
282 #define ASM_PREVIOUS_SECTION ".section .text\n"
283 #elif defined(__APPLE__)
284 #define ASM_DATA_SECTION ".data\n"
285 #define ASM_PREVIOUS_SECTION ".text\n"
286 #else
287 #define ASM_DATA_SECTION ".section \".data\"\n"
288 #define ASM_PREVIOUS_SECTION ".previous\n"
289 #endif
290
291 #define ASM_OP_LABEL_NAME(n, opname) \
292     ASM_NAME(__op_label) #n "." ASM_NAME(opname)
293
294 extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
295 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
296 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
297
298 #if defined(__powerpc__)
299 static inline int testandset (int *p)
300 {
301     int ret;
302     __asm__ __volatile__ (
303                           "0:    lwarx %0,0,%1\n"
304                           "      xor. %0,%3,%0\n"
305                           "      bne 1f\n"
306                           "      stwcx. %2,0,%1\n"
307                           "      bne- 0b\n"
308                           "1:    "
309                           : "=&r" (ret)
310                           : "r" (p), "r" (1), "r" (0)
311                           : "cr0", "memory");
312     return ret;
313 }
314 #elif defined(__i386__)
315 static inline int testandset (int *p)
316 {
317     long int readval = 0;
318
319     __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
320                           : "+m" (*p), "+a" (readval)
321                           : "r" (1)
322                           : "cc");
323     return readval;
324 }
325 #elif defined(__x86_64__)
326 static inline int testandset (int *p)
327 {
328     long int readval = 0;
329
330     __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
331                           : "+m" (*p), "+a" (readval)
332                           : "r" (1)
333                           : "cc");
334     return readval;
335 }
336 #elif defined(__s390__)
337 static inline int testandset (int *p)
338 {
339     int ret;
340
341     __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
342                           "   jl    0b"
343                           : "=&d" (ret)
344                           : "r" (1), "a" (p), "0" (*p)
345                           : "cc", "memory" );
346     return ret;
347 }
348 #elif defined(__alpha__)
349 static inline int testandset (int *p)
350 {
351     int ret;
352     unsigned long one;
353
354     __asm__ __volatile__ ("0:   mov 1,%2\n"
355                           "     ldl_l %0,%1\n"
356                           "     stl_c %2,%1\n"
357                           "     beq %2,1f\n"
358                           ".subsection 2\n"
359                           "1:   br 0b\n"
360                           ".previous"
361                           : "=r" (ret), "=m" (*p), "=r" (one)
362                           : "m" (*p));
363     return ret;
364 }
365 #elif defined(__sparc__)
366 static inline int testandset (int *p)
367 {
368         int ret;
369
370         __asm__ __volatile__("ldstub    [%1], %0"
371                              : "=r" (ret)
372                              : "r" (p)
373                              : "memory");
374
375         return (ret ? 1 : 0);
376 }
377 #elif defined(__arm__)
378 static inline int testandset (int *spinlock)
379 {
380     register unsigned int ret;
381     __asm__ __volatile__("swp %0, %1, [%2]"
382                          : "=r"(ret)
383                          : "0"(1), "r"(spinlock));
384
385     return ret;
386 }
387 #elif defined(__mc68000)
388 static inline int testandset (int *p)
389 {
390     char ret;
391     __asm__ __volatile__("tas %1; sne %0"
392                          : "=r" (ret)
393                          : "m" (p)
394                          : "cc","memory");
395     return ret;
396 }
397 #elif defined(__ia64)
398
399 #include <ia64intrin.h>
400
401 static inline int testandset (int *p)
402 {
403     return __sync_lock_test_and_set (p, 1);
404 }
405 #elif defined(__mips__)
406 static inline int testandset (int *p)
407 {
408     int ret;
409
410     __asm__ __volatile__ (
411         "       .set push               \n"
412         "       .set noat               \n"
413         "       .set mips2              \n"
414         "1:     li      $1, 1           \n"
415         "       ll      %0, %1          \n"
416         "       sc      $1, %1          \n"
417         "       beqz    $1, 1b          \n"
418         "       .set pop                "
419         : "=r" (ret), "+R" (*p)
420         :
421         : "memory");
422
423     return ret;
424 }
425 #else
426 #error unimplemented CPU support
427 #endif
428
429 typedef int spinlock_t;
430
431 #define SPIN_LOCK_UNLOCKED 0
432
433 #if defined(CONFIG_USER_ONLY)
434 static inline void spin_lock(spinlock_t *lock)
435 {
436     while (testandset(lock));
437 }
438
439 static inline void spin_unlock(spinlock_t *lock)
440 {
441     *lock = 0;
442 }
443
444 static inline int spin_trylock(spinlock_t *lock)
445 {
446     return !testandset(lock);
447 }
448 #else
449 static inline void spin_lock(spinlock_t *lock)
450 {
451 }
452
453 static inline void spin_unlock(spinlock_t *lock)
454 {
455 }
456
457 static inline int spin_trylock(spinlock_t *lock)
458 {
459     return 1;
460 }
461 #endif
462
463 extern spinlock_t tb_lock;
464
465 extern int tb_invalidated_flag;
466
467 #if !defined(CONFIG_USER_ONLY)
468
469 void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
470               void *retaddr);
471
472 #define ACCESS_TYPE (NB_MMU_MODES + 1)
473 #define MEMSUFFIX _code
474 #define env cpu_single_env
475
476 #define DATA_SIZE 1
477 #include "softmmu_header.h"
478
479 #define DATA_SIZE 2
480 #include "softmmu_header.h"
481
482 #define DATA_SIZE 4
483 #include "softmmu_header.h"
484
485 #define DATA_SIZE 8
486 #include "softmmu_header.h"
487
488 #undef ACCESS_TYPE
489 #undef MEMSUFFIX
490 #undef env
491
492 #endif
493
494 #if defined(CONFIG_USER_ONLY)
495 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
496 {
497     return addr;
498 }
499 #else
500 /* NOTE: this function can trigger an exception */
501 /* NOTE2: the returned address is not exactly the physical address: it
502    is the offset relative to phys_ram_base */
503 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
504 {
505     int mmu_idx, index, pd;
506
507     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
508     mmu_idx = cpu_mmu_index(env);
509     if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_code !=
510                          (addr & TARGET_PAGE_MASK), 0)) {
511         ldub_code(addr);
512     }
513     pd = env->tlb_table[mmu_idx][index].addr_code & ~TARGET_PAGE_MASK;
514     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
515 #if defined(TARGET_SPARC) || defined(TARGET_MIPS)
516         do_unassigned_access(addr, 0, 1, 0);
517 #else
518         cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
519 #endif
520     }
521     return addr + env->tlb_table[mmu_idx][index].addend - (unsigned long)phys_ram_base;
522 }
523 #endif
524
525 #ifdef USE_KQEMU
526 #define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
527
528 int kqemu_init(CPUState *env);
529 int kqemu_cpu_exec(CPUState *env);
530 void kqemu_flush_page(CPUState *env, target_ulong addr);
531 void kqemu_flush(CPUState *env, int global);
532 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
533 void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
534 void kqemu_cpu_interrupt(CPUState *env);
535 void kqemu_record_dump(void);
536
537 static inline int kqemu_is_ok(CPUState *env)
538 {
539     return(env->kqemu_enabled &&
540            (env->cr[0] & CR0_PE_MASK) &&
541            !(env->hflags & HF_INHIBIT_IRQ_MASK) &&
542            (env->eflags & IF_MASK) &&
543            !(env->eflags & VM_MASK) &&
544            (env->kqemu_enabled == 2 ||
545             ((env->hflags & HF_CPL_MASK) == 3 &&
546              (env->eflags & IOPL_MASK) != IOPL_MASK)));
547 }
548
549 #endif