cpu-all.h 29.3 KB
Newer Older
B
bellard 已提交
1 2
/*
 * defines common to all virtual CPUs
3
 *
B
bellard 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *  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
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
B
bellard 已提交
19 20 21 22
 */
#ifndef CPU_ALL_H
#define CPU_ALL_H

B
blueswir1 已提交
23 24
#include "qemu-common.h"

A
aurel32 已提交
25
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
B
bellard 已提交
26 27 28
#define WORDS_ALIGNED
#endif

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

42
#include "bswap.h"
43
#include "softfloat.h"
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif

#ifdef BSWAP_NEEDED

static inline uint16_t tswap16(uint16_t s)
{
    return bswap16(s);
}

static inline uint32_t tswap32(uint32_t s)
{
    return bswap32(s);
}

static inline uint64_t tswap64(uint64_t s)
{
    return bswap64(s);
}

static inline void tswap16s(uint16_t *s)
{
    *s = bswap16(*s);
}

static inline void tswap32s(uint32_t *s)
{
    *s = bswap32(*s);
}

static inline void tswap64s(uint64_t *s)
{
    *s = bswap64(*s);
}

#else

static inline uint16_t tswap16(uint16_t s)
{
    return s;
}

static inline uint32_t tswap32(uint32_t s)
{
    return s;
}

static inline uint64_t tswap64(uint64_t s)
{
    return s;
}

static inline void tswap16s(uint16_t *s)
{
}

static inline void tswap32s(uint32_t *s)
{
}

static inline void tswap64s(uint64_t *s)
{
}

#endif

#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
B
bellard 已提交
115
#define bswaptls(s) bswap32s(s)
116 117 118
#else
#define tswapl(s) tswap64(s)
#define tswapls(s) tswap64s((uint64_t *)(s))
B
bellard 已提交
119
#define bswaptls(s) bswap64s(s)
120 121
#endif

A
aurel32 已提交
122 123 124 125 126
typedef union {
    float32 f;
    uint32_t l;
} CPU_FloatU;

B
bellard 已提交
127 128
/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
   endian ! */
B
bellard 已提交
129
typedef union {
B
bellard 已提交
130
    float64 d;
B
bellard 已提交
131 132
#if defined(WORDS_BIGENDIAN) \
    || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
B
bellard 已提交
133 134
    struct {
        uint32_t upper;
B
bellard 已提交
135
        uint32_t lower;
B
bellard 已提交
136 137 138 139
    } l;
#else
    struct {
        uint32_t lower;
B
bellard 已提交
140
        uint32_t upper;
B
bellard 已提交
141 142 143 144 145
    } l;
#endif
    uint64_t ll;
} CPU_DoubleU;

B
blueswir1 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
#ifdef TARGET_SPARC
typedef union {
    float128 q;
#if defined(WORDS_BIGENDIAN) \
    || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
    struct {
        uint32_t upmost;
        uint32_t upper;
        uint32_t lower;
        uint32_t lowest;
    } l;
    struct {
        uint64_t upper;
        uint64_t lower;
    } ll;
#else
    struct {
        uint32_t lowest;
        uint32_t lower;
        uint32_t upper;
        uint32_t upmost;
    } l;
    struct {
        uint64_t lower;
        uint64_t upper;
    } ll;
#endif
} CPU_QuadU;
#endif

B
bellard 已提交
176 177
/* CPU memory access without any memory or io remapping */

178 179 180 181 182 183 184 185 186 187
/*
 * the generic syntax for the memory accesses is:
 *
 * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
 *
 * store: st{type}{size}{endian}_{access_type}(ptr, val)
 *
 * type is:
 * (empty): integer access
 *   f    : float access
188
 *
189 190 191 192 193 194 195 196 197 198
 * sign is:
 * (empty): for floats or 32 bit size
 *   u    : unsigned
 *   s    : signed
 *
 * size is:
 *   b: 8 bits
 *   w: 16 bits
 *   l: 32 bits
 *   q: 64 bits
199
 *
200 201 202 203 204 205 206 207 208 209 210
 * endian is:
 * (empty): target cpu endianness or 8 bit access
 *   r    : reversed target cpu endianness (not implemented yet)
 *   be   : big endian (not implemented yet)
 *   le   : little endian (not implemented yet)
 *
 * access_type is:
 *   raw    : host memory access
 *   user   : user mode access using soft MMU
 *   kernel : kernel mode access using soft MMU
 */
211
static inline int ldub_p(const void *ptr)
B
bellard 已提交
212 213 214 215
{
    return *(uint8_t *)ptr;
}

216
static inline int ldsb_p(const void *ptr)
B
bellard 已提交
217 218 219 220
{
    return *(int8_t *)ptr;
}

