Statistics
| Branch: | Revision:

root / cpu-all.h @ 8b1f24b0

History | View | Annotate | Download (15.4 kB)

1
/*
2
 * defines common to all virtual CPUs
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
#ifndef CPU_ALL_H
21
#define CPU_ALL_H
22

    
23
#if defined(__arm__) || defined(__sparc__)
24
#define WORDS_ALIGNED
25
#endif
26

    
27
/* some important defines: 
28
 * 
29
 * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
30
 * memory accesses.
31
 * 
32
 * WORDS_BIGENDIAN : if defined, the host cpu is big endian and
33
 * otherwise little endian.
34
 * 
35
 * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
36
 * 
37
 * TARGET_WORDS_BIGENDIAN : same for target cpu
38
 */
39

    
40
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
41
typedef union {
42
    double d;
43
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
44
    struct {
45
        uint32_t lower;
46
        uint32_t upper;
47
    } l;
48
#else
49
    struct {
50
        uint32_t upper;
51
        uint32_t lower;
52
    } l;
53
#endif
54
    uint64_t ll;
55
} CPU_DoubleU;
56

    
57
/* CPU memory access without any memory or io remapping */
58

    
59
/*
60
 * the generic syntax for the memory accesses is:
61
 *
62
 * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
63
 *
64
 * store: st{type}{size}{endian}_{access_type}(ptr, val)
65
 *
66
 * type is:
67
 * (empty): integer access
68
 *   f    : float access
69
 * 
70
 * sign is:
71
 * (empty): for floats or 32 bit size
72
 *   u    : unsigned
73
 *   s    : signed
74
 *
75
 * size is:
76
 *   b: 8 bits
77
 *   w: 16 bits
78
 *   l: 32 bits
79
 *   q: 64 bits
80
 * 
81
 * endian is:
82
 * (empty): target cpu endianness or 8 bit access
83
 *   r    : reversed target cpu endianness (not implemented yet)
84
 *   be   : big endian (not implemented yet)
85
 *   le   : little endian (not implemented yet)
86
 *
87
 * access_type is:
88
 *   raw    : host memory access
89
 *   user   : user mode access using soft MMU
90
 *   kernel : kernel mode access using soft MMU
91
 */
92
static inline int ldub_raw(void *ptr)
93
{
94
    return *(uint8_t *)ptr;
95
}
96

    
97
static inline int ldsb_raw(void *ptr)
98
{
99
    return *(int8_t *)ptr;
100
}
101

    
102
static inline void stb_raw(void *ptr, int v)
103
{
104
    *(uint8_t *)ptr = v;
105
}
106

    
107
/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
108
   kernel handles unaligned load/stores may give better results, but
109
   it is a system wide setting : bad */
