exec-all.h 17.5 KB
Newer Older
bellard's avatar
bellard committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * internal execution defines for qemu
 * 
 *  Copyright (c) 2003 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

bellard's avatar
bellard committed
21
22
23
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS

24
25
26
27
28
29
30
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s)	tostring(s)
#define tostring(s)	#s
#endif

31
#if __GNUC__ < 3
32
33
34
#define __builtin_expect(x, n) (x)
#endif

bellard's avatar
bellard committed
35
36
37
38
39
40
#ifdef __i386__
#define REGPARM(n) __attribute((regparm(n)))
#else
#define REGPARM(n)
#endif

bellard's avatar
bellard committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* is_jmp field values */
#define DISAS_NEXT    0 /* next instruction can be analyzed */
#define DISAS_JUMP    1 /* only pc was modified dynamically */
#define DISAS_UPDATE  2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */

struct TranslationBlock;

/* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 32
#define OPC_BUF_SIZE 512
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)

#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)

extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
bellard's avatar
bellard committed
58
59
60
61
extern long gen_labels[OPC_BUF_SIZE];
extern int nb_gen_labels;
extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
bellard's avatar
bellard committed
62
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
bellard's avatar
bellard committed
63
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
64
extern target_ulong gen_opc_jump_pc[2];
bellard's avatar
bellard committed
65

bellard's avatar
bellard committed
66
67
68
69
70
typedef void (GenOpFunc)(void);
typedef void (GenOpFunc1)(long);
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
                    
bellard's avatar
bellard committed
71
72
#if defined(TARGET_I386)

73
void optimize_flags_init(void);
bellard's avatar
bellard committed
74

bellard's avatar
bellard committed
75
76
77
78
79
#endif

extern FILE *logfile;
extern int loglevel;

bellard's avatar
bellard committed
80
81
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
bellard's avatar
bellard committed
82
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
bellard's avatar
bellard committed
83
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
bellard's avatar
bellard committed
84
                 int max_code_size, int *gen_code_size_ptr);
bellard's avatar
bellard committed
85
int cpu_restore_state(struct TranslationBlock *tb, 
bellard's avatar
bellard committed
86
87
88
89
90
91
92
                      CPUState *env, unsigned long searched_pc,
                      void *puc);
int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
                      int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state_copy(struct TranslationBlock *tb, 
                           CPUState *env, unsigned long searched_pc,
                           void *puc);
93
void cpu_resume_from_signal(CPUState *env1, void *puc);
bellard's avatar
bellard committed
94
void cpu_exec_init(void);
95
96
97
int page_unprotect(unsigned long address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, 
                                   int is_cpu_write_access);
98
void tb_invalidate_page_range(target_ulong start, target_ulong end);
99
void tlb_flush_page(CPUState *env, target_ulong addr);
100
void tlb_flush(CPUState *env, int flush_global);
101
102
int tlb_set_page(CPUState *env, target_ulong vaddr, 
                 target_phys_addr_t paddr, int prot, 
103
                 int is_user, int is_softmmu);
bellard's avatar
bellard committed
104
105
106
107
108
109
110

#define CODE_GEN_MAX_SIZE        65536
#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */

#define CODE_GEN_HASH_BITS     15
#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)

111
112
113
#define CODE_GEN_PHYS_HASH_BITS     15
#define CODE_GEN_PHYS_HASH_SIZE     (1 << CODE_GEN_PHYS_HASH_BITS)

bellard's avatar
bellard committed
114
/* maximum total translate dcode allocated */
115
116

/* NOTE: the translated code area cannot be too big because on some
bellard's avatar
bellard committed
117
   archs the range of "fast" function calls is limited. Here is a
118
119
120
121
122
123
124
125
126
127
128
   summary of the ranges:

   i386  : signed 32 bits
   arm   : signed 26 bits
   ppc   : signed 24 bits
   sparc : signed 32 bits
   alpha : signed 23 bits
*/

#if defined(__alpha__)
#define CODE_GEN_BUFFER_SIZE     (2 * 1024 * 1024)
bellard's avatar
bellard committed
129
130
#elif defined(__ia64)
#define CODE_GEN_BUFFER_SIZE     (4 * 1024 * 1024)	/* range of addl */
131
#elif defined(__powerpc__)
bellard's avatar
bellard committed
132
#define CODE_GEN_BUFFER_SIZE     (6 * 1024 * 1024)
133
#else
134
#define CODE_GEN_BUFFER_SIZE     (16 * 1024 * 1024)
135
136
#endif