B
bellard 已提交
221
static inline void stb_p(void *ptr, int v)
B
bellard 已提交
222 223 224 225 226 227 228
{
    *(uint8_t *)ptr = v;
}

/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
   kernel handles unaligned load/stores may give better results, but
   it is a system wide setting : bad */
229
#if defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
B
bellard 已提交
230 231

/* conservative code for little endian unaligned accesses */
232
static inline int lduw_le_p(const void *ptr)
B
bellard 已提交
233
{
M
malc 已提交
234
#ifdef _ARCH_PPC
B
bellard 已提交
235 236 237 238
    int val;
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return val;
#else
M
malc 已提交
239
    const uint8_t *p = ptr;
B
bellard 已提交
240 241 242 243
    return p[0] | (p[1] << 8);
#endif
}

244
static inline int ldsw_le_p(const void *ptr)
B
bellard 已提交
245
{
M
malc 已提交
246
#ifdef _ARCH_PPC
B
bellard 已提交
247 248 249 250
    int val;
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return (int16_t)val;
#else
M
malc 已提交
251
    const uint8_t *p = ptr;
B
bellard 已提交
252 253 254 255
    return (int16_t)(p[0] | (p[1] << 8));
#endif
}

256
static inline int ldl_le_p(const void *ptr)
B
bellard 已提交
257
{
M
malc 已提交
258
#ifdef _ARCH_PPC
B
bellard 已提交
259 260 261 262
    int val;
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return val;
#else
M
malc 已提交
263
    const uint8_t *p = ptr;
B
bellard 已提交
264 265 266 267
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
#endif
}

268
static inline uint64_t ldq_le_p(const void *ptr)
B
bellard 已提交
269
{
M
malc 已提交
270
    const uint8_t *p = ptr;
B
bellard 已提交
271
    uint32_t v1, v2;
B
bellard 已提交
272 273
    v1 = ldl_le_p(p);
    v2 = ldl_le_p(p + 4);
B
bellard 已提交
274 275 276
    return v1 | ((uint64_t)v2 << 32);
}

277
static inline void stw_le_p(void *ptr, int v)
B
bellard 已提交
278
{
M
malc 已提交
279
#ifdef _ARCH_PPC
B
bellard 已提交
280 281 282 283 284 285 286 287
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
#else
    uint8_t *p = ptr;
    p[0] = v;
    p[1] = v >> 8;
#endif
}

288
static inline void stl_le_p(void *ptr, int v)
B
bellard 已提交
289
{
M
malc 已提交
290
#ifdef _ARCH_PPC
B
bellard 已提交
291 292 293 294 295 296 297 298 299 300
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
#else
    uint8_t *p = ptr;
    p[0] = v;
    p[1] = v >> 8;
    p[2] = v >> 16;
    p[3] = v >> 24;
#endif
}

301
static inline void stq_le_p(void *ptr, uint64_t v)
B
bellard 已提交
302 303
{
    uint8_t *p = ptr;
B
bellard 已提交
304 305
    stl_le_p(p, (uint32_t)v);
    stl_le_p(p + 4, v >> 32);
B
bellard 已提交
306 307 308 309
}

/* float access */

310
static inline float32 ldfl_le_p(const void *ptr)
B
bellard 已提交
311 312
{
    union {
B
bellard 已提交
313
        float32 f;
B
bellard 已提交
314 315
        uint32_t i;
    } u;
316
    u.i = ldl_le_p(ptr);
B
bellard 已提交
317 318 319
    return u.f;
}

320
static inline void stfl_le_p(void *ptr, float32 v)
B
bellard 已提交
321 322
{
    union {
B
bellard 已提交
323
        float32 f;
B
bellard 已提交
324 325 326
        uint32_t i;
    } u;
    u.f = v;
327
    stl_le_p(ptr, u.i);
B
bellard 已提交
328 329
}

330
static inline float64 ldfq_le_p(const void *ptr)
B
bellard 已提交
331
{
B
bellard 已提交
332
    CPU_DoubleU u;
333 334
    u.l.lower = ldl_le_p(ptr);
    u.l.upper = ldl_le_p(ptr + 4);
B
bellard 已提交
335 336 337
    return u.d;
}

338
static inline void stfq_le_p(void *ptr, float64 v)
B
bellard 已提交
339
{
B
bellard 已提交
340
    CPU_DoubleU u;
B
bellard 已提交
341
    u.d = v;
342 343
    stl_le_p(ptr, u.l.lower);
    stl_le_p(ptr + 4, u.l.upper);
B
bellard 已提交
344 345
}

346 347
#else

348
static inline int lduw_le_p(const void *ptr)
349 350 351 352
{
    return *(uint16_t *)ptr;
}