110
#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
111

    
112
/* conservative code for little endian unaligned accesses */
113
static inline int lduw_raw(void *ptr)
114
{
115
#ifdef __powerpc__
116
    int val;
117
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
118
    return val;
119
#else
120
    uint8_t *p = ptr;
121
    return p[0] | (p[1] << 8);
122
#endif
123
}
124

    
125
static inline int ldsw_raw(void *ptr)
126
{
127
#ifdef __powerpc__
128
    int val;
129
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
130
    return (int16_t)val;
131
#else
132
    uint8_t *p = ptr;
133
    return (int16_t)(p[0] | (p[1] << 8));
134
#endif
135
}
136

    
137
static inline int ldl_raw(void *ptr)
138
{
139
#ifdef __powerpc__
140
    int val;
141
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
142
    return val;
143
#else
144
    uint8_t *p = ptr;
145
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
146
#endif
147
}
148

    
149
static inline uint64_t ldq_raw(void *ptr)
150
{
151
    uint8_t *p = ptr;
152
    uint32_t v1, v2;
153
    v1 = ldl_raw(p);
154
    v2 = ldl_raw(p + 4);
155
    return v1 | ((uint64_t)v2 << 32);
156
}
157

    
158
static inline void stw_raw(void *ptr, int v)
159
{
160
#ifdef __powerpc__
161
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
162
#else
163
    uint8_t *p = ptr;
164
    p[0] = v;
165
    p[1] = v >> 8;
166
#endif
167
}
168

    
169
static inline void stl_raw(void *ptr, int v)
170
{
171
#ifdef __powerpc__
172
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
173
#else
174
    uint8_t *p = ptr;
175
    p[0] = v;
176
    p[1] = v >> 8;
177
    p[2] = v >> 16;
178
    p[3] = v >> 24;
179
#endif
180
}
181

    
182
static inline void stq_raw(void *ptr, uint64_t v)
183
{
184
    uint8_t *p = ptr;
185
    stl_raw(p, (uint32_t)v);
186
    stl_raw(p + 4, v >> 32);
187
}
188

    
189
/* float access */
190

    
191
static inline float ldfl_raw(void *ptr)
192
{
193
    union {
194
        float f;
195
        uint32_t i;
196
    } u;
197
    u.i = ldl_raw(ptr);
198
    return u.f;
199
}
200

    
201
static inline void stfl_raw(void *ptr, float v)
202
{
203
    union {
204
        float f;
205
        uint32_t i;
206
    } u;
207
    u.f = v;
208
    stl_raw(ptr, u.i);
209
}
210

    
211
static inline double ldfq_raw(void *ptr)
212
{
213
    CPU_DoubleU u;
214
    u.l.lower = ldl_raw(ptr);
215
    u.l.upper = ldl_raw(ptr + 4);
216
    return u.d;
217
}
218

    
219
static inline void stfq_raw(void *ptr, double v)
220
{
221
    CPU_DoubleU u;
222
    u.d = v;
223
    stl_raw(ptr, u.l.lower);
224
    stl_raw(ptr + 4, u.l.upper);
225
}
226

    
227
#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
228

    
229
static inline int lduw_raw(void *ptr)
230
{
231
#if defined(__i386__)
232
    int val;
233
    asm volatile ("movzwl %1, %0\n"
234
                  "xchgb %b0, %h0\n"
235
                  : "=q" (val)
236
                  : "m" (*(uint16_t *)ptr));
237
    return val;
238
#else
239
    uint8_t *b = (uint8_t *) ptr;
240
    return ((b[0] << 8) | b[1]);
241
#endif
242
}
243

    
244
static inline int ldsw_raw(void *ptr)
245
{
246
#if defined(__i386__)
247
    int val;
248
    asm volatile ("movzwl %1, %0\n"
249
                  "xchgb %b0, %h0\n"
250
                  : "=q" (val)
251
                  : "m" (*(uint16_t *)ptr));
252
    return (int16_t)val;
253
#else
254
    uint8_t *b = (uint8_t *) ptr;
255
    return (int16_t)((b[0] << 8) | b[1]);
256
#endif
257
}
258

    
259
static inline int ldl_raw(void *ptr)
260
{
261
#if defined(__i386__)
262
    int val;
263
    asm volatile ("movl %1, %0\n"
264
                  "bswap %0\n"
265
                  : "=r" (val)
266
                  : "m" (*(uint32_t *)ptr));
267
    return val;
268
#else
269
    uint8_t *b = (uint8_t *) ptr;
270
    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
271
#endif
272
}
273

    
274
static inline uint64_t ldq_raw(void *ptr)
275
{
276
    uint32_t a,b;
277
    a = ldl_raw(ptr);
278
    b = ldl_raw(ptr+4);
279
    return (((uint64_t)a<<32)|b);
280
}
281

    
282
static inline void stw_raw(void *ptr, int v)
283
{
284
#if defined(__i386__)
285
    asm volatile ("xchgb %b0, %h0\n"
286
                  "movw %w0, %1\n"
287
                  : "=q" (v)
288
                  : "m" (*(uint16_t *)ptr), "0" (v));
289
#else
290
    uint8_t *d = (uint8_t *) ptr;
291
    d[0] = v >> 8;
292
    d[1] = v;
293
#endif
294
}
295

    
296
static inline void stl_raw(void *ptr, int v)
297
{
298
#if defined(__i386__)
299
    asm volatile ("bswap %0\n"
300
                  "movl %0, %1\n"
301
                  : "=r" (v)
302
                  : "m" (*(uint32_t *)ptr), "0" (v));
303
#else
304
    uint8_t *d = (uint8_t *) ptr;
305
    d[0] = v >> 24;
306
    d[1] = v >> 16;
307
    d[2] = v >> 8;
308
    d[3] = v;
309
#endif
310
}
311

    
312
static inline void stq_raw(void *ptr, uint64_t v)
313
{
314
    stl_raw(ptr, v >> 32);
315
    stl_raw(ptr + 4, v);
316
}
317

    
318
/* float access */
319

    
320
static inline float ldfl_raw(void *ptr)
321
{
322
    union {
323
        float f;
324
        uint32_t i;
325
    } u;
326
    u.i = ldl_raw(ptr);
327
    return u.f;
328
}
329

    
330
static inline void stfl_raw(void *ptr, float v)
331
{
332
    union {
333
        float f;
334
        uint32_t i;
335
    } u;
336
    u.f = v;
337
    stl_raw(ptr, u.i);
338
}
339

    
340
static inline double ldfq_raw(void *ptr)
341
{
342
    CPU_DoubleU u;
343
    u.l.upper = ldl_raw(ptr);
344
    u.l.lower = ldl_raw(ptr + 4);
345
    return u.d;
346
}
347

    
348
static inline void stfq_raw(void *ptr, double v)
349
{
350
    CPU_DoubleU u;
351
    u.d = v;
352
    stl_raw(ptr, u.l.upper);
353
    stl_raw(ptr + 4, u.l.lower);
354
}
355

    
356
#else
357

    
358
static inline int lduw_raw(void *ptr)
359
{
360
    return *(uint16_t *)ptr;
361
}
362

    
363
static inline int ldsw_raw(void *ptr)
364
{
365
    return *(int16_t *)ptr;
366
}
367

    
368
static inline int ldl_raw(void *ptr)
369
{
370
    return *(uint32_t *)ptr;
371
}
372

    
373
static inline uint64_t ldq_raw(void *ptr)
374
{
375
    return *(uint64_t *)ptr;
376
}
377

    
378
static inline void stw_raw(void *ptr, int v)
379
{
380
    *(uint16_t *)ptr = v;
381
}
382

    
383
static inline void stl_raw(void *ptr, int v)
384
{
385
    *(uint32_t *)ptr = v;
386
}
387

    
388
static inline void stq_raw(void *ptr, uint64_t v)
389
{
390
    *(uint64_t *)ptr = v;
391
}
392

    
393
/* float access */
394

    
395
static inline float ldfl_raw(void *ptr)
396
{
397
    return *(float *)ptr;
398
}
399

    
400
static inline double ldfq_raw(void *ptr)
401
{
402
    return *(double *)ptr;
403
}
404

    
405
static inline void stfl_raw(void *ptr, float v)
406
{
407
    *(float *)ptr = v;
408
}
409

    
410
static inline void stfq_raw(void *ptr, double v)
411
{
412
    *(double *)ptr = v;
413
}
414
#endif
415

    
416
/* MMU memory access macros */
417

    
418
#if defined(CONFIG_USER_ONLY) 
419

    
420
/* if user mode, no other memory access functions */
421
#define ldub(p) ldub_raw(p)
422
#define ldsb(p) ldsb_raw(p)
423
#define lduw(p) lduw_raw(p)
424
#define ldsw(p) ldsw_raw(p)
425
#define ldl(p) ldl_raw(p)
426
#define ldq(p) ldq_raw(p)
427
#define ldfl(p) ldfl_raw(p)
428
#define ldfq(p) ldfq_raw(p)
429
#define stb(p, v) stb_raw(p, v)
430
#define stw(p, v) stw_raw(p, v)
431
#define stl(p, v) stl_raw(p, v)
432
#define stq(p, v) stq_raw(p, v)
433
#define stfl(p, v) stfl_raw(p, v)
434
#define stfq(p, v) stfq_raw(p, v)
435

    
436
#define ldub_code(p) ldub_raw(p)
437
#define ldsb_code(p) ldsb_raw(p)
438
#define lduw_code(p) lduw_raw(p)
439
#define ldsw_code(p) ldsw_raw(p)
440
#define ldl_code(p) ldl_raw(p)
441

    
442
#define ldub_kernel(p) ldub_raw(p)
443
#define ldsb_kernel(p) ldsb_raw(p)
444
#define lduw_kernel(p) lduw_raw(p)
445
#define ldsw_kernel(p) ldsw_raw(p)
446
#define ldl_kernel(p) ldl_raw(p)
447
#define ldfl_kernel(p) ldfl_raw(p)
448
#define ldfq_kernel(p) ldfq_raw(p)
449
#define stb_kernel(p, v) stb_raw(p, v)
450
#define stw_kernel(p, v) stw_raw(p, v)
451
#define stl_kernel(p, v) stl_raw(p, v)
452
#define stq_kernel(p, v) stq_raw(p, v)
453
#define stfl_kernel(p, v) stfl_raw(p, v)
454
#define stfq_kernel(p, vt) stfq_raw(p, v)
455

    
456
#endif /* defined(CONFIG_USER_ONLY) */
457

    
458
/* page related stuff */
459

    
460
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
461
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
462
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
463

    
464
extern unsigned long real_host_page_size;
465
extern unsigned long host_page_bits;
466
extern unsigned long host_page_size;
467
extern unsigned long host_page_mask;
468

    
469
#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
470

    
471
/* same as PROT_xxx */
472
#define PAGE_READ      0x0001
473
#define PAGE_WRITE     0x0002
474
#define PAGE_EXEC      0x0004
475
#define PAGE_BITS      (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
476
#define PAGE_VALID     0x0008
477
/* original state of the write flag (used when tracking self-modifying
478
   code */