bellard's avatar
bellard committed
137
138
//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)

139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
   according to the host CPU */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 128
#else
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif

#define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)

#if defined(__powerpc__) 
#define USE_DIRECT_JUMP
#endif
bellard's avatar
bellard committed
153
#if defined(__i386__) && !defined(_WIN32)
bellard's avatar
bellard committed
154
155
156
157
#define USE_DIRECT_JUMP
#endif

typedef struct TranslationBlock {
158
159
    target_ulong pc;   /* simulated PC corresponding to this block (EIP + CS base) */
    target_ulong cs_base; /* CS base for this block */
bellard's avatar
bellard committed
160
161
162
    unsigned int flags; /* flags defining in which context the code was generated */
    uint16_t size;      /* size of target code for this block (1 <=
                           size <= TARGET_PAGE_SIZE) */
bellard's avatar
bellard committed
163
    uint16_t cflags;    /* compile flags */
bellard's avatar
bellard committed
164
165
166
#define CF_CODE_COPY   0x0001 /* block was generated in code copy mode */
#define CF_TB_FP_USED  0x0002 /* fp ops are used in the TB */
#define CF_FP_USED     0x0004 /* fp ops are used in the TB or in a chained TB */
167
#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
bellard's avatar
bellard committed
168

bellard's avatar
bellard committed
169
    uint8_t *tc_ptr;    /* pointer to the translated code */
170
171
172
173
174
175
176
177
    struct TranslationBlock *hash_next; /* next matching tb for virtual address */
    /* next matching tb for physical address. */
    struct TranslationBlock *phys_hash_next; 
    /* first and second physical page containing code. The lower bit
       of the pointer tells the index in page_next[] */
    struct TranslationBlock *page_next[2]; 
    target_ulong page_addr[2]; 

bellard's avatar
bellard committed
178
179
180
181
    /* the following data are used to directly call another TB from
       the code of this one. */
    uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
182
    uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
bellard's avatar
bellard committed
183
#else
184
    uint32_t tb_next[2]; /* address of jump generated code */
bellard's avatar
bellard committed
185
186
187
188
189
190
191
192
193
#endif
    /* list of TBs jumping to this one. This is a circular list using
       the two least significant bits of the pointers to tell what is
       the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
       jmp_first */
    struct TranslationBlock *jmp_next[2]; 
    struct TranslationBlock *jmp_first;
} TranslationBlock;

bellard's avatar
bellard committed
194
static inline unsigned int tb_hash_func(target_ulong pc)
bellard's avatar
bellard committed
195
196
197
198
{
    return pc & (CODE_GEN_HASH_SIZE - 1);
}

199
200
201
202
203
static inline unsigned int tb_phys_hash_func(unsigned long pc)
{
    return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
}

bellard's avatar
bellard committed
204
TranslationBlock *tb_alloc(target_ulong pc);
205
void tb_flush(CPUState *env);
bellard's avatar
bellard committed
206
void tb_link(TranslationBlock *tb);
207
208
void tb_link_phys(TranslationBlock *tb, 
                  target_ulong phys_pc, target_ulong phys_page2);
bellard's avatar
bellard committed
209
210

extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
211
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
bellard's avatar
bellard committed
212
213
214
215
216
217
218

extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
extern uint8_t *code_gen_ptr;

/* find a translation block in the translation cache. If not found,
   return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
219
220
                                        target_ulong pc, 
                                        target_ulong cs_base,
bellard's avatar
bellard committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
                                        unsigned int flags)
{
    TranslationBlock **ptb, *tb;
    unsigned int h;
 
    h = tb_hash_func(pc);
    ptb = &tb_hash[h];
    for(;;) {
        tb = *ptb;
        if (!tb)
            break;
        if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
            return tb;
        ptb = &tb->hash_next;
    }
    *pptb = ptb;
    return NULL;
}


241
242
243
#if defined(USE_DIRECT_JUMP)

#if defined(__powerpc__)
244
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
bellard's avatar
bellard committed
245
246
247
248
{
    uint32_t val, *ptr;

    /* patch the branch destination */