353
static inline int ldsw_le_p(const void *ptr)
354 355 356
{
    return *(int16_t *)ptr;
}
357

358
static inline int ldl_le_p(const void *ptr)
359 360 361 362
{
    return *(uint32_t *)ptr;
}

363
static inline uint64_t ldq_le_p(const void *ptr)
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
{
    return *(uint64_t *)ptr;
}

static inline void stw_le_p(void *ptr, int v)
{
    *(uint16_t *)ptr = v;
}

static inline void stl_le_p(void *ptr, int v)
{
    *(uint32_t *)ptr = v;
}

static inline void stq_le_p(void *ptr, uint64_t v)
{
    *(uint64_t *)ptr = v;
}

/* float access */

385
static inline float32 ldfl_le_p(const void *ptr)
386 387 388 389
{
    return *(float32 *)ptr;
}

390
static inline float64 ldfq_le_p(const void *ptr)
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
{
    return *(float64 *)ptr;
}

static inline void stfl_le_p(void *ptr, float32 v)
{
    *(float32 *)ptr = v;
}

static inline void stfq_le_p(void *ptr, float64 v)
{
    *(float64 *)ptr = v;
}
#endif

#if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)

408
static inline int lduw_be_p(const void *ptr)
409
{
410 411 412 413 414 415 416 417
#if defined(__i386__)
    int val;
    asm volatile ("movzwl %1, %0\n"
                  "xchgb %b0, %h0\n"
                  : "=q" (val)
                  : "m" (*(uint16_t *)ptr));
    return val;
#else
M
malc 已提交
418
    const uint8_t *b = ptr;
419 420
    return ((b[0] << 8) | b[1]);
#endif
421 422
}

423
static inline int ldsw_be_p(const void *ptr)
424
{
425 426 427 428 429 430 431 432
#if defined(__i386__)
    int val;
    asm volatile ("movzwl %1, %0\n"
                  "xchgb %b0, %h0\n"
                  : "=q" (val)
                  : "m" (*(uint16_t *)ptr));
    return (int16_t)val;
#else
M
malc 已提交
433
    const uint8_t *b = ptr;
434 435
    return (int16_t)((b[0] << 8) | b[1]);
#endif
436 437
}

438
static inline int ldl_be_p(const void *ptr)
439
{
B
bellard 已提交
440
#if defined(__i386__) || defined(__x86_64__)
441 442 443 444 445 446 447
    int val;
    asm volatile ("movl %1, %0\n"
                  "bswap %0\n"
                  : "=r" (val)
                  : "m" (*(uint32_t *)ptr));
    return val;
#else
M
malc 已提交
448
    const uint8_t *b = ptr;
449 450
    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#endif
451 452
}

453
static inline uint64_t ldq_be_p(const void *ptr)
454 455
{
    uint32_t a,b;
456
    a = ldl_be_p(ptr);
457
    b = ldl_be_p((uint8_t *)ptr + 4);
458 459 460
    return (((uint64_t)a<<32)|b);
}

461
static inline void stw_be_p(void *ptr, int v)
462
{
463 464 465 466 467 468
#if defined(__i386__)
    asm volatile ("xchgb %b0, %h0\n"
                  "movw %w0, %1\n"
                  : "=q" (v)
                  : "m" (*(uint16_t *)ptr), "0" (v));
#else
469 470 471
    uint8_t *d = (uint8_t *) ptr;
    d[0] = v >> 8;
    d[1] = v;
472
#endif
473 474
}

475
static inline void stl_be_p(void *ptr, int v)
476
{
B
bellard 已提交
477
#if defined(__i386__) || defined(__x86_64__)
478 479 480 481 482
    asm volatile ("bswap %0\n"
                  "movl %0, %1\n"
                  : "=r" (v)
                  : "m" (*(uint32_t *)ptr), "0" (v));
#else
483 484 485 486 487
    uint8_t *d = (uint8_t *) ptr;
    d[0] = v >> 24;
    d[1] = v >> 16;
    d[2] = v >> 8;
    d[3] = v;
488
#endif
489 490
}

491
static inline void stq_be_p(void *ptr, uint64_t v)
492
{
493
    stl_be_p(ptr, v >> 32);
494
    stl_be_p((uint8_t *)ptr + 4, v);
B
bellard 已提交
495 496 497 498
}

/* float access */

499
static inline float32 ldfl_be_p(const void *ptr)
B
bellard 已提交
500 501
{
    union {
B
bellard 已提交
502
        float32 f;
B
bellard 已提交
503 504
        uint32_t i;
    } u;
505
    u.i = ldl_be_p(ptr);
B
bellard 已提交
506 507 508
    return u.f;
}