479
#define PAGE_WRITE_ORG 0x0010 
480

    
481
void page_dump(FILE *f);
482
int page_get_flags(unsigned long address);
483
void page_set_flags(unsigned long start, unsigned long end, int flags);
484
void page_unprotect_range(uint8_t *data, unsigned long data_size);
485

    
486
#define SINGLE_CPU_DEFINES
487
#ifdef SINGLE_CPU_DEFINES
488

    
489
#if defined(TARGET_I386)
490

    
491
#define CPUState CPUX86State
492
#define cpu_init cpu_x86_init
493
#define cpu_exec cpu_x86_exec
494
#define cpu_gen_code cpu_x86_gen_code
495
#define cpu_interrupt cpu_x86_interrupt
496
#define cpu_signal_handler cpu_x86_signal_handler
497
#define cpu_dump_state cpu_x86_dump_state
498

    
499
#elif defined(TARGET_ARM)
500

    
501
#define CPUState CPUARMState
502
#define cpu_init cpu_arm_init
503
#define cpu_exec cpu_arm_exec
504
#define cpu_gen_code cpu_arm_gen_code
505
#define cpu_interrupt cpu_arm_interrupt
506
#define cpu_signal_handler cpu_arm_signal_handler
507
#define cpu_dump_state cpu_arm_dump_state
508

    
509
#elif defined(TARGET_SPARC)
510

    
511
#define CPUState CPUSPARCState
512
#define cpu_init cpu_sparc_init
513
#define cpu_exec cpu_sparc_exec
514
#define cpu_gen_code cpu_sparc_gen_code
515
#define cpu_interrupt cpu_sparc_interrupt
516
#define cpu_signal_handler cpu_sparc_signal_handler
517
#define cpu_dump_state cpu_sparc_dump_state
518

    
519
#elif defined(TARGET_PPC)
520

    
521
#define CPUState CPUPPCState
522
#define cpu_init cpu_ppc_init
523
#define cpu_exec cpu_ppc_exec
524
#define cpu_gen_code cpu_ppc_gen_code
525
#define cpu_interrupt cpu_ppc_interrupt
526
#define cpu_signal_handler cpu_ppc_signal_handler
527
#define cpu_dump_state cpu_ppc_dump_state
528

    
529
#else
530

    
531
#error unsupported target CPU
532

    
533
#endif
534

    
535
#endif /* SINGLE_CPU_DEFINES */
536

    
537
#define DEFAULT_GDBSTUB_PORT 1234
538

    
539
void cpu_abort(CPUState *env, const char *fmt, ...);
540
extern CPUState *cpu_single_env;
541
extern int code_copy_enabled;
542

    
543
#define CPU_INTERRUPT_EXIT   0x01 /* wants exit from main loop */
544
#define CPU_INTERRUPT_HARD   0x02 /* hardware interrupt pending */
545
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
546
void cpu_interrupt(CPUState *s, int mask);
547

    
548
int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
549
int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
550
void cpu_single_step(CPUState *env, int enabled);
551

    
552
/* Return the physical page corresponding to a virtual one. Use it
553
   only for debugging because no protection checks are done. Return -1
554
   if no page found. */