249
    ptr = (uint32_t *)jmp_addr;
bellard's avatar
bellard committed
250
    val = *ptr;
251
    val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
bellard's avatar
bellard committed
252
253
254
255
256
257
258
259
    *ptr = val;
    /* flush icache */
    asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
    asm volatile ("sync" : : : "memory");
    asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
    asm volatile ("sync" : : : "memory");
    asm volatile ("isync" : : : "memory");
}
260
261
262
263
264
265
266
267
#elif defined(__i386__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
    /* patch the branch destination */
    *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
    /* no need to flush icache explicitely */
}
#endif
bellard's avatar
bellard committed
268

269
270
271
272
273
274
275
276
277
278
279
280
static inline void tb_set_jmp_target(TranslationBlock *tb, 
                                     int n, unsigned long addr)
{
    unsigned long offset;

    offset = tb->tb_jmp_offset[n];
    tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
    offset = tb->tb_jmp_offset[n + 2];
    if (offset != 0xffff)
        tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
}

bellard's avatar
bellard committed
281
282
283
284
285
286
#else

/* set the jump target */
static inline void tb_set_jmp_target(TranslationBlock *tb, 
                                     int n, unsigned long addr)
{
287
    tb->tb_next[n] = addr;
bellard's avatar
bellard committed
288
289
290
291
292
293
294
}

#endif

static inline void tb_add_jump(TranslationBlock *tb, int n, 
                               TranslationBlock *tb_next)
{
bellard's avatar
bellard committed
295
296
297
298
299
300
301
302
303
    /* NOTE: this test is only needed for thread safety */
    if (!tb->jmp_next[n]) {
        /* patch the native jump address */
        tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
        
        /* add in TB jmp circular list */
        tb->jmp_next[n] = tb_next->jmp_first;
        tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
    }
bellard's avatar
bellard committed
304
305
}

bellard's avatar
bellard committed
306
307
TranslationBlock *tb_find_pc(unsigned long pc_ptr);

bellard's avatar
bellard committed
308
309
310
311
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif

312
313
314
315
316
317
318
319
320
321
322
#if defined(_WIN32)
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".section .text\n"
#elif defined(__APPLE__)
#define ASM_DATA_SECTION ".data\n"
#define ASM_PREVIOUS_SECTION ".text\n"
#else
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".previous\n"
#endif

323
324
325
#define ASM_OP_LABEL_NAME(n, opname) \
    ASM_NAME(__op_label) #n "." ASM_NAME(opname)

bellard's avatar
bellard committed
326
327
#if defined(__powerpc__)

328
/* we patch the jump instruction directly */
bellard's avatar
bellard committed
329
#define GOTO_TB(opname, tbparam, n)\
bellard's avatar
bellard committed
330
do {\
331
    asm volatile (ASM_DATA_SECTION\
332
		  ASM_OP_LABEL_NAME(n, opname) ":\n"\
333
		  ".long 1f\n"\
334
335
		  ASM_PREVIOUS_SECTION \
                  "b " ASM_NAME(__op_jmp) #n "\n"\
336
		  "1:\n");\
337
338
339
340
341
} while (0)

#elif defined(__i386__) && defined(USE_DIRECT_JUMP)

/* we patch the jump instruction directly */
bellard's avatar
bellard committed
342
#define GOTO_TB(opname, tbparam, n)\
bellard's avatar
bellard committed
343
344
do {\
    asm volatile (".section .data\n"\
345
		  ASM_OP_LABEL_NAME(n, opname) ":\n"\
bellard's avatar
bellard committed
346
347
348
349
350
351
		  ".long 1f\n"\
		  ASM_PREVIOUS_SECTION \
                  "jmp " ASM_NAME(__op_jmp) #n "\n"\
		  "1:\n");\
} while (0)

bellard's avatar
bellard committed
352
353
354
355
#else

/* jump to next block operations (more portable code, does not need
   cache flushing, but slower because of indirect jump) */
bellard's avatar
bellard committed
356
#define GOTO_TB(opname, tbparam, n)\
bellard's avatar
bellard committed
357
do {\
358
    static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
359
360
    static void __attribute__((unused)) *__op_label ## n \
        __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
bellard's avatar
bellard committed
361
    goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
bellard's avatar
bellard committed
362
363
label ## n: ;\
dummy_label ## n: ;\
bellard's avatar
bellard committed
364
365
} while (0)