509
static inline void stfl_be_p(void *ptr, float32 v)
B
bellard 已提交
510 511
{
    union {
B
bellard 已提交
512
        float32 f;
B
bellard 已提交
513 514 515
        uint32_t i;
    } u;
    u.f = v;
516
    stl_be_p(ptr, u.i);
B
bellard 已提交
517 518
}

519
static inline float64 ldfq_be_p(const void *ptr)
B
bellard 已提交
520 521
{
    CPU_DoubleU u;
522
    u.l.upper = ldl_be_p(ptr);
523
    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
B
bellard 已提交
524 525 526
    return u.d;
}

527
static inline void stfq_be_p(void *ptr, float64 v)
B
bellard 已提交
528 529 530
{
    CPU_DoubleU u;
    u.d = v;
531
    stl_be_p(ptr, u.l.upper);
532
    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
533 534
}

B
bellard 已提交
535 536
#else

537
static inline int lduw_be_p(const void *ptr)
B
bellard 已提交
538 539 540 541
{
    return *(uint16_t *)ptr;
}

542
static inline int ldsw_be_p(const void *ptr)
B
bellard 已提交
543 544 545 546
{
    return *(int16_t *)ptr;
}

547
static inline int ldl_be_p(const void *ptr)
B
bellard 已提交
548 549 550 551
{
    return *(uint32_t *)ptr;
}

552
static inline uint64_t ldq_be_p(const void *ptr)
B
bellard 已提交
553 554 555 556
{
    return *(uint64_t *)ptr;
}

557
static inline void stw_be_p(void *ptr, int v)
B
bellard 已提交
558 559 560 561
{
    *(uint16_t *)ptr = v;
}

562
static inline void stl_be_p(void *ptr, int v)
B
bellard 已提交
563 564 565 566
{
    *(uint32_t *)ptr = v;
}

567
static inline void stq_be_p(void *ptr, uint64_t v)
B
bellard 已提交
568 569 570 571 572 573
{
    *(uint64_t *)ptr = v;
}

/* float access */

574
static inline float32 ldfl_be_p(const void *ptr)
B
bellard 已提交
575
{
B
bellard 已提交
576
    return *(float32 *)ptr;
B
bellard 已提交
577 578
}

579
static inline float64 ldfq_be_p(const void *ptr)
B
bellard 已提交
580
{
B
bellard 已提交
581
    return *(float64 *)ptr;
B
bellard 已提交
582 583
}

584
static inline void stfl_be_p(void *ptr, float32 v)
B
bellard 已提交
585
{
B
bellard 已提交
586
    *(float32 *)ptr = v;
B
bellard 已提交
587 588
}

589
static inline void stfq_be_p(void *ptr, float64 v)
B
bellard 已提交
590
{
B
bellard 已提交
591
    *(float64 *)ptr = v;
B
bellard 已提交
592
}
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620

#endif

/* target CPU memory access functions */
#if defined(TARGET_WORDS_BIGENDIAN)
#define lduw_p(p) lduw_be_p(p)
#define ldsw_p(p) ldsw_be_p(p)
#define ldl_p(p) ldl_be_p(p)
#define ldq_p(p) ldq_be_p(p)
#define ldfl_p(p) ldfl_be_p(p)
#define ldfq_p(p) ldfq_be_p(p)
#define stw_p(p, v) stw_be_p(p, v)
#define stl_p(p, v) stl_be_p(p, v)
#define stq_p(p, v) stq_be_p(p, v)
#define stfl_p(p, v) stfl_be_p(p, v)
#define stfq_p(p, v) stfq_be_p(p, v)
#else
#define lduw_p(p) lduw_le_p(p)
#define ldsw_p(p) ldsw_le_p(p)
#define ldl_p(p) ldl_le_p(p)
#define ldq_p(p) ldq_le_p(p)
#define ldfl_p(p) ldfl_le_p(p)
#define ldfq_p(p) ldfq_le_p(p)
#define stw_p(p, v) stw_le_p(p, v)
#define stl_p(p, v) stl_le_p(p, v)
#define stq_p(p, v) stq_le_p(p, v)
#define stfl_p(p, v) stfl_le_p(p, v)
#define stfq_p(p, v) stfq_le_p(p, v)
B
bellard 已提交
621 622
#endif

B
bellard 已提交
623 624
/* MMU memory access macros */

625
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
626 627 628
#include <assert.h>
#include "qemu-types.h"

629 630 631 632 633 634 635 636
/* On some host systems the guest address space is reserved on the host.
 * This allows the guest address space to be offset to a convenient location.
 */
//#define GUEST_BASE 0x20000000
#define GUEST_BASE 0