555
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
556

    
557
#define CPU_LOG_ALL 1
558
void cpu_set_log(int log_flags);
559
void cpu_set_log_filename(const char *filename);
560

    
561
/* IO ports API */
562

    
563
/* NOTE: as these functions may be even used when there is an isa
564
   brige on non x86 targets, we always defined them */
565
#ifndef NO_CPU_IO_DEFS
566
void cpu_outb(CPUState *env, int addr, int val);
567
void cpu_outw(CPUState *env, int addr, int val);
568
void cpu_outl(CPUState *env, int addr, int val);
569
int cpu_inb(CPUState *env, int addr);
570
int cpu_inw(CPUState *env, int addr);
571
int cpu_inl(CPUState *env, int addr);
572
#endif
573

    
574
/* memory API */
575

    
576
extern int phys_ram_size;
577
extern int phys_ram_fd;
578
extern uint8_t *phys_ram_base;
579
extern uint8_t *phys_ram_dirty;
580

    
581
/* physical memory access */
582
#define IO_MEM_NB_ENTRIES  256
583
#define TLB_INVALID_MASK   (1 << 3)
584
#define IO_MEM_SHIFT       4
585

    
586
#define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
587
#define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
588
#define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
589
#define IO_MEM_CODE        (3 << IO_MEM_SHIFT) /* used internally, never use directly */
590
#define IO_MEM_NOTDIRTY    (4 << IO_MEM_SHIFT) /* used internally, never use directly */
591

    
592
/* NOTE: vaddr is only used internally. Never use it except if you know what you do */
593
typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value, uint32_t vaddr);
594
typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
595

    
596
void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
597
                                  long phys_offset);
598
int cpu_register_io_memory(int io_index,
599
                           CPUReadMemoryFunc **mem_read,
600
                           CPUWriteMemoryFunc **mem_write);
601

    
602
void cpu_physical_memory_rw(target_ulong addr, uint8_t *buf,
603
                            int len, int is_write);
604
static inline void cpu_physical_memory_read(target_ulong addr, uint8_t *buf,
605
                                            int len)
606
{
607
    cpu_physical_memory_rw(addr, buf, len, 0);
608
}
609
static inline void cpu_physical_memory_write(target_ulong addr, const uint8_t *buf,
610
                                            int len)
611
{
612
    cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
613
}
614

    
615
int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
616
                        uint8_t *buf, int len, int is_write);
617

    
618
/* read dirty bit (return 0 or 1) */
619
static inline int cpu_physical_memory_is_dirty(target_ulong addr)
620
{
621
    return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
622
}
623

    
624
static inline void cpu_physical_memory_set_dirty(target_ulong addr)
625
{
626
    phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1;
627
}
628

    
629
void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
630

    
631
/* gdb stub API */
632
extern int gdbstub_fd;
633
CPUState *cpu_gdbstub_get_env(void *opaque);
634
int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port);
635

    
636
#endif /* CPU_ALL_H */