bellard's avatar
bellard committed
366
367
368
369
#endif

/* XXX: will be suppressed */
#define JUMP_TB(opname, tbparam, n, eip)\
370
do {\
bellard's avatar
bellard committed
371
372
373
374
    GOTO_TB(opname, tbparam, n);\
    T0 = (long)(tbparam) + (n);\
    EIP = (int32_t)eip;\
    EXIT_TB();\
375
376
} while (0)

377
378
extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
379
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
380

bellard's avatar
bellard committed
381
382
383
384
385
#ifdef __powerpc__
static inline int testandset (int *p)
{
    int ret;
    __asm__ __volatile__ (
bellard's avatar
bellard committed
386
387
388
389
390
                          "0:    lwarx %0,0,%1\n"
                          "      xor. %0,%3,%0\n"
                          "      bne 1f\n"
                          "      stwcx. %2,0,%1\n"
                          "      bne- 0b\n"
bellard's avatar
bellard committed
391
392
393
394
395
396
397
398
399
400
401
                          "1:    "
                          : "=&r" (ret)
                          : "r" (p), "r" (1), "r" (0)
                          : "cr0", "memory");
    return ret;
}
#endif

#ifdef __i386__
static inline int testandset (int *p)
{
bellard's avatar
bellard committed
402
    long int readval = 0;
bellard's avatar
bellard committed
403
    
bellard's avatar
bellard committed
404
405
406
407
408
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
                          : "+m" (*p), "+a" (readval)
                          : "r" (1)
                          : "cc");
    return readval;
bellard's avatar
bellard committed
409
410
411
}
#endif

412
413
414
#ifdef __x86_64__
static inline int testandset (int *p)
{
bellard's avatar
bellard committed
415
    long int readval = 0;
416
    
bellard's avatar
bellard committed
417
418
419
420
421
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
                          : "+m" (*p), "+a" (readval)
                          : "r" (1)
                          : "cc");
    return readval;
422
423
424
}
#endif

bellard's avatar
bellard committed
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
#ifdef __s390__
static inline int testandset (int *p)
{
    int ret;

    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
			  "   jl    0b"
			  : "=&d" (ret)
			  : "r" (1), "a" (p), "0" (*p) 
			  : "cc", "memory" );
    return ret;
}
#endif

#ifdef __alpha__
bellard's avatar
bellard committed
440
static inline int testandset (int *p)
bellard's avatar
bellard committed
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
{
    int ret;
    unsigned long one;

    __asm__ __volatile__ ("0:	mov 1,%2\n"
			  "	ldl_l %0,%1\n"
			  "	stl_c %2,%1\n"
			  "	beq %2,1f\n"
			  ".subsection 2\n"
			  "1:	br 0b\n"
			  ".previous"
			  : "=r" (ret), "=m" (*p), "=r" (one)
			  : "m" (*p));
    return ret;
}
#endif

#ifdef __sparc__
static inline int testandset (int *p)
{
	int ret;

	__asm__ __volatile__("ldstub	[%1], %0"
			     : "=r" (ret)
			     : "r" (p)
			     : "memory");

	return (ret ? 1 : 0);
}
#endif

bellard's avatar
bellard committed
472
473
474
475
476
477
478
479
480
481
482
483
#ifdef __arm__
static inline int testandset (int *spinlock)
{
    register unsigned int ret;
    __asm__ __volatile__("swp %0, %1, [%2]"
                         : "=r"(ret)
                         : "0"(1), "r"(spinlock));
    
    return ret;
}
#endif

bellard's avatar
bellard committed
484
485
486
487
488
489
490
491
#ifdef __mc68000
static inline int testandset (int *p)
{
    char ret;
    __asm__ __volatile__("tas %1; sne %0"
                         : "=r" (ret)
                         : "m" (p)
                         : "cc","memory");
bellard's avatar
bellard committed
492
    return ret;
bellard's avatar
bellard committed
493
494
495
}
#endif

bellard's avatar
bellard committed
496
497
498
499
500
501
502
503
504
#ifdef __ia64
#include <ia64intrin.h>

static inline int testandset (int *p)
{
    return __sync_lock_test_and_set (p, 1);
}
#endif

bellard's avatar
bellard committed
505
506
507
508
typedef int spinlock_t;