/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
A
aurel32 已提交
637 638 639 640 641 642
#define h2g(x) ({ \
    unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
    /* Check if given address fits target address space */ \
    assert(__ret == (abi_ulong)__ret); \
    (abi_ulong)__ret; \
})
A
aurel32 已提交
643 644 645 646
#define h2g_valid(x) ({ \
    unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
    (__guest == (abi_ulong)__guest); \
})
647 648 649 650 651

#define saddr(x) g2h(x)
#define laddr(x) g2h(x)

#else /* !CONFIG_USER_ONLY */
B
bellard 已提交
652 653
/* NOTE: we use double casts if pointers and target_ulong have
   different sizes */
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
#define saddr(x) (uint8_t *)(long)(x)
#define laddr(x) (uint8_t *)(long)(x)
#endif

#define ldub_raw(p) ldub_p(laddr((p)))
#define ldsb_raw(p) ldsb_p(laddr((p)))
#define lduw_raw(p) lduw_p(laddr((p)))
#define ldsw_raw(p) ldsw_p(laddr((p)))
#define ldl_raw(p) ldl_p(laddr((p)))
#define ldq_raw(p) ldq_p(laddr((p)))
#define ldfl_raw(p) ldfl_p(laddr((p)))
#define ldfq_raw(p) ldfq_p(laddr((p)))
#define stb_raw(p, v) stb_p(saddr((p)), v)
#define stw_raw(p, v) stw_p(saddr((p)), v)
#define stl_raw(p, v) stl_p(saddr((p)), v)
#define stq_raw(p, v) stq_p(saddr((p)), v)
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
B
bellard 已提交
672 673


674
#if defined(CONFIG_USER_ONLY)
B
bellard 已提交
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696

/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
#define ldsb(p) ldsb_raw(p)
#define lduw(p) lduw_raw(p)
#define ldsw(p) ldsw_raw(p)
#define ldl(p) ldl_raw(p)
#define ldq(p) ldq_raw(p)
#define ldfl(p) ldfl_raw(p)
#define ldfq(p) ldfq_raw(p)
#define stb(p, v) stb_raw(p, v)
#define stw(p, v) stw_raw(p, v)
#define stl(p, v) stl_raw(p, v)
#define stq(p, v) stq_raw(p, v)
#define stfl(p, v) stfl_raw(p, v)
#define stfq(p, v) stfq_raw(p, v)

#define ldub_code(p) ldub_raw(p)
#define ldsb_code(p) ldsb_raw(p)
#define lduw_code(p) lduw_raw(p)
#define ldsw_code(p) ldsw_raw(p)
#define ldl_code(p) ldl_raw(p)
J
j_mayer 已提交
697
#define ldq_code(p) ldq_raw(p)
B
bellard 已提交
698 699 700 701 702 703

#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
J
j_mayer 已提交
704
#define ldq_kernel(p) ldq_raw(p)
B
bellard 已提交
705 706
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
B
bellard 已提交
707 708 709 710
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
B
bellard 已提交
711 712
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
B
bellard 已提交
713 714 715

#endif /* defined(CONFIG_USER_ONLY) */

B
bellard 已提交
716 717
/* page related stuff */

718
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
B
bellard 已提交
719 720 721
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)

722
/* ??? These should be the larger of unsigned long and target_ulong.  */
723 724 725 726
extern unsigned long qemu_real_host_page_size;
extern unsigned long qemu_host_page_bits;
extern unsigned long qemu_host_page_size;
extern unsigned long qemu_host_page_mask;
B
bellard 已提交
727

728
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
B
bellard 已提交
729 730 731 732 733 734 735 736 737

/* same as PROT_xxx */
#define PAGE_READ      0x0001
#define PAGE_WRITE     0x0002
#define PAGE_EXEC      0x0004
#define PAGE_BITS      (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
#define PAGE_VALID     0x0008
/* original state of the write flag (used when tracking self-modifying
   code */
738
#define PAGE_WRITE_ORG 0x0010
739
#define PAGE_RESERVED  0x0020
B
bellard 已提交
740 741

void page_dump(FILE *f);
742 743
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
744
int page_check_range(target_ulong start, target_ulong len, int flags);
B
bellard 已提交
745

746
void cpu_exec_init_all(unsigned long tb_size);
747 748
CPUState *cpu_copy(CPUState *env);

749
void cpu_dump_state(CPUState *env, FILE *f,
B
bellard 已提交
750 751
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                    int flags);
752 753 754
void cpu_dump_statistics (CPUState *env, FILE *f,
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                          int flags);
B
bellard 已提交
755

M
malc 已提交
756
void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
B
blueswir1 已提交
757
    __attribute__ ((__format__ (__printf__, 2, 3)));
B
bellard 已提交
758
extern CPUState *first_cpu;
B
bellard 已提交
759
extern CPUState *cpu_single_env;
P
pbrook 已提交
760 761
extern int64_t qemu_icount;
extern int use_icount;
B
bellard 已提交
762

763 764
#define CPU_INTERRUPT_HARD   0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
B
bellard 已提交
765
#define CPU_INTERRUPT_TIMER  0x08 /* internal timer exception pending */
B
bellard 已提交
766
#define CPU_INTERRUPT_FIQ    0x10 /* Fast interrupt pending.  */
B
bellard 已提交
767
#define CPU_INTERRUPT_HALT   0x20 /* CPU halt wanted */
B
bellard 已提交
768
#define CPU_INTERRUPT_SMI    0x40 /* (x86 only) SMI interrupt pending */
769
#define CPU_INTERRUPT_DEBUG  0x80 /* Debug event occured.  */
T
ths 已提交
770
#define CPU_INTERRUPT_VIRQ   0x100 /* virtual interrupt pending.  */
A
aurel32 已提交
771
#define CPU_INTERRUPT_NMI    0x200 /* NMI pending. */
B
bellard 已提交
772

B
update  
bellard 已提交
773
void cpu_interrupt(CPUState *s, int mask);
774
void cpu_reset_interrupt(CPUState *env, int mask);
B
bellard 已提交
775

776 777
void cpu_exit(CPUState *s);

778 779 780 781
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ           0x01
#define BP_MEM_WRITE          0x02
#define BP_MEM_ACCESS         (BP_MEM_READ | BP_MEM_WRITE)
782
#define BP_STOP_BEFORE_ACCESS 0x04
783
#define BP_WATCHPOINT_HIT     0x08
784
#define BP_GDB                0x10
785
#define BP_CPU                0x20
786 787 788 789 790 791 792 793 794 795 796 797

int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
                          CPUBreakpoint **breakpoint);
int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags);
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint);
void cpu_breakpoint_remove_all(CPUState *env, int mask);
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
                          int flags, CPUWatchpoint **watchpoint);
int cpu_watchpoint_remove(CPUState *env, target_ulong addr,
                          target_ulong len, int flags);
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint);
void cpu_watchpoint_remove_all(CPUState *env, int mask);
798 799 800 801 802

#define SSTEP_ENABLE  0x1  /* Enable simulated HW single stepping */
#define SSTEP_NOIRQ   0x2  /* Do not use IRQ while single stepping */
#define SSTEP_NOTIMER 0x4  /* Do not Timers while single stepping */

B
bellard 已提交
803
void cpu_single_step(CPUState *env, int enabled);
B
bellard 已提交
804
void cpu_reset(CPUState *s);
B
bellard 已提交
805

B
bellard 已提交
806 807 808
/* Return the physical page corresponding to a virtual one. Use it
   only for debugging because no protection checks are done. Return -1
   if no page found. */
809
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
B
bellard 已提交
810

811
#define CPU_LOG_TB_OUT_ASM (1 << 0)
812
#define CPU_LOG_TB_IN_ASM  (1 << 1)
813 814 815 816 817
#define CPU_LOG_TB_OP      (1 << 2)
#define CPU_LOG_TB_OP_OPT  (1 << 3)
#define CPU_LOG_INT        (1 << 4)
#define CPU_LOG_EXEC       (1 << 5)
#define CPU_LOG_PCALL      (1 << 6)
818
#define CPU_LOG_IOPORT     (1 << 7)
819
#define CPU_LOG_TB_CPU     (1 << 8)
A
aliguori 已提交
820
#define CPU_LOG_RESET      (1 << 9)
821 822 823 824 825 826 827 828

/* define log items */
typedef struct CPULogItem {
    int mask;
    const char *name;
    const char *help;
} CPULogItem;

B
blueswir1 已提交
829
extern const CPULogItem cpu_log_items[];
830

831 832
void cpu_set_log(int log_flags);
void cpu_set_log_filename(const char *filename);
833
int cpu_str_to_log_mask(const char *str);
834

B
bellard 已提交
835 836 837 838 839 840 841 842 843 844 845 846 847
/* IO ports API */

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

848 849 850 851 852 853 854
/* address in the RAM (different from a physical address) */
#ifdef USE_KQEMU
typedef uint32_t ram_addr_t;
#else
typedef unsigned long ram_addr_t;
#endif

855 856
/* memory API */

857
extern ram_addr_t phys_ram_size;
B
bellard 已提交
858 859
extern int phys_ram_fd;
extern uint8_t *phys_ram_base;
860
extern uint8_t *phys_ram_dirty;
861
extern ram_addr_t ram_size;
B
bellard 已提交
862 863

/* physical memory access */
P
pbrook 已提交
864 865 866 867 868 869

/* MMIO pages are identified by a combination of an IO device index and
   3 flags.  The ROMD code stores the page ram offset in iotlb entry, 
   so only a limited number of ids are avaiable.  */