#define SPIN_LOCK_UNLOCKED 0

bellard's avatar
bellard committed
509
#if defined(CONFIG_USER_ONLY)
bellard's avatar
bellard committed
510
511
512
513
514
515
516
517
518
519
520
521
522
523
static inline void spin_lock(spinlock_t *lock)
{
    while (testandset(lock));
}

static inline void spin_unlock(spinlock_t *lock)
{
    *lock = 0;
}

static inline int spin_trylock(spinlock_t *lock)
{
    return !testandset(lock);
}
524
525
526
527
528
529
530
531
532
533
534
535
536
537
#else
static inline void spin_lock(spinlock_t *lock)
{
}

static inline void spin_unlock(spinlock_t *lock)
{
}

static inline int spin_trylock(spinlock_t *lock)
{
    return 1;
}
#endif
bellard's avatar
bellard committed
538
539
540

extern spinlock_t tb_lock;

541
extern int tb_invalidated_flag;
bellard's avatar
bellard committed
542

543
#if !defined(CONFIG_USER_ONLY)
bellard's avatar
bellard committed
544

bellard's avatar
bellard committed
545
void tlb_fill(target_ulong addr, int is_write, int is_user, 
bellard's avatar
bellard committed
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
              void *retaddr);

#define ACCESS_TYPE 3
#define MEMSUFFIX _code
#define env cpu_single_env

#define DATA_SIZE 1
#include "softmmu_header.h"

#define DATA_SIZE 2
#include "softmmu_header.h"

#define DATA_SIZE 4
#include "softmmu_header.h"

bellard's avatar
bellard committed
561
562
563
#define DATA_SIZE 8
#include "softmmu_header.h"

bellard's avatar
bellard committed
564
565
566
567
568
#undef ACCESS_TYPE
#undef MEMSUFFIX
#undef env

#endif
569
570
571
572
573
574
575
576

#if defined(CONFIG_USER_ONLY)
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
    return addr;
}
#else
/* NOTE: this function can trigger an exception */
577
578
/* NOTE2: the returned address is not exactly the physical address: it
   is the offset relative to phys_ram_base */
579
580
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
bellard's avatar
bellard committed
581
    int is_user, index, pd;
582
583

    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard's avatar
bellard committed
584
#if defined(TARGET_I386)
585
    is_user = ((env->hflags & HF_CPL_MASK) == 3);
bellard's avatar
bellard committed
586
587
#elif defined (TARGET_PPC)
    is_user = msr_pr;
bellard's avatar
bellard committed
588
589
#elif defined (TARGET_MIPS)
    is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
590
591
#elif defined (TARGET_SPARC)
    is_user = (env->psrs == 0);
bellard's avatar
bellard committed
592
593
594
#else
#error "Unimplemented !"
#endif
595
596
    if (__builtin_expect(env->tlb_read[is_user][index].address != 
                         (addr & TARGET_PAGE_MASK), 0)) {
bellard's avatar
bellard committed
597
598
599
600
601
        ldub_code(addr);
    }
    pd = env->tlb_read[is_user][index].address & ~TARGET_PAGE_MASK;
    if (pd > IO_MEM_ROM) {
        cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
602
603
604
605
    }
    return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
}
#endif
bellard's avatar
bellard committed
606
607
608
609
610
611
612


#ifdef USE_KQEMU
int kqemu_init(CPUState *env);
int kqemu_cpu_exec(CPUState *env);
void kqemu_flush_page(CPUState *env, target_ulong addr);
void kqemu_flush(CPUState *env, int global);
bellard's avatar
bellard committed
613
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
bellard's avatar
bellard committed
614
615
616
617
618
619
620
621

static inline int kqemu_is_ok(CPUState *env)
{
    return(env->kqemu_enabled &&
           (env->hflags & HF_CPL_MASK) == 3 &&
           (env->eflags & IOPL_MASK) != IOPL_MASK &&
           (env->cr[0] & CR0_PE_MASK) && 
           (env->eflags & IF_MASK) &&
bellard's avatar
bellard committed
622
623
624
625
626
           !(env->eflags & VM_MASK)
#if 1
           && (env->ldt.limit == 0 || env->ldt.limit == 0x27)
#endif
           );
bellard's avatar
bellard committed
627
628
629
}

#endif