#define IO_MEM_SHIFT       3
B
bellard 已提交
870
#define IO_MEM_NB_ENTRIES  (1 << (TARGET_PAGE_BITS  - IO_MEM_SHIFT))
B
bellard 已提交
871 872 873 874

#define IO_MEM_RAM         (0 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
P
pbrook 已提交
875 876 877
#define IO_MEM_NOTDIRTY    (3 << IO_MEM_SHIFT)

/* Acts like a ROM when read and like a device when written.  */
878
#define IO_MEM_ROMD        (1)
879
#define IO_MEM_SUBPAGE     (2)
880
#define IO_MEM_SUBWIDTH    (4)
B
bellard 已提交
881

P
pbrook 已提交
882 883 884 885 886 887 888 889 890 891
/* Flags stored in the low bits of the TLB virtual address.  These are
   defined so that fast path ram access is all zeros.  */
/* Zero if TLB entry is valid.  */
#define TLB_INVALID_MASK   (1 << 3)
/* Set if TLB entry references a clean RAM page.  The iotlb entry will
   contain the page physical address.  */
#define TLB_NOTDIRTY    (1 << 4)
/* Set if TLB entry is an IO callback.  */
#define TLB_MMIO        (1 << 5)

B
bellard 已提交
892 893
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
894

895 896 897 898 899 900 901 902 903 904 905
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
                                         ram_addr_t size,
                                         ram_addr_t phys_offset,
                                         ram_addr_t region_offset);
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
                                                ram_addr_t size,
                                                ram_addr_t phys_offset)
{
    cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
}

906 907
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
ram_addr_t qemu_ram_alloc(ram_addr_t);
B
bellard 已提交
908
void qemu_ram_free(ram_addr_t addr);
909 910
/* This should only be used for ram local to a device.  */
void *qemu_get_ram_ptr(ram_addr_t addr);
P
pbrook 已提交
911 912 913
/* This should not be used by devices.  */
ram_addr_t qemu_ram_addr_from_host(void *ptr);

914 915
int cpu_register_io_memory(int io_index,
                           CPUReadMemoryFunc **mem_read,
B
bellard 已提交
916 917
                           CPUWriteMemoryFunc **mem_write,
                           void *opaque);
918
void cpu_unregister_io_memory(int table_address);
B
bellard 已提交
919 920
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
921

922
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
B
bellard 已提交
923
                            int len, int is_write);
924
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
925
                                            uint8_t *buf, int len)
926 927 928
{
    cpu_physical_memory_rw(addr, buf, len, 0);
}
929
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
930
                                             const uint8_t *buf, int len)
931 932 933
{
    cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
934 935 936 937 938
void *cpu_physical_memory_map(target_phys_addr_t addr,
                              target_phys_addr_t *plen,
                              int is_write);
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
                               int is_write, target_phys_addr_t access_len);
939 940
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
941

B
bellard 已提交
942 943
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_phys(target_phys_addr_t addr);
B
bellard 已提交
944
uint32_t ldl_phys(target_phys_addr_t addr);
B
bellard 已提交
945
uint64_t ldq_phys(target_phys_addr_t addr);
B
bellard 已提交
946
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
J
j_mayer 已提交
947
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
B
bellard 已提交
948 949
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
B
bellard 已提交
950
void stl_phys(target_phys_addr_t addr, uint32_t val);
B
bellard 已提交
951
void stq_phys(target_phys_addr_t addr, uint64_t val);
952

953
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
B
bellard 已提交
954
                                   const uint8_t *buf, int len);
955
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
956
                        uint8_t *buf, int len, int is_write);
B
bellard 已提交
957

A
aliguori 已提交
958 959 960 961
#define VGA_DIRTY_FLAG       0x01
#define CODE_DIRTY_FLAG      0x02
#define KQEMU_DIRTY_FLAG     0x04
#define MIGRATION_DIRTY_FLAG 0x08
B
bellard 已提交
962

963
/* read dirty bit (return 0 or 1) */
B
bellard 已提交
964
static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
965
{
B
bellard 已提交
966 967 968
    return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
}

969
static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
B
bellard 已提交
970 971 972
                                                int dirty_flags)
{
    return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
973 974
}

B
bellard 已提交
975
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
976
{
B
bellard 已提交
977
    phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
978 979
}

B
bellard 已提交
980
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
B
bellard 已提交
981
                                     int dirty_flags);
B
bellard 已提交
982
void cpu_tlb_update_dirty(CPUState *env);
983

A
aliguori 已提交
984 985 986 987
int cpu_physical_memory_set_dirty_tracking(int enable);

int cpu_physical_memory_get_dirty_tracking(void);

A
aliguori 已提交
988 989
void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr);

B
bellard 已提交
990 991 992
void dump_exec_info(FILE *f,
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...));

A
aliguori 已提交
993 994 995 996 997 998 999 1000 1001
/* Coalesced MMIO regions are areas where write operations can be reordered.
 * This usually implies that write operations are side-effect free.  This allows
 * batching which can make a major impact on performance when using
 * virtualization.
 */
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);

void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);

B
bellard 已提交
1002 1003 1004
/*******************************************/
/* host CPU ticks (if available) */

M
malc 已提交
1005
#if defined(_ARCH_PPC)
B
bellard 已提交
1006 1007 1008

static inline int64_t cpu_get_real_ticks(void)
{
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
    int64_t retval;
#ifdef _ARCH_PPC64
    /* This reads timebase in one 64bit go and includes Cell workaround from:
       http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
     */
    __asm__ __volatile__ (
        "mftb    %0\n\t"
        "cmpwi   %0,0\n\t"
        "beq-    $-8"
        : "=r" (retval));
#else
    /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
    unsigned long junk;
    __asm__ __volatile__ (
        "mftbu   %1\n\t"
        "mftb    %L0\n\t"
        "mftbu   %0\n\t"
        "cmpw    %0,%1\n\t"
        "bne     $-16"
        : "=r" (retval), "=r" (junk));
#endif
    return retval;
B
bellard 已提交
1031 1032 1033 1034 1035
}

#elif defined(__i386__)

static inline int64_t cpu_get_real_ticks(void)
B
bellard 已提交
1036 1037 1038 1039 1040 1041
{
    int64_t val;
    asm volatile ("rdtsc" : "=A" (val));
    return val;
}

B
bellard 已提交
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
#elif defined(__x86_64__)

static inline int64_t cpu_get_real_ticks(void)
{
    uint32_t low,high;
    int64_t val;
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
    val = high;
    val <<= 32;
    val |= low;
    return val;
}

A
aurel32 已提交
1055 1056 1057 1058 1059 1060 1061 1062 1063
#elif defined(__hppa__)

static inline int64_t cpu_get_real_ticks(void)
{
    int val;
    asm volatile ("mfctl %%cr16, %0" : "=r"(val));
    return val;
}

B
bellard 已提交
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
#elif defined(__ia64)

static inline int64_t cpu_get_real_ticks(void)
{
	int64_t val;
	asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
	return val;
}

#elif defined(__s390__)

static inline int64_t cpu_get_real_ticks(void)
{
    int64_t val;
    asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
    return val;
}

1082
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
B
bellard 已提交
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102

static inline int64_t cpu_get_real_ticks (void)
{
#if     defined(_LP64)
        uint64_t        rval;
        asm volatile("rd %%tick,%0" : "=r"(rval));
        return rval;
#else
        union {
                uint64_t i64;
                struct {
                        uint32_t high;
                        uint32_t low;
                }       i32;
        } rval;
        asm volatile("rd %%tick,%1; srlx %1,32,%0"
                : "=r"(rval.i32.high), "=r"(rval.i32.low));
        return rval.i64;
#endif
}
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

#elif defined(__mips__)

static inline int64_t cpu_get_real_ticks(void)
{
#if __mips_isa_rev >= 2
    uint32_t count;
    static uint32_t cyc_per_count = 0;

    if (!cyc_per_count)
        __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count));

    __asm__ __volatile__("rdhwr %1, $2" : "=r" (count));
    return (int64_t)(count * cyc_per_count);
#else
    /* FIXME */
    static int64_t ticks = 0;
    return ticks++;
#endif
}

P
pbrook 已提交
1124 1125
#else
/* The host CPU doesn't have an easily accessible cycle counter.
T
ths 已提交
1126 1127
   Just return a monotonically increasing value.  This will be
   totally wrong, but hopefully better than nothing.  */
P
pbrook 已提交
1128 1129 1130 1131 1132
static inline int64_t cpu_get_real_ticks (void)
{
    static int64_t ticks = 0;
    return ticks++;
}
B
bellard 已提交
1133 1134 1135 1136 1137 1138 1139 1140 1141
#endif

/* profiling */
#ifdef CONFIG_PROFILER
static inline int64_t profile_getclock(void)
{
    return cpu_get_real_ticks();
}

B
bellard 已提交
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
extern int64_t kqemu_time, kqemu_time_start;
extern int64_t qemu_time, qemu_time_start;
extern int64_t tlb_flush_time;
extern int64_t kqemu_exec_count;
extern int64_t dev_time;
extern int64_t kqemu_ret_int_count;
extern int64_t kqemu_ret_excp_count;
extern int64_t kqemu_ret_intr_count;
#endif

B
bellard 已提交
1152
#endif /* CPU_ALL_H */