op_helper.c 116.6 KB
Newer Older
1
#include "exec.h"
B
blueswir1 已提交
2
#include "host-utils.h"
B
blueswir1 已提交
3
#include "helper.h"
4

B
bellard 已提交
5
//#define DEBUG_MMU
6
//#define DEBUG_MXCC
B
blueswir1 已提交
7
//#define DEBUG_UNALIGNED
8
//#define DEBUG_UNASSIGNED
9
//#define DEBUG_ASI
B
blueswir1 已提交
10
//#define DEBUG_PCALL
11
//#define DEBUG_PSTATE
B
bellard 已提交
12

13
#ifdef DEBUG_MMU
14 15
#define DPRINTF_MMU(fmt, ...)                                   \
    do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
16
#else
17
#define DPRINTF_MMU(fmt, ...) do {} while (0)
18 19 20
#endif

#ifdef DEBUG_MXCC
21 22
#define DPRINTF_MXCC(fmt, ...)                                  \
    do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
23
#else
24
#define DPRINTF_MXCC(fmt, ...) do {} while (0)
25 26
#endif

27
#ifdef DEBUG_ASI
28 29
#define DPRINTF_ASI(fmt, ...)                                   \
    do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
30 31
#endif

32 33 34 35 36 37 38
#ifdef DEBUG_PSTATE
#define DPRINTF_PSTATE(fmt, ...)                                   \
    do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
#endif

B
blueswir1 已提交
39 40 41
#ifdef TARGET_SPARC64
#ifndef TARGET_ABI32
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
42
#else
B
blueswir1 已提交
43 44
#define AM_CHECK(env1) (1)
#endif
45 46
#endif

47 48 49 50 51
#define DT0 (env->dt0)
#define DT1 (env->dt1)
#define QT0 (env->qt0)
#define QT1 (env->qt1)

P
Paul Brook 已提交
52 53 54 55 56
#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
                          int is_asi, int size);
#endif

57
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
58 59 60 61 62 63
// Calculates TSB pointer value for fault page size 8k or 64k
static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
                                       uint64_t tag_access_register,
                                       int page_size)
{
    uint64_t tsb_base = tsb_register & ~0x1fffULL;
64 65
    int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
    int tsb_size  = tsb_register & 0xf;
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

    // discard lower 13 bits which hold tag access context
    uint64_t tag_access_va = tag_access_register & ~0x1fffULL;

    // now reorder bits
    uint64_t tsb_base_mask = ~0x1fffULL;
    uint64_t va = tag_access_va;

    // move va bits to correct position
    if (page_size == 8*1024) {
        va >>= 9;
    } else if (page_size == 64*1024) {
        va >>= 12;
    }

    if (tsb_size) {
        tsb_base_mask <<= tsb_size;
    }

    // calculate tsb_base mask and adjust va if split is in use
    if (tsb_split) {
        if (page_size == 8*1024) {
            va &= ~(1ULL << (13 + tsb_size));
        } else if (page_size == 64*1024) {
            va |= (1ULL << (13 + tsb_size));
        }
        tsb_base_mask <<= 1;
    }

    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
}

// Calculates tag target register value by reordering bits
// in tag access register
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
{
    return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
}

105 106 107
static void replace_tlb_entry(SparcTLBEntry *tlb,
                              uint64_t tlb_tag, uint64_t tlb_tte,
                              CPUState *env1)
108 109 110 111
{
    target_ulong mask, size, va, offset;

    // flush page range if translation is valid
112
    if (TTE_IS_VALID(tlb->tte)) {
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

        mask = 0xffffffffffffe000ULL;
        mask <<= 3 * ((tlb->tte >> 61) & 3);
        size = ~mask + 1;

        va = tlb->tag & mask;

        for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
            tlb_flush_page(env1, va + offset);
        }
    }

    tlb->tag = tlb_tag;
    tlb->tte = tlb_tte;
}

static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
130
                      const char* strmmu, CPUState *env1)
131 132 133
{
    unsigned int i;
    target_ulong mask;
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
    uint64_t context;

    int is_demap_context = (demap_addr >> 6) & 1;

    // demap context
    switch ((demap_addr >> 4) & 3) {
    case 0: // primary
        context = env1->dmmu.mmu_primary_context;
        break;
    case 1: // secondary
        context = env1->dmmu.mmu_secondary_context;
        break;
    case 2: // nucleus
        context = 0;
        break;
    case 3: // reserved
    default:
        return;
    }
153 154

    for (i = 0; i < 64; i++) {
155
        if (TTE_IS_VALID(tlb[i].tte)) {
156

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
            if (is_demap_context) {
                // will remove non-global entries matching context value
                if (TTE_IS_GLOBAL(tlb[i].tte) ||
                    !tlb_compare_context(&tlb[i], context)) {
                    continue;
                }
            } else {
                // demap page
                // will remove any entry matching VA
                mask = 0xffffffffffffe000ULL;
                mask <<= 3 * ((tlb[i].tte >> 61) & 3);

                if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
                    continue;
                }

                // entry should be global or matching context value
                if (!TTE_IS_GLOBAL(tlb[i].tte) &&
                    !tlb_compare_context(&tlb[i], context)) {
                    continue;
                }
            }
179

180
            replace_tlb_entry(&tlb[i], 0, 0, env1);
181
#ifdef DEBUG_MMU
182
            DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
183
            dump_mmu(stdout, fprintf, env1);
184 185 186 187 188
#endif
        }
    }
}

189 190 191 192 193 194 195 196 197 198 199 200
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
                                 uint64_t tlb_tag, uint64_t tlb_tte,
                                 const char* strmmu, CPUState *env1)
{
    unsigned int i, replace_used;

    // Try replacing invalid entry
    for (i = 0; i < 64; i++) {
        if (!TTE_IS_VALID(tlb[i].tte)) {
            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
#ifdef DEBUG_MMU
            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
201
            dump_mmu(stdout, fprintf, env1);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
#endif
            return;
        }
    }

    // All entries are valid, try replacing unlocked entry

    for (replace_used = 0; replace_used < 2; ++replace_used) {

        // Used entries are not replaced on first pass

        for (i = 0; i < 64; i++) {
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {

                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
#ifdef DEBUG_MMU
                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
                            strmmu, (replace_used?"used":"unused"), i);
220
                dump_mmu(stdout, fprintf, env1);
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#endif
                return;
            }
        }

        // Now reset used bit and search for unused entries again

        for (i = 0; i < 64; i++) {
            TTE_SET_UNUSED(tlb[i].tte);
        }
    }

#ifdef DEBUG_MMU
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
#endif
    // error state?
}

239 240
#endif

241
static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
B
blueswir1 已提交
242 243 244
{
#ifdef TARGET_SPARC64
    if (AM_CHECK(env1))
245
        addr &= 0xffffffffULL;
B
blueswir1 已提交
246
#endif
247
    return addr;
B
blueswir1 已提交
248 249
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
/* returns true if access using this ASI is to have address translated by MMU
   otherwise access is to raw physical address */
static inline int is_translating_asi(int asi)
{
#ifdef TARGET_SPARC64
    /* Ultrasparc IIi translating asi
       - note this list is defined by cpu implementation
     */
    switch (asi) {
    case 0x04 ... 0x11:
    case 0x18 ... 0x19:
    case 0x24 ... 0x2C:
    case 0x70 ... 0x73:
    case 0x78 ... 0x79:
    case 0x80 ... 0xFF:
        return 1;

    default:
        return 0;
    }
#else
    /* TODO: check sparc32 bits */
    return 0;
#endif
}

static inline target_ulong asi_address_mask(CPUState *env1,
                                            int asi, target_ulong addr)
{
    if (is_translating_asi(asi)) {
        return address_mask(env, addr);
    } else {
        return addr;
    }
}

B
blueswir1 已提交
286
static void raise_exception(int tt)
B
bellard 已提交
287 288 289
{
    env->exception_index = tt;
    cpu_loop_exit();
290
}
B
bellard 已提交
291

P
pbrook 已提交
292 293 294 295 296
void HELPER(raise_exception)(int tt)
{
    raise_exception(tt);
}

B
blueswir1 已提交
297 298
void helper_check_align(target_ulong addr, uint32_t align)
{
299 300 301 302 303
    if (addr & align) {
#ifdef DEBUG_UNALIGNED
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
           "\n", addr, env->pc);
#endif
B
blueswir1 已提交
304
        raise_exception(TT_UNALIGNED);
305
    }
B
blueswir1 已提交
306 307
}

308 309 310
#define F_HELPER(name, p) void helper_f##name##p(void)

#define F_BINOP(name)                                           \
B
blueswir1 已提交
311
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
312
    {                                                           \
B
blueswir1 已提交
313
        return float32_ ## name (src1, src2, &env->fp_status);  \
314 315 316 317
    }                                                           \
    F_HELPER(name, d)                                           \
    {                                                           \
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
B
blueswir1 已提交
318 319 320 321
    }                                                           \
    F_HELPER(name, q)                                           \
    {                                                           \
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
322 323 324 325 326 327 328 329
    }

F_BINOP(add);
F_BINOP(sub);
F_BINOP(mul);
F_BINOP(div);
#undef F_BINOP

330
void helper_fsmuld(float32 src1, float32 src2)
B
blueswir1 已提交
331
{
332 333
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
                      float32_to_float64(src2, &env->fp_status),
334 335
                      &env->fp_status);
}
B
blueswir1 已提交
336

B
blueswir1 已提交
337 338 339 340 341 342 343
void helper_fdmulq(void)
{
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
                       float64_to_float128(DT1, &env->fp_status),
                       &env->fp_status);
}

B
blueswir1 已提交
344
float32 helper_fnegs(float32 src)
345
{
B
blueswir1 已提交
346
    return float32_chs(src);
347 348
}

349 350
#ifdef TARGET_SPARC64
F_HELPER(neg, d)
351
{
352
    DT0 = float64_chs(DT1);
353
}
B
blueswir1 已提交
354 355 356 357 358 359

F_HELPER(neg, q)
{
    QT0 = float128_chs(QT1);
}
#endif
360 361

/* Integer to float conversion.  */
B
blueswir1 已提交
362
float32 helper_fitos(int32_t src)
B
bellard 已提交
363
{
B
blueswir1 已提交
364
    return int32_to_float32(src, &env->fp_status);
B
bellard 已提交
365 366
}

367
void helper_fitod(int32_t src)
B
bellard 已提交
368
{
369
    DT0 = int32_to_float64(src, &env->fp_status);
B
bellard 已提交
370
}
371

372
void helper_fitoq(int32_t src)
B
blueswir1 已提交
373
{
374
    QT0 = int32_to_float128(src, &env->fp_status);
B
blueswir1 已提交
375 376
}

B
blueswir1 已提交
377
#ifdef TARGET_SPARC64
378
float32 helper_fxtos(void)
B
blueswir1 已提交
379
{
380
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
B
blueswir1 已提交
381 382
}

383
F_HELPER(xto, d)
B
blueswir1 已提交
384 385 386
{
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
}
B
blueswir1 已提交
387

B
blueswir1 已提交
388 389 390 391 392
F_HELPER(xto, q)
{
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
}
#endif
393 394 395
#undef F_HELPER

/* floating point conversion */
396
float32 helper_fdtos(void)
397
{
398
    return float64_to_float32(DT1, &env->fp_status);
399 400
}

401
void helper_fstod(float32 src)
402
{
403
    DT0 = float32_to_float64(src, &env->fp_status);
404
}
405

406
float32 helper_fqtos(void)
B
blueswir1 已提交
407
{
408
    return float128_to_float32(QT1, &env->fp_status);
B
blueswir1 已提交
409 410
}

411
void helper_fstoq(float32 src)
B
blueswir1 已提交
412
{
413
    QT0 = float32_to_float128(src, &env->fp_status);
B
blueswir1 已提交
414 415 416 417 418 419 420 421 422 423 424 425
}

void helper_fqtod(void)
{
    DT0 = float128_to_float64(QT1, &env->fp_status);
}

void helper_fdtoq(void)
{
    QT0 = float64_to_float128(DT1, &env->fp_status);
}

426
/* Float to integer conversion.  */
B
blueswir1 已提交
427
int32_t helper_fstoi(float32 src)
428
{
B
blueswir1 已提交
429
    return float32_to_int32_round_to_zero(src, &env->fp_status);
430 431
}

432
int32_t helper_fdtoi(void)
433
{
434
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
435 436
}

437
int32_t helper_fqtoi(void)
B
blueswir1 已提交
438
{
439
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
B
blueswir1 已提交
440 441
}

442
#ifdef TARGET_SPARC64
443
void helper_fstox(float32 src)
444
{
445
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
446 447 448 449 450 451 452
}

void helper_fdtox(void)
{
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
}

B
blueswir1 已提交
453 454 455 456 457
void helper_fqtox(void)
{
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
}

458 459 460 461 462
void helper_faligndata(void)
{
    uint64_t tmp;

    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
B
blueswir1 已提交
463 464 465 466
    /* on many architectures a shift of 64 does nothing */
    if ((env->gsr & 7) != 0) {
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
    }
467 468 469
    *((uint64_t *)&DT0) = tmp;
}

470
#ifdef HOST_WORDS_BIGENDIAN
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 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 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
#define VIS_B64(n) b[7 - (n)]
#define VIS_W64(n) w[3 - (n)]
#define VIS_SW64(n) sw[3 - (n)]
#define VIS_L64(n) l[1 - (n)]
#define VIS_B32(n) b[3 - (n)]
#define VIS_W32(n) w[1 - (n)]
#else
#define VIS_B64(n) b[n]
#define VIS_W64(n) w[n]
#define VIS_SW64(n) sw[n]
#define VIS_L64(n) l[n]
#define VIS_B32(n) b[n]
#define VIS_W32(n) w[n]
#endif

typedef union {
    uint8_t b[8];
    uint16_t w[4];
    int16_t sw[4];
    uint32_t l[2];
    float64 d;
} vis64;

typedef union {
    uint8_t b[4];
    uint16_t w[2];
    uint32_t l;
    float32 f;
} vis32;

void helper_fpmerge(void)
{
    vis64 s, d;

    s.d = DT0;
    d.d = DT1;

    // Reverse calculation order to handle overlap
    d.VIS_B64(7) = s.VIS_B64(3);
    d.VIS_B64(6) = d.VIS_B64(3);
    d.VIS_B64(5) = s.VIS_B64(2);
    d.VIS_B64(4) = d.VIS_B64(2);
    d.VIS_B64(3) = s.VIS_B64(1);
    d.VIS_B64(2) = d.VIS_B64(1);
    d.VIS_B64(1) = s.VIS_B64(0);
    //d.VIS_B64(0) = d.VIS_B64(0);

    DT0 = d.d;
}

void helper_fmul8x16(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                 \
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
    if ((tmp & 0xff) > 0x7f)                                    \
        tmp += 0x100;                                           \
    d.VIS_W64(r) = tmp >> 8;

    PMUL(0);
    PMUL(1);
    PMUL(2);
    PMUL(3);
#undef PMUL

    DT0 = d.d;
}

void helper_fmul8x16al(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                 \
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
    if ((tmp & 0xff) > 0x7f)                                    \
        tmp += 0x100;                                           \
    d.VIS_W64(r) = tmp >> 8;

    PMUL(0);
    PMUL(1);
    PMUL(2);
    PMUL(3);
#undef PMUL

    DT0 = d.d;
}

void helper_fmul8x16au(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                 \
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
    if ((tmp & 0xff) > 0x7f)                                    \
        tmp += 0x100;                                           \
    d.VIS_W64(r) = tmp >> 8;

    PMUL(0);
    PMUL(1);
    PMUL(2);
    PMUL(3);
#undef PMUL

    DT0 = d.d;
}

void helper_fmul8sux16(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                         \
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
    if ((tmp & 0xff) > 0x7f)                                            \
        tmp += 0x100;                                                   \
    d.VIS_W64(r) = tmp >> 8;

    PMUL(0);
    PMUL(1);
    PMUL(2);
    PMUL(3);
#undef PMUL

    DT0 = d.d;
}

void helper_fmul8ulx16(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                         \
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
    if ((tmp & 0xff) > 0x7f)                                            \
        tmp += 0x100;                                                   \
    d.VIS_W64(r) = tmp >> 8;

    PMUL(0);
    PMUL(1);
    PMUL(2);
    PMUL(3);
#undef PMUL

    DT0 = d.d;
}

void helper_fmuld8sux16(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                         \
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
    if ((tmp & 0xff) > 0x7f)                                            \
        tmp += 0x100;                                                   \
    d.VIS_L64(r) = tmp;

    // Reverse calculation order to handle overlap
    PMUL(1);
    PMUL(0);
#undef PMUL

    DT0 = d.d;
}

void helper_fmuld8ulx16(void)
{
    vis64 s, d;
    uint32_t tmp;

    s.d = DT0;
    d.d = DT1;

#define PMUL(r)                                                         \
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
    if ((tmp & 0xff) > 0x7f)                                            \
        tmp += 0x100;                                                   \
    d.VIS_L64(r) = tmp;

    // Reverse calculation order to handle overlap
    PMUL(1);
    PMUL(0);
#undef PMUL

    DT0 = d.d;
}

void helper_fexpand(void)
{
    vis32 s;
    vis64 d;

    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
    d.d = DT1;
687 688 689 690
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710

    DT0 = d.d;
}

#define VIS_HELPER(name, F)                             \
    void name##16(void)                                 \
    {                                                   \
        vis64 s, d;                                     \
                                                        \
        s.d = DT0;                                      \
        d.d = DT1;                                      \
                                                        \
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
                                                        \
        DT0 = d.d;                                      \
    }                                                   \
                                                        \
B
blueswir1 已提交
711
    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
712 713 714
    {                                                   \
        vis32 s, d;                                     \
                                                        \
B
blueswir1 已提交
715 716
        s.l = src1;                                     \
        d.l = src2;                                     \
717 718 719 720
                                                        \
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
                                                        \
B
blueswir1 已提交
721
        return d.l;                                     \
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
    }                                                   \
                                                        \
    void name##32(void)                                 \
    {                                                   \
        vis64 s, d;                                     \
                                                        \
        s.d = DT0;                                      \
        d.d = DT1;                                      \
                                                        \
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
                                                        \
        DT0 = d.d;                                      \
    }                                                   \
                                                        \
B
blueswir1 已提交
737
    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
738 739 740
    {                                                   \
        vis32 s, d;                                     \
                                                        \
B
blueswir1 已提交
741 742
        s.l = src1;                                     \
        d.l = src2;                                     \
743 744 745
                                                        \
        d.l = F(d.l, s.l);                              \
                                                        \
B
blueswir1 已提交
746
        return d.l;                                     \
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
    }

#define FADD(a, b) ((a) + (b))
#define FSUB(a, b) ((a) - (b))
VIS_HELPER(helper_fpadd, FADD)
VIS_HELPER(helper_fpsub, FSUB)

#define VIS_CMPHELPER(name, F)                                        \
    void name##16(void)                                           \
    {                                                             \
        vis64 s, d;                                               \
                                                                  \
        s.d = DT0;                                                \
        d.d = DT1;                                                \
                                                                  \
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
                                                                  \
        DT0 = d.d;                                                \
    }                                                             \
                                                                  \
    void name##32(void)                                           \
    {                                                             \
        vis64 s, d;                                               \
                                                                  \
        s.d = DT0;                                                \
        d.d = DT1;                                                \
                                                                  \
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
                                                                  \
        DT0 = d.d;                                                \
    }

#define FCMPGT(a, b) ((a) > (b))
#define FCMPEQ(a, b) ((a) == (b))
#define FCMPLE(a, b) ((a) <= (b))
#define FCMPNE(a, b) ((a) != (b))

VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
VIS_CMPHELPER(helper_fcmple, FCMPLE)
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
#endif

void helper_check_ieee_exceptions(void)
{
    target_ulong status;

    status = get_float_exception_flags(&env->fp_status);
    if (status) {
        /* Copy IEEE 754 flags into FSR */
        if (status & float_flag_invalid)
            env->fsr |= FSR_NVC;
        if (status & float_flag_overflow)
            env->fsr |= FSR_OFC;
        if (status & float_flag_underflow)
            env->fsr |= FSR_UFC;
        if (status & float_flag_divbyzero)
            env->fsr |= FSR_DZC;
        if (status & float_flag_inexact)
            env->fsr |= FSR_NXC;

        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
            /* Unmasked exception, generate a trap */
            env->fsr |= FSR_FTT_IEEE_EXCP;
            raise_exception(TT_FP_EXCP);
        } else {
            /* Accumulate exceptions */
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
        }
    }
}

void helper_clear_float_exceptions(void)
{
    set_float_exception_flags(0, &env->fp_status);
}

B
blueswir1 已提交
828
float32 helper_fabss(float32 src)
829
{
B
blueswir1 已提交
830
    return float32_abs(src);
831 832
}

B
bellard 已提交
833
#ifdef TARGET_SPARC64
834
void helper_fabsd(void)
B
bellard 已提交
835 836 837
{
    DT0 = float64_abs(DT1);
}
B
blueswir1 已提交
838 839 840 841 842 843

void helper_fabsq(void)
{
    QT0 = float128_abs(QT1);
}
#endif
B
bellard 已提交
844

B
blueswir1 已提交
845
float32 helper_fsqrts(float32 src)
846
{
B
blueswir1 已提交
847
    return float32_sqrt(src, &env->fp_status);
848 849
}

850
void helper_fsqrtd(void)
851
{
B
bellard 已提交
852
    DT0 = float64_sqrt(DT1, &env->fp_status);
853 854
}

B
blueswir1 已提交
855 856 857 858 859
void helper_fsqrtq(void)
{
    QT0 = float128_sqrt(QT1, &env->fp_status);
}

860
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
861
    void glue(helper_, name) (void)                                     \
B
bellard 已提交
862
    {                                                                   \
B
blueswir1 已提交
863 864
        target_ulong new_fsr;                                           \
                                                                        \
B
bellard 已提交
865 866 867
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
        case float_relation_unordered:                                  \
B
blueswir1 已提交
868
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
869
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
B
blueswir1 已提交
870
                env->fsr |= new_fsr;                                    \
871 872
                env->fsr |= FSR_NVC;                                    \
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
B
bellard 已提交
873 874 875 876 877 878
                raise_exception(TT_FP_EXCP);                            \
            } else {                                                    \
                env->fsr |= FSR_NVA;                                    \
            }                                                           \
            break;                                                      \
        case float_relation_less:                                       \
B
blueswir1 已提交
879
            new_fsr = FSR_FCC0 << FS;                                   \
B
bellard 已提交
880 881
            break;                                                      \
        case float_relation_greater:                                    \
B
blueswir1 已提交
882
            new_fsr = FSR_FCC1 << FS;                                   \
B
bellard 已提交
883 884
            break;                                                      \
        default:                                                        \
B
blueswir1 已提交
885
            new_fsr = 0;                                                \
B
bellard 已提交
886 887
            break;                                                      \
        }                                                               \
B
blueswir1 已提交
888
        env->fsr |= new_fsr;                                            \
889
    }
B
blueswir1 已提交
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
#define GEN_FCMPS(name, size, FS, TRAP)                                 \
    void glue(helper_, name)(float32 src1, float32 src2)                \
    {                                                                   \
        target_ulong new_fsr;                                           \
                                                                        \
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
        case float_relation_unordered:                                  \
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
                env->fsr |= new_fsr;                                    \
                env->fsr |= FSR_NVC;                                    \
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
                raise_exception(TT_FP_EXCP);                            \
            } else {                                                    \
                env->fsr |= FSR_NVA;                                    \
            }                                                           \
            break;                                                      \
        case float_relation_less:                                       \
            new_fsr = FSR_FCC0 << FS;                                   \
            break;                                                      \
        case float_relation_greater:                                    \
            new_fsr = FSR_FCC1 << FS;                                   \
            break;                                                      \
        default:                                                        \
            new_fsr = 0;                                                \
            break;                                                      \
        }                                                               \
        env->fsr |= new_fsr;                                            \
    }
920

B
blueswir1 已提交
921
GEN_FCMPS(fcmps, float32, 0, 0);
922 923
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);

B
blueswir1 已提交
924
GEN_FCMPS(fcmpes, float32, 0, 1);
925
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
B
bellard 已提交
926

B
blueswir1 已提交
927 928 929
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);

930 931 932 933 934 935 936 937 938 939
static uint32_t compute_all_flags(void)
{
    return env->psr & PSR_ICC;
}

static uint32_t compute_C_flags(void)
{
    return env->psr & PSR_CARRY;
}

940
static inline uint32_t get_NZ_icc(int32_t dst)
B
Blue Swirl 已提交
941 942 943
{
    uint32_t ret = 0;

944 945 946 947 948
    if (dst == 0) {
        ret = PSR_ZERO;
    } else if (dst < 0) {
        ret = PSR_NEG;
    }
B
Blue Swirl 已提交
949 950 951
    return ret;
}

952 953 954 955 956 957 958 959 960 961 962
#ifdef TARGET_SPARC64
static uint32_t compute_all_flags_xcc(void)
{
    return env->xcc & PSR_ICC;
}

static uint32_t compute_C_flags_xcc(void)
{
    return env->xcc & PSR_CARRY;
}

963
static inline uint32_t get_NZ_xcc(target_long dst)
B
Blue Swirl 已提交
964 965 966
{
    uint32_t ret = 0;

967 968 969 970 971
    if (!dst) {
        ret = PSR_ZERO;
    } else if (dst < 0) {
        ret = PSR_NEG;
    }
B
Blue Swirl 已提交
972 973 974 975
    return ret;
}
#endif

B
Blue Swirl 已提交
976 977 978 979
static inline uint32_t get_V_div_icc(target_ulong src2)
{
    uint32_t ret = 0;

980 981 982
    if (src2 != 0) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
    return ret;
}

static uint32_t compute_all_div(void)
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
    ret |= get_V_div_icc(CC_SRC2);
    return ret;
}

static uint32_t compute_C_div(void)
{
    return 0;
}

1000
static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
B
Blue Swirl 已提交
1001 1002 1003
{
    uint32_t ret = 0;

1004 1005 1006
    if (dst < src1) {
        ret = PSR_CARRY;
    }
B
Blue Swirl 已提交
1007 1008 1009
    return ret;
}

1010 1011
static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
                                      uint32_t src2)
B
Blue Swirl 已提交
1012 1013 1014
{
    uint32_t ret = 0;

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
    if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
        ret = PSR_CARRY;
    }
    return ret;
}

static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
                                     uint32_t src2)
{
    uint32_t ret = 0;

    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
1029 1030 1031 1032 1033 1034 1035 1036
    return ret;
}

#ifdef TARGET_SPARC64
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
{
    uint32_t ret = 0;

1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
    if (dst < src1) {
        ret = PSR_CARRY;
    }
    return ret;
}

static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
                                      target_ulong src2)
{
    uint32_t ret = 0;

    if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
        ret = PSR_CARRY;
    }
B
Blue Swirl 已提交
1051 1052 1053 1054 1055 1056 1057 1058
    return ret;
}

static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
                                         target_ulong src2)
{
    uint32_t ret = 0;

1059 1060 1061
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
    return ret;
}

static uint32_t compute_all_add_xcc(void)
{
    uint32_t ret;

    ret = get_NZ_xcc(CC_DST);
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_C_add_xcc(void)
{
    return get_C_add_xcc(CC_DST, CC_SRC);
}
1079 1080
#endif

1081
static uint32_t compute_all_add(void)
B
Blue Swirl 已提交
1082 1083 1084 1085
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1086
    ret |= get_C_add_icc(CC_DST, CC_SRC);
B
Blue Swirl 已提交
1087 1088 1089 1090
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

1091
static uint32_t compute_C_add(void)
B
Blue Swirl 已提交
1092
{
1093
    return get_C_add_icc(CC_DST, CC_SRC);
B
Blue Swirl 已提交
1094 1095 1096 1097 1098 1099 1100 1101
}

#ifdef TARGET_SPARC64
static uint32_t compute_all_addx_xcc(void)
{
    uint32_t ret;

    ret = get_NZ_xcc(CC_DST);
1102
    ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1103 1104 1105 1106 1107 1108 1109 1110
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_C_addx_xcc(void)
{
    uint32_t ret;

1111
    ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1112 1113 1114 1115
    return ret;
}
#endif

1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
static uint32_t compute_all_addx(void)
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_C_addx(void)
{
    uint32_t ret;

    ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

B
Blue Swirl 已提交
1134 1135 1136 1137
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
{
    uint32_t ret = 0;

1138 1139 1140
    if ((src1 | src2) & 0x3) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
1141 1142 1143 1144 1145 1146 1147 1148
    return ret;
}

static uint32_t compute_all_tadd(void)
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1149
    ret |= get_C_add_icc(CC_DST, CC_SRC);
B
Blue Swirl 已提交
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_all_taddtv(void)
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1160
    ret |= get_C_add_icc(CC_DST, CC_SRC);
B
Blue Swirl 已提交
1161 1162 1163
    return ret;
}

1164
static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
B
Blue Swirl 已提交
1165
{
1166 1167 1168 1169 1170 1171
    uint32_t ret = 0;

    if (src1 < src2) {
        ret = PSR_CARRY;
    }
    return ret;
B
Blue Swirl 已提交
1172 1173
}

1174 1175
static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
                                      uint32_t src2)
B
Blue Swirl 已提交
1176 1177 1178
{
    uint32_t ret = 0;

1179 1180 1181
    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
        ret = PSR_CARRY;
    }
B
Blue Swirl 已提交
1182 1183 1184
    return ret;
}

1185 1186
static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
                                     uint32_t src2)
B
Blue Swirl 已提交
1187 1188 1189
{
    uint32_t ret = 0;

1190 1191 1192
    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
1193 1194 1195 1196 1197 1198 1199 1200 1201
    return ret;
}


#ifdef TARGET_SPARC64
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
{
    uint32_t ret = 0;

1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
    if (src1 < src2) {
        ret = PSR_CARRY;
    }
    return ret;
}

static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
                                      target_ulong src2)
{
    uint32_t ret = 0;

    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
        ret = PSR_CARRY;
    }
B
Blue Swirl 已提交
1216 1217 1218 1219 1220 1221 1222 1223
    return ret;
}

static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
                                     target_ulong src2)
{
    uint32_t ret = 0;

1224 1225 1226
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
        ret = PSR_OVF;
    }
B
Blue Swirl 已提交
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
    return ret;
}

static uint32_t compute_all_sub_xcc(void)
{
    uint32_t ret;

    ret = get_NZ_xcc(CC_DST);
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_C_sub_xcc(void)
{
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
}
#endif

1246
static uint32_t compute_all_sub(void)
B
Blue Swirl 已提交
1247 1248 1249 1250
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1251
    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1252 1253 1254 1255
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

1256
static uint32_t compute_C_sub(void)
B
Blue Swirl 已提交
1257
{
1258
    return get_C_sub_icc(CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1259 1260 1261 1262 1263 1264 1265 1266
}

#ifdef TARGET_SPARC64
static uint32_t compute_all_subx_xcc(void)
{
    uint32_t ret;

    ret = get_NZ_xcc(CC_DST);
1267
    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1268 1269 1270 1271 1272 1273 1274 1275
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

static uint32_t compute_C_subx_xcc(void)
{
    uint32_t ret;

1276
    ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1277 1278 1279 1280
    return ret;
}
#endif

1281
static uint32_t compute_all_subx(void)
B
Blue Swirl 已提交
1282 1283 1284 1285
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1286
    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1287 1288 1289 1290
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
}

1291
static uint32_t compute_C_subx(void)
B
Blue Swirl 已提交
1292
{
1293 1294 1295 1296
    uint32_t ret;

    ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
    return ret;
B
Blue Swirl 已提交
1297 1298
}

1299
static uint32_t compute_all_tsub(void)
B
Blue Swirl 已提交
1300 1301 1302 1303
{
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
1304 1305 1306
    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
B
Blue Swirl 已提交
1307 1308 1309
    return ret;
}

1310
static uint32_t compute_all_tsubtv(void)
B
Blue Swirl 已提交
1311
{
1312 1313 1314 1315 1316
    uint32_t ret;

    ret = get_NZ_icc(CC_DST);
    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
    return ret;
B
Blue Swirl 已提交
1317 1318
}

1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
static uint32_t compute_all_logic(void)
{
    return get_NZ_icc(CC_DST);
}

static uint32_t compute_C_logic(void)
{
    return 0;
}

#ifdef TARGET_SPARC64
static uint32_t compute_all_logic_xcc(void)
{
    return get_NZ_xcc(CC_DST);
}
#endif

1336 1337 1338 1339 1340 1341 1342 1343
typedef struct CCTable {
    uint32_t (*compute_all)(void); /* return all the flags */
    uint32_t (*compute_c)(void);  /* return the C flag */
} CCTable;

static const CCTable icc_table[CC_OP_NB] = {
    /* CC_OP_DYNAMIC should never happen */
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
B
Blue Swirl 已提交
1344
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
B
Blue Swirl 已提交
1345
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1346 1347 1348
    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
B
Blue Swirl 已提交
1349
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1350 1351 1352
    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
1353
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1354 1355 1356 1357 1358 1359
};

#ifdef TARGET_SPARC64
static const CCTable xcc_table[CC_OP_NB] = {
    /* CC_OP_DYNAMIC should never happen */
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
B
Blue Swirl 已提交
1360
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
B
Blue Swirl 已提交
1361
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
B
Blue Swirl 已提交
1362
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
B
Blue Swirl 已提交
1363 1364
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
B
Blue Swirl 已提交
1365
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
B
Blue Swirl 已提交
1366
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
B
Blue Swirl 已提交
1367 1368
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1369
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
};
#endif

void helper_compute_psr(void)
{
    uint32_t new_psr;

    new_psr = icc_table[CC_OP].compute_all();
    env->psr = new_psr;
#ifdef TARGET_SPARC64
    new_psr = xcc_table[CC_OP].compute_all();
    env->xcc = new_psr;
#endif
    CC_OP = CC_OP_FLAGS;
}

1386
uint32_t helper_compute_C_icc(void)
1387 1388 1389 1390 1391 1392 1393
{
    uint32_t ret;

    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
    return ret;
}

1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
static inline void memcpy32(target_ulong *dst, const target_ulong *src)
{
    dst[0] = src[0];
    dst[1] = src[1];
    dst[2] = src[2];
    dst[3] = src[3];
    dst[4] = src[4];
    dst[5] = src[5];
    dst[6] = src[6];
    dst[7] = src[7];
}

static void set_cwp(int new_cwp)
{
    /* put the modified wrap registers at their proper location */
    if (env->cwp == env->nwindows - 1) {
        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
    }
    env->cwp = new_cwp;

    /* put the wrap registers at their temporary location */
    if (new_cwp == env->nwindows - 1) {
        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
    }
    env->regwptr = env->regbase + (new_cwp * 16);
}

void cpu_set_cwp(CPUState *env1, int new_cwp)
{
    CPUState *saved_env;

    saved_env = env;
    env = env1;
    set_cwp(new_cwp);
    env = saved_env;
}

static target_ulong get_psr(void)
{
    helper_compute_psr();

#if !defined (TARGET_SPARC64)
    return env->version | (env->psr & PSR_ICC) |
        (env->psref? PSR_EF : 0) |
        (env->psrpil << 8) |
        (env->psrs? PSR_S : 0) |
        (env->psrps? PSR_PS : 0) |
        (env->psret? PSR_ET : 0) | env->cwp;
#else
1443
    return env->psr & PSR_ICC;
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461
#endif
}

target_ulong cpu_get_psr(CPUState *env1)
{
    CPUState *saved_env;
    target_ulong ret;

    saved_env = env;
    env = env1;
    ret = get_psr();
    env = saved_env;
    return ret;
}

static void put_psr(target_ulong val)
{
    env->psr = val & PSR_ICC;
1462
#if !defined (TARGET_SPARC64)
1463 1464
    env->psref = (val & PSR_EF)? 1 : 0;
    env->psrpil = (val & PSR_PIL) >> 8;
1465
#endif
1466 1467 1468
#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
    cpu_check_irqs(env);
#endif
1469
#if !defined (TARGET_SPARC64)
1470 1471 1472 1473
    env->psrs = (val & PSR_S)? 1 : 0;
    env->psrps = (val & PSR_PS)? 1 : 0;
    env->psret = (val & PSR_ET)? 1 : 0;
    set_cwp(val & PSR_CWP);
1474
#endif
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
    env->cc_op = CC_OP_FLAGS;
}

void cpu_put_psr(CPUState *env1, target_ulong val)
{
    CPUState *saved_env;

    saved_env = env;
    env = env1;
    put_psr(val);
    env = saved_env;
}

static int cwp_inc(int cwp)
{
    if (unlikely(cwp >= env->nwindows)) {
        cwp -= env->nwindows;
    }
    return cwp;
}

int cpu_cwp_inc(CPUState *env1, int cwp)
{
    CPUState *saved_env;
    target_ulong ret;

    saved_env = env;
    env = env1;
    ret = cwp_inc(cwp);
    env = saved_env;
    return ret;
}

static int cwp_dec(int cwp)
{
    if (unlikely(cwp < 0)) {
        cwp += env->nwindows;
    }
    return cwp;
}

int cpu_cwp_dec(CPUState *env1, int cwp)
{
    CPUState *saved_env;
    target_ulong ret;

    saved_env = env;
    env = env1;
    ret = cwp_dec(cwp);
    env = saved_env;
    return ret;
}

B
bellard 已提交
1528
#ifdef TARGET_SPARC64
B
blueswir1 已提交
1529
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1530
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
B
blueswir1 已提交
1531
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1532

B
blueswir1 已提交
1533
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1534
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
B
blueswir1 已提交
1535
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1536

B
blueswir1 已提交
1537
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1538
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
B
blueswir1 已提交
1539
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1540

B
blueswir1 已提交
1541
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1542
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
B
blueswir1 已提交
1543
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
B
bellard 已提交
1544

B
blueswir1 已提交
1545
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1546
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
B
blueswir1 已提交
1547
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
B
bellard 已提交
1548

B
blueswir1 已提交
1549
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1550
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
B
blueswir1 已提交
1551 1552
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
#endif
B
blueswir1 已提交
1553
#undef GEN_FCMPS
B
bellard 已提交
1554

B
blueswir1 已提交
1555 1556
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
    defined(DEBUG_MXCC)
1557 1558
static void dump_mxcc(CPUState *env)
{
1559 1560
    printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
           "\n",
B
blueswir1 已提交
1561 1562
           env->mxccdata[0], env->mxccdata[1],
           env->mxccdata[2], env->mxccdata[3]);
1563 1564 1565 1566
    printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
           "\n"
           "          %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
           "\n",
B
blueswir1 已提交
1567 1568 1569 1570
           env->mxccregs[0], env->mxccregs[1],
           env->mxccregs[2], env->mxccregs[3],
           env->mxccregs[4], env->mxccregs[5],
           env->mxccregs[6], env->mxccregs[7]);
1571 1572 1573
}
#endif

B
blueswir1 已提交
1574 1575 1576 1577
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
    && defined(DEBUG_ASI)
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
                     uint64_t r1)
1578 1579 1580 1581
{
    switch (size)
    {
    case 1:
B
blueswir1 已提交
1582 1583
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
                    addr, asi, r1 & 0xff);
1584 1585
        break;
    case 2:
B
blueswir1 已提交
1586 1587
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
                    addr, asi, r1 & 0xffff);
1588 1589
        break;
    case 4:
B
blueswir1 已提交
1590 1591
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
                    addr, asi, r1 & 0xffffffff);
1592 1593
        break;
    case 8:
B
blueswir1 已提交
1594 1595
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
                    addr, asi, r1);
1596 1597 1598 1599 1600
        break;
    }
}
#endif

B
blueswir1 已提交
1601 1602 1603
#ifndef TARGET_SPARC64
#ifndef CONFIG_USER_ONLY
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1604
{
B
blueswir1 已提交
1605
    uint64_t ret = 0;
1606
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
B
blueswir1 已提交
1607
    uint32_t last_addr = addr;
1608
#endif
B
bellard 已提交
1609

1610
    helper_check_align(addr, size - 1);
B
bellard 已提交
1611
    switch (asi) {
1612
    case 2: /* SuperSparc MXCC registers */
B
blueswir1 已提交
1613
        switch (addr) {
1614
        case 0x01c00a00: /* MXCC control register */
B
blueswir1 已提交
1615 1616 1617
            if (size == 8)
                ret = env->mxccregs[3];
            else
B
blueswir1 已提交
1618 1619
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1620 1621 1622 1623 1624
            break;
        case 0x01c00a04: /* MXCC control register */
            if (size == 4)
                ret = env->mxccregs[3];
            else
B
blueswir1 已提交
1625 1626
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1627
            break;
1628 1629
        case 0x01c00c00: /* Module reset register */
            if (size == 8) {
B
blueswir1 已提交
1630
                ret = env->mxccregs[5];
1631 1632
                // should we do something here?
            } else
B
blueswir1 已提交
1633 1634
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1635
            break;
1636
        case 0x01c00f00: /* MBus port address register */
B
blueswir1 已提交
1637 1638 1639
            if (size == 8)
                ret = env->mxccregs[7];
            else
B
blueswir1 已提交
1640 1641
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1642 1643
            break;
        default:
B
blueswir1 已提交
1644 1645
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
                         size);
1646 1647
            break;
        }
B
blueswir1 已提交
1648
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1649
                     "addr = %08x -> ret = %" PRIx64 ","
B
blueswir1 已提交
1650
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1651 1652 1653
#ifdef DEBUG_MXCC
        dump_mxcc(env);
#endif
1654
        break;
1655
    case 3: /* MMU probe */
B
blueswir1 已提交
1656 1657 1658
        {
            int mmulev;

B
blueswir1 已提交
1659
            mmulev = (addr >> 8) & 15;
B
blueswir1 已提交
1660 1661
            if (mmulev > 4)
                ret = 0;
B
blueswir1 已提交
1662 1663 1664 1665
            else
                ret = mmu_probe(env, addr, mmulev);
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
                        addr, mmulev, ret);
B
blueswir1 已提交
1666 1667
        }
        break;
1668
    case 4: /* read MMU regs */
B
blueswir1 已提交
1669
        {
B
blueswir1 已提交
1670
            int reg = (addr >> 8) & 0x1f;
1671

B
blueswir1 已提交
1672 1673
            ret = env->mmuregs[reg];
            if (reg == 3) /* Fault status cleared on read */
B
blueswir1 已提交
1674 1675 1676 1677 1678
                env->mmuregs[3] = 0;
            else if (reg == 0x13) /* Fault status read */
                ret = env->mmuregs[3];
            else if (reg == 0x14) /* Fault address read */
                ret = env->mmuregs[4];
B
blueswir1 已提交
1679
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
B
blueswir1 已提交
1680 1681
        }
        break;
B
blueswir1 已提交
1682 1683 1684 1685
    case 5: // Turbosparc ITLB Diagnostic
    case 6: // Turbosparc DTLB Diagnostic
    case 7: // Turbosparc IOTLB Diagnostic
        break;
1686 1687 1688
    case 9: /* Supervisor code access */
        switch(size) {
        case 1:
B
blueswir1 已提交
1689
            ret = ldub_code(addr);
1690 1691
            break;
        case 2:
1692
            ret = lduw_code(addr);
1693 1694 1695
            break;
        default:
        case 4:
1696
            ret = ldl_code(addr);
1697 1698
            break;
        case 8:
1699
            ret = ldq_code(addr);
1700 1701 1702
            break;
        }
        break;
1703 1704 1705
    case 0xa: /* User data access */
        switch(size) {
        case 1:
B
blueswir1 已提交
1706
            ret = ldub_user(addr);
1707 1708
            break;
        case 2:
1709
            ret = lduw_user(addr);
1710 1711 1712
            break;
        default:
        case 4:
1713
            ret = ldl_user(addr);
1714 1715
            break;
        case 8:
1716
            ret = ldq_user(addr);
1717 1718 1719 1720 1721 1722
            break;
        }
        break;
    case 0xb: /* Supervisor data access */
        switch(size) {
        case 1:
B
blueswir1 已提交
1723
            ret = ldub_kernel(addr);
1724 1725
            break;
        case 2:
1726
            ret = lduw_kernel(addr);
1727 1728 1729
            break;
        default:
        case 4:
1730
            ret = ldl_kernel(addr);
1731 1732
            break;
        case 8:
1733
            ret = ldq_kernel(addr);
1734 1735 1736
            break;
        }
        break;
1737 1738 1739 1740 1741 1742
    case 0xc: /* I-cache tag */
    case 0xd: /* I-cache data */
    case 0xe: /* D-cache tag */
    case 0xf: /* D-cache data */
        break;
    case 0x20: /* MMU passthrough */
B
bellard 已提交
1743 1744
        switch(size) {
        case 1:
B
blueswir1 已提交
1745
            ret = ldub_phys(addr);
B
bellard 已提交
1746 1747
            break;
        case 2:
1748
            ret = lduw_phys(addr);
B
bellard 已提交
1749 1750 1751
            break;
        default:
        case 4:
1752
            ret = ldl_phys(addr);
B
bellard 已提交
1753
            break;
B
bellard 已提交
1754
        case 8:
1755
            ret = ldq_phys(addr);
B
blueswir1 已提交
1756
            break;
B
bellard 已提交
1757
        }
B
blueswir1 已提交
1758
        break;
1759
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1760 1761
        switch(size) {
        case 1:
A
Anthony Liguori 已提交
1762 1763
            ret = ldub_phys((target_phys_addr_t)addr
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1764 1765
            break;
        case 2:
A
Anthony Liguori 已提交
1766 1767
            ret = lduw_phys((target_phys_addr_t)addr
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1768 1769 1770
            break;
        default:
        case 4:
A
Anthony Liguori 已提交
1771 1772
            ret = ldl_phys((target_phys_addr_t)addr
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1773 1774
            break;
        case 8:
A
Anthony Liguori 已提交
1775 1776
            ret = ldq_phys((target_phys_addr_t)addr
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
B
blueswir1 已提交
1777
            break;
1778
        }
B
blueswir1 已提交
1779
        break;
B
blueswir1 已提交
1780 1781 1782
    case 0x30: // Turbosparc secondary cache diagnostic
    case 0x31: // Turbosparc RAM snoop
    case 0x32: // Turbosparc page table descriptor diagnostic
B
blueswir1 已提交
1783
    case 0x39: /* data cache diagnostic register */
1784
    case 0x4c: /* SuperSPARC MMU Breakpoint Action register */
B
blueswir1 已提交
1785 1786
        ret = 0;
        break;
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
        {
            int reg = (addr >> 8) & 3;

            switch(reg) {
            case 0: /* Breakpoint Value (Addr) */
                ret = env->mmubpregs[reg];
                break;
            case 1: /* Breakpoint Mask */
                ret = env->mmubpregs[reg];
                break;
            case 2: /* Breakpoint Control */
                ret = env->mmubpregs[reg];
                break;
            case 3: /* Breakpoint Status */
                ret = env->mmubpregs[reg];
                env->mmubpregs[reg] = 0ULL;
                break;
            }
1806 1807
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
                        ret);
1808 1809
        }
        break;
B
blueswir1 已提交
1810
    case 8: /* User code access, XXX */
1811
    default:
1812
        do_unassigned_access(addr, 0, 0, asi, size);
B
blueswir1 已提交
1813 1814
        ret = 0;
        break;
1815
    }
1816 1817 1818
    if (sign) {
        switch(size) {
        case 1:
B
blueswir1 已提交
1819
            ret = (int8_t) ret;
B
blueswir1 已提交
1820
            break;
1821
        case 2:
B
blueswir1 已提交
1822 1823 1824 1825
            ret = (int16_t) ret;
            break;
        case 4:
            ret = (int32_t) ret;
B
blueswir1 已提交
1826
            break;
1827 1828 1829 1830
        default:
            break;
        }
    }
1831
#ifdef DEBUG_ASI
B
blueswir1 已提交
1832
    dump_asi("read ", last_addr, asi, size, ret);
1833
#endif
B
blueswir1 已提交
1834
    return ret;
1835 1836
}

B
blueswir1 已提交
1837
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1838
{
1839
    helper_check_align(addr, size - 1);
1840
    switch(asi) {
1841
    case 2: /* SuperSparc MXCC registers */
B
blueswir1 已提交
1842
        switch (addr) {
1843 1844
        case 0x01c00000: /* MXCC stream data register 0 */
            if (size == 8)
B
blueswir1 已提交
1845
                env->mxccdata[0] = val;
1846
            else
B
blueswir1 已提交
1847 1848
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1849 1850 1851
            break;
        case 0x01c00008: /* MXCC stream data register 1 */
            if (size == 8)
B
blueswir1 已提交
1852
                env->mxccdata[1] = val;
1853
            else
B
blueswir1 已提交
1854 1855
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1856 1857 1858
            break;
        case 0x01c00010: /* MXCC stream data register 2 */
            if (size == 8)
B
blueswir1 已提交
1859
                env->mxccdata[2] = val;
1860
            else
B
blueswir1 已提交
1861 1862
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1863 1864 1865
            break;
        case 0x01c00018: /* MXCC stream data register 3 */
            if (size == 8)
B
blueswir1 已提交
1866
                env->mxccdata[3] = val;
1867
            else
B
blueswir1 已提交
1868 1869
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1870 1871 1872
            break;
        case 0x01c00100: /* MXCC stream source */
            if (size == 8)
B
blueswir1 已提交
1873
                env->mxccregs[0] = val;
1874
            else
B
blueswir1 已提交
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
                                        0);
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
                                        8);
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
                                        16);
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
                                        24);
1885 1886 1887
            break;
        case 0x01c00200: /* MXCC stream destination */
            if (size == 8)
B
blueswir1 已提交
1888
                env->mxccregs[1] = val;
1889
            else
B
blueswir1 已提交
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
                     env->mxccdata[0]);
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
                     env->mxccdata[1]);
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
                     env->mxccdata[2]);
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
                     env->mxccdata[3]);
1900 1901 1902
            break;
        case 0x01c00a00: /* MXCC control register */
            if (size == 8)
B
blueswir1 已提交
1903
                env->mxccregs[3] = val;
1904
            else
B
blueswir1 已提交
1905 1906
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1907 1908 1909
            break;
        case 0x01c00a04: /* MXCC control register */
            if (size == 4)
1910
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
B
blueswir1 已提交
1911
                    | val;
1912
            else
B
blueswir1 已提交
1913 1914
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1915 1916
            break;
        case 0x01c00e00: /* MXCC error register  */
1917
            // writing a 1 bit clears the error
1918
            if (size == 8)
B
blueswir1 已提交
1919
                env->mxccregs[6] &= ~val;
1920
            else
B
blueswir1 已提交
1921 1922
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1923 1924 1925
            break;
        case 0x01c00f00: /* MBus port address register */
            if (size == 8)
B
blueswir1 已提交
1926
                env->mxccregs[7] = val;
1927
            else
B
blueswir1 已提交
1928 1929
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                             size);
1930 1931
            break;
        default:
B
blueswir1 已提交
1932 1933
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
                         size);
1934 1935
            break;
        }
1936 1937
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
                     asi, size, addr, val);
1938 1939 1940
#ifdef DEBUG_MXCC
        dump_mxcc(env);
#endif
1941
        break;
1942
    case 3: /* MMU flush */
B
blueswir1 已提交
1943 1944
        {
            int mmulev;
B
bellard 已提交
1945

B
blueswir1 已提交
1946
            mmulev = (addr >> 8) & 15;
1947
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
B
blueswir1 已提交
1948 1949
            switch (mmulev) {
            case 0: // flush page
B
blueswir1 已提交
1950
                tlb_flush_page(env, addr & 0xfffff000);
B
blueswir1 已提交
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
                break;
            case 1: // flush segment (256k)
            case 2: // flush region (16M)
            case 3: // flush context (4G)
            case 4: // flush entire
                tlb_flush(env, 1);
                break;
            default:
                break;
            }
B
bellard 已提交
1961
#ifdef DEBUG_MMU
1962
            dump_mmu(stdout, fprintf, env);
B
bellard 已提交
1963
#endif
B
blueswir1 已提交
1964
        }
1965
        break;
1966
    case 4: /* write MMU regs */
B
blueswir1 已提交
1967
        {
B
blueswir1 已提交
1968
            int reg = (addr >> 8) & 0x1f;
B
blueswir1 已提交
1969
            uint32_t oldreg;
1970

B
blueswir1 已提交
1971
            oldreg = env->mmuregs[reg];
B
bellard 已提交
1972
            switch(reg) {
1973
            case 0: // Control Register
B
blueswir1 已提交
1974
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
B
blueswir1 已提交
1975
                                    (val & 0x00ffffff);
B
blueswir1 已提交
1976 1977
                // Mappings generated during no-fault mode or MMU
                // disabled mode are invalid in normal mode
1978 1979
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
B
bellard 已提交
1980 1981
                    tlb_flush(env, 1);
                break;
1982
            case 1: // Context Table Pointer Register
1983
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1984 1985
                break;
            case 2: // Context Register
1986
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
B
bellard 已提交
1987 1988 1989 1990 1991 1992
                if (oldreg != env->mmuregs[reg]) {
                    /* we flush when the MMU context changes because
                       QEMU has no MMU context support */
                    tlb_flush(env, 1);
                }
                break;
1993 1994 1995 1996
            case 3: // Synchronous Fault Status Register with Clear
            case 4: // Synchronous Fault Address Register
                break;
            case 0x10: // TLB Replacement Control Register
1997
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
B
bellard 已提交
1998
                break;
1999
            case 0x13: // Synchronous Fault Status Register with Read and Clear
2000
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
B
blueswir1 已提交
2001
                break;
2002
            case 0x14: // Synchronous Fault Address Register
B
blueswir1 已提交
2003
                env->mmuregs[4] = val;
B
blueswir1 已提交
2004
                break;
B
bellard 已提交
2005
            default:
B
blueswir1 已提交
2006
                env->mmuregs[reg] = val;
B
bellard 已提交
2007 2008 2009
                break;
            }
            if (oldreg != env->mmuregs[reg]) {
B
blueswir1 已提交
2010 2011
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
                            reg, oldreg, env->mmuregs[reg]);
B
bellard 已提交
2012
            }
2013
#ifdef DEBUG_MMU
2014
            dump_mmu(stdout, fprintf, env);
B
bellard 已提交
2015
#endif
B
blueswir1 已提交
2016
        }
2017
        break;
B
blueswir1 已提交
2018 2019 2020 2021
    case 5: // Turbosparc ITLB Diagnostic
    case 6: // Turbosparc DTLB Diagnostic
    case 7: // Turbosparc IOTLB Diagnostic
        break;
2022 2023 2024
    case 0xa: /* User data access */
        switch(size) {
        case 1:
B
blueswir1 已提交
2025
            stb_user(addr, val);
2026 2027
            break;
        case 2:
2028
            stw_user(addr, val);
2029 2030 2031
            break;
        default:
        case 4:
2032
            stl_user(addr, val);
2033 2034
            break;
        case 8:
2035
            stq_user(addr, val);
2036 2037 2038 2039 2040 2041
            break;
        }
        break;
    case 0xb: /* Supervisor data access */
        switch(size) {
        case 1:
B
blueswir1 已提交
2042
            stb_kernel(addr, val);
2043 2044
            break;
        case 2:
2045
            stw_kernel(addr, val);
2046 2047 2048
            break;
        default:
        case 4:
2049
            stl_kernel(addr, val);
2050 2051
            break;
        case 8:
2052
            stq_kernel(addr, val);
2053 2054 2055
            break;
        }
        break;
2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
    case 0xc: /* I-cache tag */
    case 0xd: /* I-cache data */
    case 0xe: /* D-cache tag */
    case 0xf: /* D-cache data */
    case 0x10: /* I/D-cache flush page */
    case 0x11: /* I/D-cache flush segment */
    case 0x12: /* I/D-cache flush region */
    case 0x13: /* I/D-cache flush context */
    case 0x14: /* I/D-cache flush user */
        break;
B
bellard 已提交
2066
    case 0x17: /* Block copy, sta access */
B
blueswir1 已提交
2067
        {
B
blueswir1 已提交
2068 2069
            // val = src
            // addr = dst
B
blueswir1 已提交
2070
            // copy 32 bytes
2071
            unsigned int i;
B
blueswir1 已提交
2072
            uint32_t src = val & ~3, dst = addr & ~3, temp;
2073

2074 2075 2076 2077
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
                temp = ldl_kernel(src);
                stl_kernel(dst, temp);
            }
B
blueswir1 已提交
2078
        }
2079
        break;
B
bellard 已提交
2080
    case 0x1f: /* Block fill, stda access */
B
blueswir1 已提交
2081
        {
B
blueswir1 已提交
2082 2083
            // addr = dst
            // fill 32 bytes with val
2084
            unsigned int i;
B
blueswir1 已提交
2085
            uint32_t dst = addr & 7;
2086 2087 2088

            for (i = 0; i < 32; i += 8, dst += 8)
                stq_kernel(dst, val);
B
blueswir1 已提交
2089
        }
2090
        break;
2091
    case 0x20: /* MMU passthrough */
B
blueswir1 已提交
2092
        {
B
bellard 已提交
2093 2094
            switch(size) {
            case 1:
B
blueswir1 已提交
2095
                stb_phys(addr, val);
B
bellard 已提交
2096 2097
                break;
            case 2:
2098
                stw_phys(addr, val);
B
bellard 已提交
2099 2100 2101
                break;
            case 4:
            default:
2102
                stl_phys(addr, val);
B
bellard 已提交
2103
                break;
B
bellard 已提交
2104
            case 8:
2105
                stq_phys(addr, val);
B
bellard 已提交
2106
                break;
B
bellard 已提交
2107
            }
B
blueswir1 已提交
2108
        }
2109
        break;
B
blueswir1 已提交
2110
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
B
blueswir1 已提交
2111
        {
2112 2113
            switch(size) {
            case 1:
A
Anthony Liguori 已提交
2114 2115
                stb_phys((target_phys_addr_t)addr
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2116 2117
                break;
            case 2:
A
Anthony Liguori 已提交
2118 2119
                stw_phys((target_phys_addr_t)addr
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2120 2121 2122
                break;
            case 4:
            default:
A
Anthony Liguori 已提交
2123 2124
                stl_phys((target_phys_addr_t)addr
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2125 2126
                break;
            case 8:
A
Anthony Liguori 已提交
2127 2128
                stq_phys((target_phys_addr_t)addr
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2129 2130
                break;
            }
B
blueswir1 已提交
2131
        }
2132
        break;
B
blueswir1 已提交
2133 2134 2135
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
               // Turbosparc snoop RAM
B
blueswir1 已提交
2136 2137
    case 0x32: // store buffer control or Turbosparc page table
               // descriptor diagnostic
2138 2139
    case 0x36: /* I-cache flash clear */
    case 0x37: /* D-cache flash clear */
B
blueswir1 已提交
2140
    case 0x4c: /* breakpoint action */
2141
        break;
2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
        {
            int reg = (addr >> 8) & 3;

            switch(reg) {
            case 0: /* Breakpoint Value (Addr) */
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
                break;
            case 1: /* Breakpoint Mask */
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
                break;
            case 2: /* Breakpoint Control */
                env->mmubpregs[reg] = (val & 0x7fULL);
                break;
            case 3: /* Breakpoint Status */
                env->mmubpregs[reg] = (val & 0xfULL);
                break;
            }
2160
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
2161 2162 2163
                        env->mmuregs[reg]);
        }
        break;
B
blueswir1 已提交
2164
    case 8: /* User code access, XXX */
2165
    case 9: /* Supervisor code access, XXX */
2166
    default:
2167
        do_unassigned_access(addr, 1, 0, asi, size);
2168
        break;
2169
    }
2170
#ifdef DEBUG_ASI
B
blueswir1 已提交
2171
    dump_asi("write", addr, asi, size, val);
2172
#endif
2173 2174
}

2175 2176 2177 2178
#endif /* CONFIG_USER_ONLY */
#else /* TARGET_SPARC64 */

#ifdef CONFIG_USER_ONLY
B
blueswir1 已提交
2179
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2180 2181
{
    uint64_t ret = 0;
B
blueswir1 已提交
2182 2183 2184
#if defined(DEBUG_ASI)
    target_ulong last_addr = addr;
#endif
2185 2186 2187 2188

    if (asi < 0x80)
        raise_exception(TT_PRIV_ACT);

2189
    helper_check_align(addr, size - 1);
2190
    addr = asi_address_mask(env, asi, addr);
2191

2192 2193 2194
    switch (asi) {
    case 0x82: // Primary no-fault
    case 0x8a: // Primary no-fault LE
B
blueswir1 已提交
2195 2196 2197 2198 2199 2200 2201 2202 2203
        if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
            dump_asi("read ", last_addr, asi, size, ret);
#endif
            return 0;
        }
        // Fall through
    case 0x80: // Primary
    case 0x88: // Primary LE
2204 2205 2206
        {
            switch(size) {
            case 1:
B
blueswir1 已提交
2207
                ret = ldub_raw(addr);
2208 2209
                break;
            case 2:
2210
                ret = lduw_raw(addr);
2211 2212
                break;
            case 4:
2213
                ret = ldl_raw(addr);
2214 2215 2216
                break;
            default:
            case 8:
2217
                ret = ldq_raw(addr);
2218 2219 2220 2221 2222 2223
                break;
            }
        }
        break;
    case 0x83: // Secondary no-fault
    case 0x8b: // Secondary no-fault LE
B
blueswir1 已提交
2224 2225 2226 2227 2228 2229 2230 2231 2232
        if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
            dump_asi("read ", last_addr, asi, size, ret);
#endif
            return 0;
        }
        // Fall through
    case 0x81: // Secondary
    case 0x89: // Secondary LE
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247
        // XXX
        break;
    default:
        break;
    }

    /* Convert from little endian */
    switch (asi) {
    case 0x88: // Primary LE
    case 0x89: // Secondary LE
    case 0x8a: // Primary no-fault LE
    case 0x8b: // Secondary no-fault LE
        switch(size) {
        case 2:
            ret = bswap16(ret);
B
blueswir1 已提交
2248
            break;
2249 2250
        case 4:
            ret = bswap32(ret);
B
blueswir1 已提交
2251
            break;
2252 2253
        case 8:
            ret = bswap64(ret);
B
blueswir1 已提交
2254
            break;
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266
        default:
            break;
        }
    default:
        break;
    }

    /* Convert to signed number */
    if (sign) {
        switch(size) {
        case 1:
            ret = (int8_t) ret;
B
blueswir1 已提交
2267
            break;
2268 2269
        case 2:
            ret = (int16_t) ret;
B
blueswir1 已提交
2270
            break;
2271 2272
        case 4:
            ret = (int32_t) ret;
B
blueswir1 已提交
2273
            break;
2274 2275 2276 2277
        default:
            break;
        }
    }
B
blueswir1 已提交
2278 2279 2280 2281
#ifdef DEBUG_ASI
    dump_asi("read ", last_addr, asi, size, ret);
#endif
    return ret;
2282 2283
}

B
blueswir1 已提交
2284
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2285
{
B
blueswir1 已提交
2286 2287 2288
#ifdef DEBUG_ASI
    dump_asi("write", addr, asi, size, val);
#endif
2289 2290 2291
    if (asi < 0x80)
        raise_exception(TT_PRIV_ACT);

2292
    helper_check_align(addr, size - 1);
2293
    addr = asi_address_mask(env, asi, addr);
2294

2295 2296 2297 2298 2299 2300
    /* Convert to little endian */
    switch (asi) {
    case 0x88: // Primary LE
    case 0x89: // Secondary LE
        switch(size) {
        case 2:
2301
            val = bswap16(val);
B
blueswir1 已提交
2302
            break;
2303
        case 4:
2304
            val = bswap32(val);
B
blueswir1 已提交
2305
            break;
2306
        case 8:
2307
            val = bswap64(val);
B
blueswir1 已提交
2308
            break;
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321
        default:
            break;
        }
    default:
        break;
    }

    switch(asi) {
    case 0x80: // Primary
    case 0x88: // Primary LE
        {
            switch(size) {
            case 1:
B
blueswir1 已提交
2322
                stb_raw(addr, val);
2323 2324
                break;
            case 2:
2325
                stw_raw(addr, val);
2326 2327
                break;
            case 4:
2328
                stl_raw(addr, val);
2329 2330 2331
                break;
            case 8:
            default:
2332
                stq_raw(addr, val);
2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346
                break;
            }
        }
        break;
    case 0x81: // Secondary
    case 0x89: // Secondary LE
        // XXX
        return;

    case 0x82: // Primary no-fault, RO
    case 0x83: // Secondary no-fault, RO
    case 0x8a: // Primary no-fault LE, RO
    case 0x8b: // Secondary no-fault LE, RO
    default:
2347
        do_unassigned_access(addr, 1, 0, 1, size);
2348 2349 2350 2351 2352
        return;
    }
}

#else /* CONFIG_USER_ONLY */
B
bellard 已提交
2353

B
blueswir1 已提交
2354
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
B
bellard 已提交
2355
{
B
bellard 已提交
2356
    uint64_t ret = 0;
B
blueswir1 已提交
2357 2358 2359
#if defined(DEBUG_ASI)
    target_ulong last_addr = addr;
#endif
B
bellard 已提交
2360

I
Igor V. Kovalenko 已提交
2361 2362
    asi &= 0xff;

B
blueswir1 已提交
2363
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2364
        || (cpu_has_hypervisor(env)
2365
            && asi >= 0x30 && asi < 0x80
2366
            && !(env->hpstate & HS_PRIV)))
B
blueswir1 已提交
2367
        raise_exception(TT_PRIV_ACT);
B
bellard 已提交
2368

2369
    helper_check_align(addr, size - 1);
2370 2371
    addr = asi_address_mask(env, asi, addr);

B
bellard 已提交
2372
    switch (asi) {
B
blueswir1 已提交
2373 2374
    case 0x82: // Primary no-fault
    case 0x8a: // Primary no-fault LE
2375 2376 2377 2378 2379 2380 2381 2382
    case 0x83: // Secondary no-fault
    case 0x8b: // Secondary no-fault LE
        {
            /* secondary space access has lowest asi bit equal to 1 */
            int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
                                             : MMU_KERNEL_SECONDARY_IDX;

            if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
B
blueswir1 已提交
2383
#ifdef DEBUG_ASI
2384
                dump_asi("read ", last_addr, asi, size, ret);
B
blueswir1 已提交
2385
#endif
2386 2387
                return 0;
            }
B
blueswir1 已提交
2388 2389
        }
        // Fall through
2390
    case 0x10: // As if user primary
2391
    case 0x11: // As if user secondary
2392
    case 0x18: // As if user primary LE
2393
    case 0x19: // As if user secondary LE
2394
    case 0x80: // Primary
2395
    case 0x81: // Secondary
2396
    case 0x88: // Primary LE
2397
    case 0x89: // Secondary LE
B
blueswir1 已提交
2398 2399
    case 0xe2: // UA2007 Primary block init
    case 0xe3: // UA2007 Secondary block init
2400
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2401
            if (cpu_hypervisor_mode(env)) {
B
blueswir1 已提交
2402 2403
                switch(size) {
                case 1:
B
blueswir1 已提交
2404
                    ret = ldub_hypv(addr);
B
blueswir1 已提交
2405 2406
                    break;
                case 2:
2407
                    ret = lduw_hypv(addr);
B
blueswir1 已提交
2408 2409
                    break;
                case 4:
2410
                    ret = ldl_hypv(addr);
B
blueswir1 已提交
2411 2412 2413
                    break;
                default:
                case 8:
2414
                    ret = ldq_hypv(addr);
B
blueswir1 已提交
2415 2416 2417
                    break;
                }
            } else {
2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455
                /* secondary space access has lowest asi bit equal to 1 */
                if (asi & 1) {
                    switch(size) {
                    case 1:
                        ret = ldub_kernel_secondary(addr);
                        break;
                    case 2:
                        ret = lduw_kernel_secondary(addr);
                        break;
                    case 4:
                        ret = ldl_kernel_secondary(addr);
                        break;
                    default:
                    case 8:
                        ret = ldq_kernel_secondary(addr);
                        break;
                    }
                } else {
                    switch(size) {
                    case 1:
                        ret = ldub_kernel(addr);
                        break;
                    case 2:
                        ret = lduw_kernel(addr);
                        break;
                    case 4:
                        ret = ldl_kernel(addr);
                        break;
                    default:
                    case 8:
                        ret = ldq_kernel(addr);
                        break;
                    }
                }
            }
        } else {
            /* secondary space access has lowest asi bit equal to 1 */
            if (asi & 1) {
B
blueswir1 已提交
2456 2457
                switch(size) {
                case 1:
2458
                    ret = ldub_user_secondary(addr);
B
blueswir1 已提交
2459 2460
                    break;
                case 2:
2461
                    ret = lduw_user_secondary(addr);
B
blueswir1 已提交
2462 2463
                    break;
                case 4:
2464
                    ret = ldl_user_secondary(addr);
B
blueswir1 已提交
2465 2466 2467
                    break;
                default:
                case 8:
2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
                    ret = ldq_user_secondary(addr);
                    break;
                }
            } else {
                switch(size) {
                case 1:
                    ret = ldub_user(addr);
                    break;
                case 2:
                    ret = lduw_user(addr);
                    break;
                case 4:
                    ret = ldl_user(addr);
                    break;
                default:
                case 8:
                    ret = ldq_user(addr);
B
blueswir1 已提交
2485 2486
                    break;
                }
2487 2488 2489
            }
        }
        break;
B
bellard 已提交
2490 2491
    case 0x14: // Bypass
    case 0x15: // Bypass, non-cacheable
2492 2493
    case 0x1c: // Bypass LE
    case 0x1d: // Bypass, non-cacheable LE
B
blueswir1 已提交
2494
        {
B
bellard 已提交
2495 2496
            switch(size) {
            case 1:
B
blueswir1 已提交
2497
                ret = ldub_phys(addr);
B
bellard 已提交
2498 2499
                break;
            case 2:
2500
                ret = lduw_phys(addr);
B
bellard 已提交
2501 2502
                break;
            case 4:
2503
                ret = ldl_phys(addr);
B
bellard 已提交
2504 2505 2506
                break;
            default:
            case 8:
2507
                ret = ldq_phys(addr);
B
bellard 已提交
2508 2509
                break;
            }
B
blueswir1 已提交
2510 2511
            break;
        }
B
blueswir1 已提交
2512 2513 2514 2515 2516
    case 0x24: // Nucleus quad LDD 128 bit atomic
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        //  Only ldda allowed
        raise_exception(TT_ILL_INSN);
        return 0;
B
bellard 已提交
2517 2518
    case 0x04: // Nucleus
    case 0x0c: // Nucleus Little Endian (LE)
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536
    {
        switch(size) {
        case 1:
            ret = ldub_nucleus(addr);
            break;
        case 2:
            ret = lduw_nucleus(addr);
            break;
        case 4:
            ret = ldl_nucleus(addr);
            break;
        default:
        case 8:
            ret = ldq_nucleus(addr);
            break;
        }
        break;
    }
B
bellard 已提交
2537
    case 0x4a: // UPA config
B
blueswir1 已提交
2538 2539
        // XXX
        break;
B
bellard 已提交
2540
    case 0x45: // LSU
B
blueswir1 已提交
2541 2542
        ret = env->lsu;
        break;
B
bellard 已提交
2543
    case 0x50: // I-MMU regs
B
blueswir1 已提交
2544
        {
B
blueswir1 已提交
2545
            int reg = (addr >> 3) & 0xf;
B
bellard 已提交
2546

2547 2548
            if (reg == 0) {
                // I-TSB Tag Target register
2549
                ret = ultrasparc_tag_target(env->immu.tag_access);
2550 2551 2552 2553
            } else {
                ret = env->immuregs[reg];
            }

B
blueswir1 已提交
2554 2555
            break;
        }
B
bellard 已提交
2556
    case 0x51: // I-MMU 8k TSB pointer
2557 2558 2559
        {
            // env->immuregs[5] holds I-MMU TSB register value
            // env->immuregs[6] holds I-MMU Tag Access register value
2560
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2561 2562 2563
                                         8*1024);
            break;
        }
B
bellard 已提交
2564
    case 0x52: // I-MMU 64k TSB pointer
2565 2566 2567
        {
            // env->immuregs[5] holds I-MMU TSB register value
            // env->immuregs[6] holds I-MMU Tag Access register value
2568
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2569 2570 2571
                                         64*1024);
            break;
        }
2572 2573 2574 2575
    case 0x55: // I-MMU data access
        {
            int reg = (addr >> 3) & 0x3f;

2576
            ret = env->itlb[reg].tte;
2577 2578
            break;
        }
B
bellard 已提交
2579
    case 0x56: // I-MMU tag read
B
blueswir1 已提交
2580
        {
B
blueswir1 已提交
2581
            int reg = (addr >> 3) & 0x3f;
B
blueswir1 已提交
2582

2583
            ret = env->itlb[reg].tag;
B
blueswir1 已提交
2584 2585
            break;
        }
B
bellard 已提交
2586
    case 0x58: // D-MMU regs
B
blueswir1 已提交
2587
        {
B
blueswir1 已提交
2588
            int reg = (addr >> 3) & 0xf;
B
bellard 已提交
2589

2590 2591
            if (reg == 0) {
                // D-TSB Tag Target register
2592
                ret = ultrasparc_tag_target(env->dmmu.tag_access);
2593 2594 2595 2596 2597 2598 2599 2600 2601
            } else {
                ret = env->dmmuregs[reg];
            }
            break;
        }
    case 0x59: // D-MMU 8k TSB pointer
        {
            // env->dmmuregs[5] holds D-MMU TSB register value
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2602
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2603 2604 2605 2606 2607 2608 2609
                                         8*1024);
            break;
        }
    case 0x5a: // D-MMU 64k TSB pointer
        {
            // env->dmmuregs[5] holds D-MMU TSB register value
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2610
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2611
                                         64*1024);
B
blueswir1 已提交
2612 2613
            break;
        }
2614 2615 2616 2617
    case 0x5d: // D-MMU data access
        {
            int reg = (addr >> 3) & 0x3f;

2618
            ret = env->dtlb[reg].tte;
2619 2620
            break;
        }
B
bellard 已提交
2621
    case 0x5e: // D-MMU tag read
B
blueswir1 已提交
2622
        {
B
blueswir1 已提交
2623
            int reg = (addr >> 3) & 0x3f;
B
blueswir1 已提交
2624

2625
            ret = env->dtlb[reg].tag;
B
blueswir1 已提交
2626 2627
            break;
        }
2628 2629
    case 0x46: // D-cache data
    case 0x47: // D-cache tag access
2630 2631 2632
    case 0x4b: // E-cache error enable
    case 0x4c: // E-cache asynchronous fault status
    case 0x4d: // E-cache asynchronous fault address
2633 2634 2635 2636 2637 2638 2639 2640
    case 0x4e: // E-cache tag data
    case 0x66: // I-cache instruction access
    case 0x67: // I-cache tag access
    case 0x6e: // I-cache predecode
    case 0x6f: // I-cache LRU etc.
    case 0x76: // E-cache tag
    case 0x7e: // E-cache tag
        break;
B
bellard 已提交
2641
    case 0x5b: // D-MMU data pointer
B
bellard 已提交
2642 2643 2644
    case 0x48: // Interrupt dispatch, RO
    case 0x49: // Interrupt data receive
    case 0x7f: // Incoming interrupt vector, RO
B
blueswir1 已提交
2645 2646
        // XXX
        break;
B
bellard 已提交
2647 2648 2649 2650
    case 0x54: // I-MMU data in, WO
    case 0x57: // I-MMU demap, WO
    case 0x5c: // D-MMU data in, WO
    case 0x5f: // D-MMU demap, WO
B
bellard 已提交
2651
    case 0x77: // Interrupt vector, WO
B
bellard 已提交
2652
    default:
2653
        do_unassigned_access(addr, 0, 0, 1, size);
B
blueswir1 已提交
2654 2655
        ret = 0;
        break;
B
bellard 已提交
2656
    }
2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671

    /* Convert from little endian */
    switch (asi) {
    case 0x0c: // Nucleus Little Endian (LE)
    case 0x18: // As if user primary LE
    case 0x19: // As if user secondary LE
    case 0x1c: // Bypass LE
    case 0x1d: // Bypass, non-cacheable LE
    case 0x88: // Primary LE
    case 0x89: // Secondary LE
    case 0x8a: // Primary no-fault LE
    case 0x8b: // Secondary no-fault LE
        switch(size) {
        case 2:
            ret = bswap16(ret);
B
blueswir1 已提交
2672
            break;
2673 2674
        case 4:
            ret = bswap32(ret);
B
blueswir1 已提交
2675
            break;
2676 2677
        case 8:
            ret = bswap64(ret);
B
blueswir1 已提交
2678
            break;
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690
        default:
            break;
        }
    default:
        break;
    }

    /* Convert to signed number */
    if (sign) {
        switch(size) {
        case 1:
            ret = (int8_t) ret;
B
blueswir1 已提交
2691
            break;
2692 2693
        case 2:
            ret = (int16_t) ret;
B
blueswir1 已提交
2694
            break;
2695 2696
        case 4:
            ret = (int32_t) ret;
B
blueswir1 已提交
2697
            break;
2698 2699 2700 2701
        default:
            break;
        }
    }
B
blueswir1 已提交
2702 2703 2704 2705
#ifdef DEBUG_ASI
    dump_asi("read ", last_addr, asi, size, ret);
#endif
    return ret;
B
bellard 已提交
2706 2707
}

B
blueswir1 已提交
2708
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
B
bellard 已提交
2709
{
B
blueswir1 已提交
2710 2711 2712
#ifdef DEBUG_ASI
    dump_asi("write", addr, asi, size, val);
#endif
I
Igor V. Kovalenko 已提交
2713 2714 2715

    asi &= 0xff;

B
blueswir1 已提交
2716
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2717
        || (cpu_has_hypervisor(env)
2718
            && asi >= 0x30 && asi < 0x80
2719
            && !(env->hpstate & HS_PRIV)))
B
blueswir1 已提交
2720
        raise_exception(TT_PRIV_ACT);
B
bellard 已提交
2721

2722
    helper_check_align(addr, size - 1);
2723 2724
    addr = asi_address_mask(env, asi, addr);

2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735
    /* Convert to little endian */
    switch (asi) {
    case 0x0c: // Nucleus Little Endian (LE)
    case 0x18: // As if user primary LE
    case 0x19: // As if user secondary LE
    case 0x1c: // Bypass LE
    case 0x1d: // Bypass, non-cacheable LE
    case 0x88: // Primary LE
    case 0x89: // Secondary LE
        switch(size) {
        case 2:
2736
            val = bswap16(val);
B
blueswir1 已提交
2737
            break;
2738
        case 4:
2739
            val = bswap32(val);
B
blueswir1 已提交
2740
            break;
2741
        case 8:
2742
            val = bswap64(val);
B
blueswir1 已提交
2743
            break;
2744 2745 2746 2747 2748 2749 2750
        default:
            break;
        }
    default:
        break;
    }

B
bellard 已提交
2751
    switch(asi) {
2752
    case 0x10: // As if user primary
2753
    case 0x11: // As if user secondary
2754
    case 0x18: // As if user primary LE
2755
    case 0x19: // As if user secondary LE
2756
    case 0x80: // Primary
2757
    case 0x81: // Secondary
2758
    case 0x88: // Primary LE
2759
    case 0x89: // Secondary LE
B
blueswir1 已提交
2760 2761
    case 0xe2: // UA2007 Primary block init
    case 0xe3: // UA2007 Secondary block init
2762
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2763
            if (cpu_hypervisor_mode(env)) {
B
blueswir1 已提交
2764 2765
                switch(size) {
                case 1:
B
blueswir1 已提交
2766
                    stb_hypv(addr, val);
B
blueswir1 已提交
2767 2768
                    break;
                case 2:
2769
                    stw_hypv(addr, val);
B
blueswir1 已提交
2770 2771
                    break;
                case 4:
2772
                    stl_hypv(addr, val);
B
blueswir1 已提交
2773 2774 2775
                    break;
                case 8:
                default:
2776
                    stq_hypv(addr, val);
B
blueswir1 已提交
2777 2778 2779
                    break;
                }
            } else {
2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817
                /* secondary space access has lowest asi bit equal to 1 */
                if (asi & 1) {
                    switch(size) {
                    case 1:
                        stb_kernel_secondary(addr, val);
                        break;
                    case 2:
                        stw_kernel_secondary(addr, val);
                        break;
                    case 4:
                        stl_kernel_secondary(addr, val);
                        break;
                    case 8:
                    default:
                        stq_kernel_secondary(addr, val);
                        break;
                    }
                } else {
                    switch(size) {
                    case 1:
                        stb_kernel(addr, val);
                        break;
                    case 2:
                        stw_kernel(addr, val);
                        break;
                    case 4:
                        stl_kernel(addr, val);
                        break;
                    case 8:
                    default:
                        stq_kernel(addr, val);
                        break;
                    }
                }
            }
        } else {
            /* secondary space access has lowest asi bit equal to 1 */
            if (asi & 1) {
B
blueswir1 已提交
2818 2819
                switch(size) {
                case 1:
2820
                    stb_user_secondary(addr, val);
B
blueswir1 已提交
2821 2822
                    break;
                case 2:
2823
                    stw_user_secondary(addr, val);
B
blueswir1 已提交
2824 2825
                    break;
                case 4:
2826
                    stl_user_secondary(addr, val);
B
blueswir1 已提交
2827 2828 2829
                    break;
                case 8:
                default:
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
                    stq_user_secondary(addr, val);
                    break;
                }
            } else {
                switch(size) {
                case 1:
                    stb_user(addr, val);
                    break;
                case 2:
                    stw_user(addr, val);
                    break;
                case 4:
                    stl_user(addr, val);
                    break;
                case 8:
                default:
                    stq_user(addr, val);
B
blueswir1 已提交
2847 2848
                    break;
                }
2849 2850 2851
            }
        }
        break;
B
bellard 已提交
2852 2853
    case 0x14: // Bypass
    case 0x15: // Bypass, non-cacheable
2854 2855
    case 0x1c: // Bypass LE
    case 0x1d: // Bypass, non-cacheable LE
B
blueswir1 已提交
2856
        {
B
bellard 已提交
2857 2858
            switch(size) {
            case 1:
B
blueswir1 已提交
2859
                stb_phys(addr, val);
B
bellard 已提交
2860 2861
                break;
            case 2:
2862
                stw_phys(addr, val);
B
bellard 已提交
2863 2864
                break;
            case 4:
2865
                stl_phys(addr, val);
B
bellard 已提交
2866 2867 2868
                break;
            case 8:
            default:
2869
                stq_phys(addr, val);
B
bellard 已提交
2870 2871
                break;
            }
B
blueswir1 已提交
2872 2873
        }
        return;
B
blueswir1 已提交
2874 2875 2876 2877 2878
    case 0x24: // Nucleus quad LDD 128 bit atomic
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        //  Only ldda allowed
        raise_exception(TT_ILL_INSN);
        return;
B
bellard 已提交
2879 2880
    case 0x04: // Nucleus
    case 0x0c: // Nucleus Little Endian (LE)
2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899
    {
        switch(size) {
        case 1:
            stb_nucleus(addr, val);
            break;
        case 2:
            stw_nucleus(addr, val);
            break;
        case 4:
            stl_nucleus(addr, val);
            break;
        default:
        case 8:
            stq_nucleus(addr, val);
            break;
        }
        break;
    }

B
bellard 已提交
2900
    case 0x4a: // UPA config
B
blueswir1 已提交
2901 2902
        // XXX
        return;
B
bellard 已提交
2903
    case 0x45: // LSU
B
blueswir1 已提交
2904 2905 2906 2907
        {
            uint64_t oldreg;

            oldreg = env->lsu;
B
blueswir1 已提交
2908
            env->lsu = val & (DMMU_E | IMMU_E);
B
blueswir1 已提交
2909 2910 2911
            // Mappings generated during D/I MMU disabled mode are
            // invalid in normal mode
            if (oldreg != env->lsu) {
B
blueswir1 已提交
2912 2913
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
                            oldreg, env->lsu);
B
bellard 已提交
2914
#ifdef DEBUG_MMU
2915
                dump_mmu(stdout, fprintf, env1);
B
bellard 已提交
2916
#endif
B
blueswir1 已提交
2917 2918 2919 2920
                tlb_flush(env, 1);
            }
            return;
        }
B
bellard 已提交
2921
    case 0x50: // I-MMU regs
B
blueswir1 已提交
2922
        {
B
blueswir1 已提交
2923
            int reg = (addr >> 3) & 0xf;
B
blueswir1 已提交
2924
            uint64_t oldreg;
2925

B
blueswir1 已提交
2926
            oldreg = env->immuregs[reg];
B
bellard 已提交
2927 2928 2929 2930 2931 2932 2933
            switch(reg) {
            case 0: // RO
                return;
            case 1: // Not in I-MMU
            case 2:
                return;
            case 3: // SFSR
B
blueswir1 已提交
2934 2935
                if ((val & 1) == 0)
                    val = 0; // Clear SFSR
2936
                env->immu.sfsr = val;
B
bellard 已提交
2937
                break;
2938 2939
            case 4: // RO
                return;
B
bellard 已提交
2940
            case 5: // TSB access
2941 2942 2943 2944
                DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
                            PRIx64 "\n", env->immu.tsb, val);
                env->immu.tsb = val;
                break;
B
bellard 已提交
2945
            case 6: // Tag access
2946 2947 2948 2949 2950
                env->immu.tag_access = val;
                break;
            case 7:
            case 8:
                return;
B
bellard 已提交
2951 2952 2953
            default:
                break;
            }
2954

B
bellard 已提交
2955
            if (oldreg != env->immuregs[reg]) {
2956
                DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
B
blueswir1 已提交
2957
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
B
bellard 已提交
2958
            }
2959
#ifdef DEBUG_MMU
2960
            dump_mmu(stdout, fprintf, env);
B
bellard 已提交
2961
#endif
B
blueswir1 已提交
2962 2963
            return;
        }
B
bellard 已提交
2964
    case 0x54: // I-MMU data in
2965 2966
        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
        return;
B
bellard 已提交
2967
    case 0x55: // I-MMU data access
B
blueswir1 已提交
2968
        {
2969 2970
            // TODO: auto demap

B
blueswir1 已提交
2971
            unsigned int i = (addr >> 3) & 0x3f;
B
bellard 已提交
2972

2973
            replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
2974 2975

#ifdef DEBUG_MMU
2976
            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2977
            dump_mmu(stdout, fprintf, env);
2978
#endif
B
blueswir1 已提交
2979 2980
            return;
        }
B
bellard 已提交
2981
    case 0x57: // I-MMU demap
2982
        demap_tlb(env->itlb, addr, "immu", env);
B
blueswir1 已提交
2983
        return;
B
bellard 已提交
2984
    case 0x58: // D-MMU regs
B
blueswir1 已提交
2985
        {
B
blueswir1 已提交
2986
            int reg = (addr >> 3) & 0xf;
B
blueswir1 已提交
2987
            uint64_t oldreg;
2988

B
blueswir1 已提交
2989
            oldreg = env->dmmuregs[reg];
B
bellard 已提交
2990 2991 2992 2993 2994
            switch(reg) {
            case 0: // RO
            case 4:
                return;
            case 3: // SFSR
B
blueswir1 已提交
2995 2996
                if ((val & 1) == 0) {
                    val = 0; // Clear SFSR, Fault address
2997
                    env->dmmu.sfar = 0;
B
blueswir1 已提交
2998
                }
2999
                env->dmmu.sfsr = val;
B
bellard 已提交
3000 3001
                break;
            case 1: // Primary context
3002
                env->dmmu.mmu_primary_context = val;
3003 3004 3005
                /* can be optimized to only flush MMU_USER_IDX
                   and MMU_KERNEL_IDX entries */
                tlb_flush(env, 1);
3006
                break;
B
bellard 已提交
3007
            case 2: // Secondary context
3008
                env->dmmu.mmu_secondary_context = val;
3009 3010 3011
                /* can be optimized to only flush MMU_USER_SECONDARY_IDX
                   and MMU_KERNEL_SECONDARY_IDX entries */
                tlb_flush(env, 1);
3012
                break;
B
bellard 已提交
3013
            case 5: // TSB access
3014 3015 3016 3017
                DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
                            PRIx64 "\n", env->dmmu.tsb, val);
                env->dmmu.tsb = val;
                break;
B
bellard 已提交
3018
            case 6: // Tag access
3019 3020
                env->dmmu.tag_access = val;
                break;
B
bellard 已提交
3021 3022 3023
            case 7: // Virtual Watchpoint
            case 8: // Physical Watchpoint
            default:
3024
                env->dmmuregs[reg] = val;
B
bellard 已提交
3025 3026
                break;
            }
3027

B
bellard 已提交
3028
            if (oldreg != env->dmmuregs[reg]) {
3029
                DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
B
blueswir1 已提交
3030
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
B
bellard 已提交
3031
            }
3032
#ifdef DEBUG_MMU
3033
            dump_mmu(stdout, fprintf, env);
B
bellard 已提交
3034
#endif
B
blueswir1 已提交
3035 3036
            return;
        }
B
bellard 已提交
3037
    case 0x5c: // D-MMU data in
3038 3039
        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
        return;
B
bellard 已提交
3040
    case 0x5d: // D-MMU data access
B
blueswir1 已提交
3041
        {
B
blueswir1 已提交
3042
            unsigned int i = (addr >> 3) & 0x3f;
B
bellard 已提交
3043

3044 3045
            replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);

3046
#ifdef DEBUG_MMU
3047
            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
3048
            dump_mmu(stdout, fprintf, env);
3049
#endif
B
blueswir1 已提交
3050 3051
            return;
        }
B
bellard 已提交
3052
    case 0x5f: // D-MMU demap
3053
        demap_tlb(env->dtlb, addr, "dmmu", env);
3054
        return;
B
bellard 已提交
3055
    case 0x49: // Interrupt data receive
B
blueswir1 已提交
3056 3057
        // XXX
        return;
3058 3059
    case 0x46: // D-cache data
    case 0x47: // D-cache tag access
3060 3061 3062
    case 0x4b: // E-cache error enable
    case 0x4c: // E-cache asynchronous fault status
    case 0x4d: // E-cache asynchronous fault address
3063 3064 3065 3066 3067 3068 3069 3070
    case 0x4e: // E-cache tag data
    case 0x66: // I-cache instruction access
    case 0x67: // I-cache tag access
    case 0x6e: // I-cache predecode
    case 0x6f: // I-cache LRU etc.
    case 0x76: // E-cache tag
    case 0x7e: // E-cache tag
        return;
B
bellard 已提交
3071 3072 3073 3074 3075 3076 3077
    case 0x51: // I-MMU 8k TSB pointer, RO
    case 0x52: // I-MMU 64k TSB pointer, RO
    case 0x56: // I-MMU tag read, RO
    case 0x59: // D-MMU 8k TSB pointer, RO
    case 0x5a: // D-MMU 64k TSB pointer, RO
    case 0x5b: // D-MMU data pointer, RO
    case 0x5e: // D-MMU tag read, RO
B
bellard 已提交
3078 3079 3080 3081 3082 3083
    case 0x48: // Interrupt dispatch, RO
    case 0x7f: // Incoming interrupt vector, RO
    case 0x82: // Primary no-fault, RO
    case 0x83: // Secondary no-fault, RO
    case 0x8a: // Primary no-fault LE, RO
    case 0x8b: // Secondary no-fault LE, RO
B
bellard 已提交
3084
    default:
3085
        do_unassigned_access(addr, 1, 0, 1, size);
B
blueswir1 已提交
3086
        return;
B
bellard 已提交
3087 3088
    }
}
3089
#endif /* CONFIG_USER_ONLY */
3090

B
blueswir1 已提交
3091 3092 3093
void helper_ldda_asi(target_ulong addr, int asi, int rd)
{
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
3094
        || (cpu_has_hypervisor(env)
3095
            && asi >= 0x30 && asi < 0x80
3096
            && !(env->hpstate & HS_PRIV)))
B
blueswir1 已提交
3097 3098
        raise_exception(TT_PRIV_ACT);

3099 3100
    addr = asi_address_mask(env, asi, addr);

B
blueswir1 已提交
3101
    switch (asi) {
B
Blue Swirl 已提交
3102
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
3103 3104 3105 3106
    case 0x24: // Nucleus quad LDD 128 bit atomic
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        helper_check_align(addr, 0xf);
        if (rd == 0) {
3107
            env->gregs[1] = ldq_nucleus(addr + 8);
B
blueswir1 已提交
3108 3109 3110
            if (asi == 0x2c)
                bswap64s(&env->gregs[1]);
        } else if (rd < 8) {
3111 3112
            env->gregs[rd] = ldq_nucleus(addr);
            env->gregs[rd + 1] = ldq_nucleus(addr + 8);
B
blueswir1 已提交
3113 3114 3115 3116 3117
            if (asi == 0x2c) {
                bswap64s(&env->gregs[rd]);
                bswap64s(&env->gregs[rd + 1]);
            }
        } else {
3118 3119
            env->regwptr[rd] = ldq_nucleus(addr);
            env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
B
blueswir1 已提交
3120 3121 3122 3123 3124 3125
            if (asi == 0x2c) {
                bswap64s(&env->regwptr[rd]);
                bswap64s(&env->regwptr[rd + 1]);
            }
        }
        break;
B
Blue Swirl 已提交
3126
#endif
B
blueswir1 已提交
3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141
    default:
        helper_check_align(addr, 0x3);
        if (rd == 0)
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
        else if (rd < 8) {
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
        } else {
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
        }
        break;
    }
}

B
blueswir1 已提交
3142
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
3143 3144
{
    unsigned int i;
B
blueswir1 已提交
3145
    target_ulong val;
3146

3147
    helper_check_align(addr, 3);
3148 3149
    addr = asi_address_mask(env, asi, addr);

3150 3151 3152 3153 3154
    switch (asi) {
    case 0xf0: // Block load primary
    case 0xf1: // Block load secondary
    case 0xf8: // Block load primary LE
    case 0xf9: // Block load secondary LE
B
blueswir1 已提交
3155 3156 3157 3158
        if (rd & 7) {
            raise_exception(TT_ILL_INSN);
            return;
        }
3159
        helper_check_align(addr, 0x3f);
B
blueswir1 已提交
3160
        for (i = 0; i < 16; i++) {
B
blueswir1 已提交
3161 3162
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
                                                         0);
B
blueswir1 已提交
3163
            addr += 4;
3164 3165
        }

3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
        return;
    case 0x70: // Block load primary, user privilege
    case 0x71: // Block load secondary, user privilege
        if (rd & 7) {
            raise_exception(TT_ILL_INSN);
            return;
        }
        helper_check_align(addr, 0x3f);
        for (i = 0; i < 16; i++) {
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x1f, 4,
                                                         0);
            addr += 4;
        }

3180 3181 3182 3183 3184
        return;
    default:
        break;
    }

B
blueswir1 已提交
3185
    val = helper_ld_asi(addr, asi, size, 0);
3186 3187 3188
    switch(size) {
    default:
    case 4:
B
blueswir1 已提交
3189
        *((uint32_t *)&env->fpr[rd]) = val;
3190 3191
        break;
    case 8:
B
blueswir1 已提交
3192
        *((int64_t *)&DT0) = val;
3193
        break;
B
blueswir1 已提交
3194 3195 3196
    case 16:
        // XXX
        break;
3197 3198 3199
    }
}

B
blueswir1 已提交
3200
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
3201 3202
{
    unsigned int i;
B
blueswir1 已提交
3203
    target_ulong val = 0;
3204

3205
    helper_check_align(addr, 3);
3206 3207
    addr = asi_address_mask(env, asi, addr);

3208
    switch (asi) {
B
blueswir1 已提交
3209 3210
    case 0xe0: // UA2007 Block commit store primary (cache flush)
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
3211 3212 3213 3214
    case 0xf0: // Block store primary
    case 0xf1: // Block store secondary
    case 0xf8: // Block store primary LE
    case 0xf9: // Block store secondary LE
B
blueswir1 已提交
3215 3216 3217 3218
        if (rd & 7) {
            raise_exception(TT_ILL_INSN);
            return;
        }
3219
        helper_check_align(addr, 0x3f);
B
blueswir1 已提交
3220
        for (i = 0; i < 16; i++) {
B
blueswir1 已提交
3221 3222 3223
            val = *(uint32_t *)&env->fpr[rd++];
            helper_st_asi(addr, val, asi & 0x8f, 4);
            addr += 4;
3224 3225
        }

3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239
        return;
    case 0x70: // Block store primary, user privilege
    case 0x71: // Block store secondary, user privilege
        if (rd & 7) {
            raise_exception(TT_ILL_INSN);
            return;
        }
        helper_check_align(addr, 0x3f);
        for (i = 0; i < 16; i++) {
            val = *(uint32_t *)&env->fpr[rd++];
            helper_st_asi(addr, val, asi & 0x1f, 4);
            addr += 4;
        }

3240 3241 3242 3243 3244 3245 3246 3247
        return;
    default:
        break;
    }

    switch(size) {
    default:
    case 4:
B
blueswir1 已提交
3248
        val = *((uint32_t *)&env->fpr[rd]);
3249 3250
        break;
    case 8:
B
blueswir1 已提交
3251
        val = *((int64_t *)&DT0);
3252
        break;
B
blueswir1 已提交
3253 3254 3255
    case 16:
        // XXX
        break;
3256
    }
B
blueswir1 已提交
3257 3258 3259 3260 3261 3262 3263 3264
    helper_st_asi(addr, val, asi, size);
}

target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
                            target_ulong val2, uint32_t asi)
{
    target_ulong ret;

3265
    val2 &= 0xffffffffUL;
B
blueswir1 已提交
3266 3267
    ret = helper_ld_asi(addr, asi, 4, 0);
    ret &= 0xffffffffUL;
3268 3269
    if (val2 == ret)
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
B
blueswir1 已提交
3270
    return ret;
3271 3272
}

B
blueswir1 已提交
3273 3274 3275 3276 3277 3278
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
                             target_ulong val2, uint32_t asi)
{
    target_ulong ret;

    ret = helper_ld_asi(addr, asi, 8, 0);
3279 3280
    if (val2 == ret)
        helper_st_asi(addr, val1, asi, 8);
B
blueswir1 已提交
3281 3282
    return ret;
}
3283
#endif /* TARGET_SPARC64 */
B
bellard 已提交
3284 3285

#ifndef TARGET_SPARC64
B
blueswir1 已提交
3286
void helper_rett(void)
3287
{
3288 3289
    unsigned int cwp;

3290 3291 3292
    if (env->psret == 1)
        raise_exception(TT_ILL_INSN);

3293
    env->psret = 1;
3294
    cwp = cwp_inc(env->cwp + 1) ;
3295 3296 3297 3298 3299 3300
    if (env->wim & (1 << cwp)) {
        raise_exception(TT_WIN_UNF);
    }
    set_cwp(cwp);
    env->psrs = env->psrps;
}
B
bellard 已提交
3301
#endif
3302

B
blueswir1 已提交
3303 3304 3305 3306 3307
target_ulong helper_udiv(target_ulong a, target_ulong b)
{
    uint64_t x0;
    uint32_t x1;

3308
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3309
    x1 = (b & 0xffffffff);
B
blueswir1 已提交
3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329

    if (x1 == 0) {
        raise_exception(TT_DIV_ZERO);
    }

    x0 = x0 / x1;
    if (x0 > 0xffffffff) {
        env->cc_src2 = 1;
        return 0xffffffff;
    } else {
        env->cc_src2 = 0;
        return x0;
    }
}

target_ulong helper_sdiv(target_ulong a, target_ulong b)
{
    int64_t x0;
    int32_t x1;

3330
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3331
    x1 = (b & 0xffffffff);
B
blueswir1 已提交
3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346

    if (x1 == 0) {
        raise_exception(TT_DIV_ZERO);
    }

    x0 = x0 / x1;
    if ((int32_t) x0 != x0) {
        env->cc_src2 = 1;
        return x0 < 0? 0x80000000: 0x7fffffff;
    } else {
        env->cc_src2 = 0;
        return x0;
    }
}

B
blueswir1 已提交
3347 3348
void helper_stdf(target_ulong addr, int mem_idx)
{
3349
    helper_check_align(addr, 7);
B
blueswir1 已提交
3350 3351
#if !defined(CONFIG_USER_ONLY)
    switch (mem_idx) {
3352
    case MMU_USER_IDX:
3353
        stfq_user(addr, DT0);
B
blueswir1 已提交
3354
        break;
3355
    case MMU_KERNEL_IDX:
3356
        stfq_kernel(addr, DT0);
B
blueswir1 已提交
3357 3358
        break;
#ifdef TARGET_SPARC64
3359
    case MMU_HYPV_IDX:
3360
        stfq_hypv(addr, DT0);
B
blueswir1 已提交
3361 3362 3363
        break;
#endif
    default:
3364
        DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx);
B
blueswir1 已提交
3365 3366 3367
        break;
    }
#else
3368
    stfq_raw(address_mask(env, addr), DT0);
B
blueswir1 已提交
3369 3370 3371 3372 3373
#endif
}

void helper_lddf(target_ulong addr, int mem_idx)
{
3374
    helper_check_align(addr, 7);
B
blueswir1 已提交
3375 3376
#if !defined(CONFIG_USER_ONLY)
    switch (mem_idx) {
3377
    case MMU_USER_IDX:
3378
        DT0 = ldfq_user(addr);
B
blueswir1 已提交
3379
        break;
3380
    case MMU_KERNEL_IDX:
3381
        DT0 = ldfq_kernel(addr);
B
blueswir1 已提交
3382 3383
        break;
#ifdef TARGET_SPARC64
3384
    case MMU_HYPV_IDX:
3385
        DT0 = ldfq_hypv(addr);
B
blueswir1 已提交
3386 3387 3388
        break;
#endif
    default:
3389
        DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx);
B
blueswir1 已提交
3390 3391 3392
        break;
    }
#else
3393
    DT0 = ldfq_raw(address_mask(env, addr));
B
blueswir1 已提交
3394 3395 3396
#endif
}

B
blueswir1 已提交
3397
void helper_ldqf(target_ulong addr, int mem_idx)
B
blueswir1 已提交
3398 3399 3400 3401
{
    // XXX add 128 bit load
    CPU_QuadU u;

3402
    helper_check_align(addr, 7);
B
blueswir1 已提交
3403 3404
#if !defined(CONFIG_USER_ONLY)
    switch (mem_idx) {
3405
    case MMU_USER_IDX:
3406 3407
        u.ll.upper = ldq_user(addr);
        u.ll.lower = ldq_user(addr + 8);
B
blueswir1 已提交
3408 3409
        QT0 = u.q;
        break;
3410
    case MMU_KERNEL_IDX:
3411 3412
        u.ll.upper = ldq_kernel(addr);
        u.ll.lower = ldq_kernel(addr + 8);
B
blueswir1 已提交
3413 3414 3415
        QT0 = u.q;
        break;
#ifdef TARGET_SPARC64
3416
    case MMU_HYPV_IDX:
3417 3418
        u.ll.upper = ldq_hypv(addr);
        u.ll.lower = ldq_hypv(addr + 8);
B
blueswir1 已提交
3419 3420 3421 3422
        QT0 = u.q;
        break;
#endif
    default:
3423
        DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx);
B
blueswir1 已提交
3424 3425 3426
        break;
    }
#else
3427 3428
    u.ll.upper = ldq_raw(address_mask(env, addr));
    u.ll.lower = ldq_raw(address_mask(env, addr + 8));
B
blueswir1 已提交
3429
    QT0 = u.q;
B
blueswir1 已提交
3430
#endif
B
blueswir1 已提交
3431 3432
}

B
blueswir1 已提交
3433
void helper_stqf(target_ulong addr, int mem_idx)
B
blueswir1 已提交
3434 3435 3436 3437
{
    // XXX add 128 bit store
    CPU_QuadU u;

3438
    helper_check_align(addr, 7);
B
blueswir1 已提交
3439 3440
#if !defined(CONFIG_USER_ONLY)
    switch (mem_idx) {
3441
    case MMU_USER_IDX:
B
blueswir1 已提交
3442
        u.q = QT0;
3443 3444
        stq_user(addr, u.ll.upper);
        stq_user(addr + 8, u.ll.lower);
B
blueswir1 已提交
3445
        break;
3446
    case MMU_KERNEL_IDX:
B
blueswir1 已提交
3447
        u.q = QT0;
3448 3449
        stq_kernel(addr, u.ll.upper);
        stq_kernel(addr + 8, u.ll.lower);
B
blueswir1 已提交
3450 3451
        break;
#ifdef TARGET_SPARC64
3452
    case MMU_HYPV_IDX:
B
blueswir1 已提交
3453
        u.q = QT0;
3454 3455
        stq_hypv(addr, u.ll.upper);
        stq_hypv(addr + 8, u.ll.lower);
B
blueswir1 已提交
3456 3457 3458
        break;
#endif
    default:
3459
        DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx);
B
blueswir1 已提交
3460 3461 3462
        break;
    }
#else
B
blueswir1 已提交
3463
    u.q = QT0;
3464 3465
    stq_raw(address_mask(env, addr), u.ll.upper);
    stq_raw(address_mask(env, addr + 8), u.ll.lower);
B
blueswir1 已提交
3466
#endif
B
blueswir1 已提交
3467
}
B
blueswir1 已提交
3468

3469
static inline void set_fsr(void)
3470
{
B
bellard 已提交
3471
    int rnd_mode;
B
blueswir1 已提交
3472

3473 3474
    switch (env->fsr & FSR_RD_MASK) {
    case FSR_RD_NEAREST:
B
bellard 已提交
3475
        rnd_mode = float_round_nearest_even;
B
blueswir1 已提交
3476
        break;
B
bellard 已提交
3477
    default:
3478
    case FSR_RD_ZERO:
B
bellard 已提交
3479
        rnd_mode = float_round_to_zero;
B
blueswir1 已提交
3480
        break;
3481
    case FSR_RD_POS:
B
bellard 已提交
3482
        rnd_mode = float_round_up;
B
blueswir1 已提交
3483
        break;
3484
    case FSR_RD_NEG:
B
bellard 已提交
3485
        rnd_mode = float_round_down;
B
blueswir1 已提交
3486
        break;
3487
    }
B
bellard 已提交
3488
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3489
}
B
bellard 已提交
3490

3491
void helper_ldfsr(uint32_t new_fsr)
B
blueswir1 已提交
3492
{
3493 3494
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
    set_fsr();
B
blueswir1 已提交
3495 3496
}

3497 3498 3499 3500 3501 3502 3503 3504
#ifdef TARGET_SPARC64
void helper_ldxfsr(uint64_t new_fsr)
{
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
    set_fsr();
}
#endif

B
blueswir1 已提交
3505
void helper_debug(void)
B
bellard 已提交
3506 3507 3508 3509
{
    env->exception_index = EXCP_DEBUG;
    cpu_loop_exit();
}
3510

B
bellard 已提交
3511
#ifndef TARGET_SPARC64
3512 3513 3514 3515 3516 3517
/* XXX: use another pointer for %iN registers to avoid slow wrapping
   handling ? */
void helper_save(void)
{
    uint32_t cwp;

3518
    cwp = cwp_dec(env->cwp - 1);
3519 3520 3521 3522 3523 3524 3525 3526 3527 3528
    if (env->wim & (1 << cwp)) {
        raise_exception(TT_WIN_OVF);
    }
    set_cwp(cwp);
}

void helper_restore(void)
{
    uint32_t cwp;

3529
    cwp = cwp_inc(env->cwp + 1);
3530 3531 3532 3533 3534 3535
    if (env->wim & (1 << cwp)) {
        raise_exception(TT_WIN_UNF);
    }
    set_cwp(cwp);
}

B
blueswir1 已提交
3536
void helper_wrpsr(target_ulong new_psr)
3537
{
3538
    if ((new_psr & PSR_CWP) >= env->nwindows) {
3539
        raise_exception(TT_ILL_INSN);
3540 3541 3542
    } else {
        cpu_put_psr(env, new_psr);
    }
3543 3544
}

B
blueswir1 已提交
3545
target_ulong helper_rdpsr(void)
3546
{
3547
    return get_psr();
3548
}
B
bellard 已提交
3549 3550

#else
3551 3552 3553 3554 3555 3556
/* XXX: use another pointer for %iN registers to avoid slow wrapping
   handling ? */
void helper_save(void)
{
    uint32_t cwp;

3557
    cwp = cwp_dec(env->cwp - 1);
3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577
    if (env->cansave == 0) {
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
                                    ((env->wstate & 0x7) << 2)));
    } else {
        if (env->cleanwin - env->canrestore == 0) {
            // XXX Clean windows without trap
            raise_exception(TT_CLRWIN);
        } else {
            env->cansave--;
            env->canrestore++;
            set_cwp(cwp);
        }
    }
}

void helper_restore(void)
{
    uint32_t cwp;

3578
    cwp = cwp_inc(env->cwp + 1);
3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591
    if (env->canrestore == 0) {
        raise_exception(TT_FILL | (env->otherwin != 0 ?
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
                                   ((env->wstate & 0x7) << 2)));
    } else {
        env->cansave++;
        env->canrestore--;
        set_cwp(cwp);
    }
}

void helper_flushw(void)
{
3592
    if (env->cansave != env->nwindows - 2) {
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
                                    ((env->wstate & 0x7) << 2)));
    }
}

void helper_saved(void)
{
    env->cansave++;
    if (env->otherwin == 0)
        env->canrestore--;
    else
        env->otherwin--;
}

void helper_restored(void)
{
    env->canrestore++;
3611
    if (env->cleanwin < env->nwindows - 1)
3612 3613 3614 3615 3616 3617 3618
        env->cleanwin++;
    if (env->otherwin == 0)
        env->cansave--;
    else
        env->otherwin--;
}

3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693
static target_ulong get_ccr(void)
{
    target_ulong psr;

    psr = get_psr();

    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
}

target_ulong cpu_get_ccr(CPUState *env1)
{
    CPUState *saved_env;
    target_ulong ret;

    saved_env = env;
    env = env1;
    ret = get_ccr();
    env = saved_env;
    return ret;
}

static void put_ccr(target_ulong val)
{
    target_ulong tmp = val;

    env->xcc = (tmp >> 4) << 20;
    env->psr = (tmp & 0xf) << 20;
    CC_OP = CC_OP_FLAGS;
}

void cpu_put_ccr(CPUState *env1, target_ulong val)
{
    CPUState *saved_env;

    saved_env = env;
    env = env1;
    put_ccr(val);
    env = saved_env;
}

static target_ulong get_cwp64(void)
{
    return env->nwindows - 1 - env->cwp;
}

target_ulong cpu_get_cwp64(CPUState *env1)
{
    CPUState *saved_env;
    target_ulong ret;

    saved_env = env;
    env = env1;
    ret = get_cwp64();
    env = saved_env;
    return ret;
}

static void put_cwp64(int cwp)
{
    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
        cwp %= env->nwindows;
    }
    set_cwp(env->nwindows - 1 - cwp);
}

void cpu_put_cwp64(CPUState *env1, int cwp)
{
    CPUState *saved_env;

    saved_env = env;
    env = env1;
    put_cwp64(cwp);
    env = saved_env;
}

B
blueswir1 已提交
3694 3695
target_ulong helper_rdccr(void)
{
3696
    return get_ccr();
B
blueswir1 已提交
3697 3698 3699 3700
}

void helper_wrccr(target_ulong new_ccr)
{
3701
    put_ccr(new_ccr);
B
blueswir1 已提交
3702 3703 3704 3705 3706 3707
}

// CWP handling is reversed in V9, but we still use the V8 register
// order.
target_ulong helper_rdcwp(void)
{
3708
    return get_cwp64();
B
blueswir1 已提交
3709 3710 3711 3712
}

void helper_wrcwp(target_ulong new_cwp)
{
3713
    put_cwp64(new_cwp);
B
blueswir1 已提交
3714
}
B
bellard 已提交
3715

3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
// This function uses non-native bit order
#define GET_FIELD(X, FROM, TO)                                  \
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))

// This function uses the order in the manuals, i.e. bit 0 is 2^0
#define GET_FIELD_SP(X, FROM, TO)               \
    GET_FIELD(X, 63 - (TO), 63 - (FROM))

target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
{
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
        (((pixel_addr >> 55) & 1) << 4) |
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
        GET_FIELD_SP(pixel_addr, 11, 12);
}

target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
{
    uint64_t tmp;

    tmp = addr + offset;
    env->gsr &= ~7ULL;
    env->gsr |= tmp & 7ULL;
    return tmp & ~7ULL;
}

B
blueswir1 已提交
3747
target_ulong helper_popc(target_ulong val)
B
bellard 已提交
3748
{
B
blueswir1 已提交
3749
    return ctpop64(val);
B
bellard 已提交
3750
}
B
bellard 已提交
3751

3752
static inline uint64_t *get_gregset(uint32_t pstate)
B
bellard 已提交
3753 3754 3755
{
    switch (pstate) {
    default:
3756 3757 3758 3759 3760 3761
        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
                pstate,
                (pstate & PS_IG) ? " IG" : "",
                (pstate & PS_MG) ? " MG" : "",
                (pstate & PS_AG) ? " AG" : "");
        /* pass through to normal set of global registers */
B
bellard 已提交
3762
    case 0:
B
blueswir1 已提交
3763
        return env->bgregs;
B
bellard 已提交
3764
    case PS_AG:
B
blueswir1 已提交
3765
        return env->agregs;
B
bellard 已提交
3766
    case PS_MG:
B
blueswir1 已提交
3767
        return env->mgregs;
B
bellard 已提交
3768
    case PS_IG:
B
blueswir1 已提交
3769
        return env->igregs;
B
bellard 已提交
3770 3771 3772
    }
}

3773
static inline void change_pstate(uint32_t new_pstate)
B
bellard 已提交
3774
{
3775
    uint32_t pstate_regs, new_pstate_regs;
B
bellard 已提交
3776 3777
    uint64_t *src, *dst;

3778 3779 3780 3781 3782
    if (env->def->features & CPU_FEATURE_GL) {
        // PS_AG is not implemented in this case
        new_pstate &= ~PS_AG;
    }

B
bellard 已提交
3783 3784
    pstate_regs = env->pstate & 0xc01;
    new_pstate_regs = new_pstate & 0xc01;
3785

B
bellard 已提交
3786
    if (new_pstate_regs != pstate_regs) {
3787 3788
        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
                       pstate_regs, new_pstate_regs);
B
blueswir1 已提交
3789 3790 3791 3792 3793
        // Switch global register bank
        src = get_gregset(new_pstate_regs);
        dst = get_gregset(pstate_regs);
        memcpy32(dst, env->gregs);
        memcpy32(env->gregs, src);
B
bellard 已提交
3794
    }
3795 3796 3797 3798
    else {
        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
                       new_pstate_regs);
    }
B
bellard 已提交
3799 3800 3801
    env->pstate = new_pstate;
}

B
blueswir1 已提交
3802
void helper_wrpstate(target_ulong new_state)
3803
{
3804
    change_pstate(new_state & 0xf3f);
3805 3806 3807 3808 3809 3810

#if !defined(CONFIG_USER_ONLY)
    if (cpu_interrupts_enabled(env)) {
        cpu_check_irqs(env);
    }
#endif
3811 3812
}

3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826
void helper_wrpil(target_ulong new_pil)
{
#if !defined(CONFIG_USER_ONLY)
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
                   env->psrpil, (uint32_t)new_pil);

    env->psrpil = new_pil;

    if (cpu_interrupts_enabled(env)) {
        cpu_check_irqs(env);
    }
#endif
}

B
blueswir1 已提交
3827
void helper_done(void)
B
bellard 已提交
3828
{
3829 3830
    trap_state* tsptr = cpu_tsptr(env);

3831
    env->pc = tsptr->tnpc;
3832
    env->npc = tsptr->tnpc + 4;
3833
    put_ccr(tsptr->tstate >> 32);
3834 3835
    env->asi = (tsptr->tstate >> 24) & 0xff;
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3836
    put_cwp64(tsptr->tstate & 0xff);
B
blueswir1 已提交
3837
    env->tl--;
3838 3839 3840 3841 3842 3843 3844 3845

    DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);

#if !defined(CONFIG_USER_ONLY)
    if (cpu_interrupts_enabled(env)) {
        cpu_check_irqs(env);
    }
#endif
B
bellard 已提交
3846 3847
}

B
blueswir1 已提交
3848
void helper_retry(void)
B
bellard 已提交
3849
{
3850 3851 3852 3853
    trap_state* tsptr = cpu_tsptr(env);

    env->pc = tsptr->tpc;
    env->npc = tsptr->tnpc;
3854
    put_ccr(tsptr->tstate >> 32);
3855 3856
    env->asi = (tsptr->tstate >> 24) & 0xff;
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3857
    put_cwp64(tsptr->tstate & 0xff);
B
blueswir1 已提交
3858
    env->tl--;
3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879

    DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);

#if !defined(CONFIG_USER_ONLY)
    if (cpu_interrupts_enabled(env)) {
        cpu_check_irqs(env);
    }
#endif
}

static void do_modify_softint(const char* operation, uint32_t value)
{
    if (env->softint != value) {
        env->softint = value;
        DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
#if !defined(CONFIG_USER_ONLY)
        if (cpu_interrupts_enabled(env)) {
            cpu_check_irqs(env);
        }
#endif
    }
B
bellard 已提交
3880
}
3881 3882 3883

void helper_set_softint(uint64_t value)
{
3884
    do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
3885 3886 3887 3888
}

void helper_clear_softint(uint64_t value)
{
3889
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3890 3891 3892 3893
}

void helper_write_softint(uint64_t value)
{
3894
    do_modify_softint("helper_write_softint", (uint32_t)value);
3895
}
B
bellard 已提交
3896
#endif
3897

B
blueswir1 已提交
3898
void helper_flush(target_ulong addr)
3899
{
B
blueswir1 已提交
3900 3901
    addr &= ~7;
    tb_invalidate_page_range(addr, addr + 8);
3902 3903
}

B
blueswir1 已提交
3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940
#ifdef TARGET_SPARC64
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
    [TT_TFAULT] = "Instruction Access Fault",
    [TT_TMISS] = "Instruction Access MMU Miss",
    [TT_CODE_ACCESS] = "Instruction Access Error",
    [TT_ILL_INSN] = "Illegal Instruction",
    [TT_PRIV_INSN] = "Privileged Instruction",
    [TT_NFPU_INSN] = "FPU Disabled",
    [TT_FP_EXCP] = "FPU Exception",
    [TT_TOVF] = "Tag Overflow",
    [TT_CLRWIN] = "Clean Windows",
    [TT_DIV_ZERO] = "Division By Zero",
    [TT_DFAULT] = "Data Access Fault",
    [TT_DMISS] = "Data Access MMU Miss",
    [TT_DATA_ACCESS] = "Data Access Error",
    [TT_DPROT] = "Data Protection Error",
    [TT_UNALIGNED] = "Unaligned Memory Access",
    [TT_PRIV_ACT] = "Privileged Action",
    [TT_EXTINT | 0x1] = "External Interrupt 1",
    [TT_EXTINT | 0x2] = "External Interrupt 2",
    [TT_EXTINT | 0x3] = "External Interrupt 3",
    [TT_EXTINT | 0x4] = "External Interrupt 4",
    [TT_EXTINT | 0x5] = "External Interrupt 5",
    [TT_EXTINT | 0x6] = "External Interrupt 6",
    [TT_EXTINT | 0x7] = "External Interrupt 7",
    [TT_EXTINT | 0x8] = "External Interrupt 8",
    [TT_EXTINT | 0x9] = "External Interrupt 9",
    [TT_EXTINT | 0xa] = "External Interrupt 10",
    [TT_EXTINT | 0xb] = "External Interrupt 11",
    [TT_EXTINT | 0xc] = "External Interrupt 12",
    [TT_EXTINT | 0xd] = "External Interrupt 13",
    [TT_EXTINT | 0xe] = "External Interrupt 14",
    [TT_EXTINT | 0xf] = "External Interrupt 15",
};
#endif

3941 3942 3943 3944 3945
trap_state* cpu_tsptr(CPUState* env)
{
    return &env->ts[env->tl & MAXTL_MASK];
}

B
blueswir1 已提交
3946 3947 3948
void do_interrupt(CPUState *env)
{
    int intno = env->exception_index;
3949
    trap_state* tsptr;
B
blueswir1 已提交
3950 3951

#ifdef DEBUG_PCALL
3952
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
B
blueswir1 已提交
3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969
        static int count;
        const char *name;

        if (intno < 0 || intno >= 0x180)
            name = "Unknown";
        else if (intno >= 0x100)
            name = "Trap Instruction";
        else if (intno >= 0xc0)
            name = "Window Fill";
        else if (intno >= 0x80)
            name = "Window Spill";
        else {
            name = excp_names[intno];
            if (!name)
                name = "Unknown";
        }

3970
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
B
blueswir1 已提交
3971 3972 3973 3974
                " SP=%016" PRIx64 "\n",
                count, name, intno,
                env->pc,
                env->npc, env->regwptr[6]);
3975
        log_cpu_state(env, 0);
B
blueswir1 已提交
3976 3977 3978 3979 3980
#if 0
        {
            int i;
            uint8_t *ptr;

3981
            qemu_log("       code=");
B
blueswir1 已提交
3982 3983
            ptr = (uint8_t *)env->pc;
            for(i = 0; i < 16; i++) {
3984
                qemu_log(" %02x", ldub(ptr + i));
B
blueswir1 已提交
3985
            }
3986
            qemu_log("\n");
B
blueswir1 已提交
3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005
        }
#endif
        count++;
    }
#endif
#if !defined(CONFIG_USER_ONLY)
    if (env->tl >= env->maxtl) {
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
                  " Error state", env->exception_index, env->tl, env->maxtl);
        return;
    }
#endif
    if (env->tl < env->maxtl - 1) {
        env->tl++;
    } else {
        env->pstate |= PS_RED;
        if (env->tl < env->maxtl)
            env->tl++;
    }
4006 4007
    tsptr = cpu_tsptr(env);

4008
    tsptr->tstate = (get_ccr() << 32) |
B
blueswir1 已提交
4009
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
4010
        get_cwp64();
4011 4012 4013
    tsptr->tpc = env->pc;
    tsptr->tnpc = env->npc;
    tsptr->tt = intno;
4014 4015 4016 4017 4018 4019 4020

    switch (intno) {
    case TT_IVEC:
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
        break;
    case TT_TFAULT:
    case TT_DFAULT:
4021 4022 4023
    case TT_TMISS ... TT_TMISS + 3:
    case TT_DMISS ... TT_DMISS + 3:
    case TT_DPROT ... TT_DPROT + 3:
4024 4025 4026 4027 4028
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
        break;
    default:
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
        break;
B
blueswir1 已提交
4029
    }
4030

4031 4032 4033 4034 4035 4036 4037
    if (intno == TT_CLRWIN) {
        set_cwp(cwp_dec(env->cwp - 1));
    } else if ((intno & 0x1c0) == TT_SPILL) {
        set_cwp(cwp_dec(env->cwp - env->cansave - 2));
    } else if ((intno & 0x1c0) == TT_FILL) {
        set_cwp(cwp_inc(env->cwp + 1));
    }
B
blueswir1 已提交
4038 4039 4040 4041
    env->tbr &= ~0x7fffULL;
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
    env->pc = env->tbr;
    env->npc = env->pc + 4;
4042
    env->exception_index = -1;
4043
}
B
blueswir1 已提交
4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
#else
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
    [TT_TFAULT] = "Instruction Access Fault",
    [TT_ILL_INSN] = "Illegal Instruction",
    [TT_PRIV_INSN] = "Privileged Instruction",
    [TT_NFPU_INSN] = "FPU Disabled",
    [TT_WIN_OVF] = "Window Overflow",
    [TT_WIN_UNF] = "Window Underflow",
    [TT_UNALIGNED] = "Unaligned Memory Access",
    [TT_FP_EXCP] = "FPU Exception",
    [TT_DFAULT] = "Data Access Fault",
    [TT_TOVF] = "Tag Overflow",
    [TT_EXTINT | 0x1] = "External Interrupt 1",
    [TT_EXTINT | 0x2] = "External Interrupt 2",
    [TT_EXTINT | 0x3] = "External Interrupt 3",
    [TT_EXTINT | 0x4] = "External Interrupt 4",
    [TT_EXTINT | 0x5] = "External Interrupt 5",
    [TT_EXTINT | 0x6] = "External Interrupt 6",
    [TT_EXTINT | 0x7] = "External Interrupt 7",
    [TT_EXTINT | 0x8] = "External Interrupt 8",
    [TT_EXTINT | 0x9] = "External Interrupt 9",
    [TT_EXTINT | 0xa] = "External Interrupt 10",
    [TT_EXTINT | 0xb] = "External Interrupt 11",
    [TT_EXTINT | 0xc] = "External Interrupt 12",
    [TT_EXTINT | 0xd] = "External Interrupt 13",
    [TT_EXTINT | 0xe] = "External Interrupt 14",
    [TT_EXTINT | 0xf] = "External Interrupt 15",
    [TT_TOVF] = "Tag Overflow",
    [TT_CODE_ACCESS] = "Instruction Access Error",
    [TT_DATA_ACCESS] = "Data Access Error",
    [TT_DIV_ZERO] = "Division By Zero",
    [TT_NCP_INSN] = "Coprocessor Disabled",
};
#endif
4079

B
blueswir1 已提交
4080
void do_interrupt(CPUState *env)
4081
{
B
blueswir1 已提交
4082 4083 4084
    int cwp, intno = env->exception_index;

#ifdef DEBUG_PCALL
4085
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
B
blueswir1 已提交
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098
        static int count;
        const char *name;

        if (intno < 0 || intno >= 0x100)
            name = "Unknown";
        else if (intno >= 0x80)
            name = "Trap Instruction";
        else {
            name = excp_names[intno];
            if (!name)
                name = "Unknown";
        }

4099
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
B
blueswir1 已提交
4100 4101 4102
                count, name, intno,
                env->pc,
                env->npc, env->regwptr[6]);
4103
        log_cpu_state(env, 0);
B
blueswir1 已提交
4104 4105 4106 4107 4108
#if 0
        {
            int i;
            uint8_t *ptr;

4109
            qemu_log("       code=");
B
blueswir1 已提交
4110 4111
            ptr = (uint8_t *)env->pc;
            for(i = 0; i < 16; i++) {
4112
                qemu_log(" %02x", ldub(ptr + i));
B
blueswir1 已提交
4113
            }
4114
            qemu_log("\n");
B
blueswir1 已提交
4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127
        }
#endif
        count++;
    }
#endif
#if !defined(CONFIG_USER_ONLY)
    if (env->psret == 0) {
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
                  env->exception_index);
        return;
    }
#endif
    env->psret = 0;
4128 4129
    cwp = cwp_dec(env->cwp - 1);
    set_cwp(cwp);
B
blueswir1 已提交
4130 4131 4132 4133 4134 4135 4136
    env->regwptr[9] = env->pc;
    env->regwptr[10] = env->npc;
    env->psrps = env->psrs;
    env->psrs = 1;
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
    env->pc = env->tbr;
    env->npc = env->pc + 4;
4137
    env->exception_index = -1;
4138
}
B
blueswir1 已提交
4139
#endif
4140

4141
#if !defined(CONFIG_USER_ONLY)
4142

4143 4144 4145
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                                void *retaddr);

4146
#define MMUSUFFIX _mmu
4147
#define ALIGNED_ONLY
4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160

#define SHIFT 0
#include "softmmu_template.h"

#define SHIFT 1
#include "softmmu_template.h"

#define SHIFT 2
#include "softmmu_template.h"

#define SHIFT 3
#include "softmmu_template.h"

4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178
/* XXX: make it generic ? */
static void cpu_restore_state2(void *retaddr)
{
    TranslationBlock *tb;
    unsigned long pc;

    if (retaddr) {
        /* now we have a real cpu fault */
        pc = (unsigned long)retaddr;
        tb = tb_find_pc(pc);
        if (tb) {
            /* the PC is inside the translated code. It means that we have
               a virtual CPU fault */
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
        }
    }
}

4179 4180 4181
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                                void *retaddr)
{
B
blueswir1 已提交
4182
#ifdef DEBUG_UNALIGNED
4183 4184
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
           "\n", addr, env->pc);
B
blueswir1 已提交
4185
#endif
4186
    cpu_restore_state2(retaddr);
B
blueswir1 已提交
4187
    raise_exception(TT_UNALIGNED);
4188
}
4189 4190 4191 4192 4193

/* try to fill the TLB and return an exception if error. If retaddr is
   NULL, it means that the function was called in C code (i.e. not
   from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
4194
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4195 4196 4197 4198 4199 4200 4201 4202 4203
{
    int ret;
    CPUState *saved_env;

    /* XXX: hack to restore env in all cases, even if not called from
       generated code */
    saved_env = env;
    env = cpu_single_env;

4204
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4205
    if (ret) {
4206
        cpu_restore_state2(retaddr);
4207 4208 4209 4210 4211
        cpu_loop_exit();
    }
    env = saved_env;
}

P
Paul Brook 已提交
4212
#endif /* !CONFIG_USER_ONLY */
4213 4214

#ifndef TARGET_SPARC64
P
Paul Brook 已提交
4215
#if !defined(CONFIG_USER_ONLY)
A
Anthony Liguori 已提交
4216
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4217
                          int is_asi, int size)
4218 4219
{
    CPUState *saved_env;
4220
    int fault_type;
4221 4222 4223 4224 4225

    /* XXX: hack to restore env in all cases, even if not called from
       generated code */
    saved_env = env;
    env = cpu_single_env;
4226 4227
#ifdef DEBUG_UNASSIGNED
    if (is_asi)
4228
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
B
blueswir1 已提交
4229
               " asi 0x%02x from " TARGET_FMT_lx "\n",
4230 4231
               is_exec ? "exec" : is_write ? "write" : "read", size,
               size == 1 ? "" : "s", addr, is_asi, env->pc);
4232
    else
4233 4234 4235 4236
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
               " from " TARGET_FMT_lx "\n",
               is_exec ? "exec" : is_write ? "write" : "read", size,
               size == 1 ? "" : "s", addr, env->pc);
4237
#endif
4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260
    /* Don't overwrite translation and access faults */
    fault_type = (env->mmuregs[3] & 0x1c) >> 2;
    if ((fault_type > 4) || (fault_type == 0)) {
        env->mmuregs[3] = 0; /* Fault status register */
        if (is_asi)
            env->mmuregs[3] |= 1 << 16;
        if (env->psrs)
            env->mmuregs[3] |= 1 << 5;
        if (is_exec)
            env->mmuregs[3] |= 1 << 6;
        if (is_write)
            env->mmuregs[3] |= 1 << 7;
        env->mmuregs[3] |= (5 << 2) | 2;
        /* SuperSPARC will never place instruction fault addresses in the FAR */
        if (!is_exec) {
            env->mmuregs[4] = addr; /* Fault address register */
        }
    }
    /* overflow (same type fault was not read before another fault) */
    if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
        env->mmuregs[3] |= 1;
    }

4261
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
4262 4263 4264 4265
        if (is_exec)
            raise_exception(TT_CODE_ACCESS);
        else
            raise_exception(TT_DATA_ACCESS);
4266
    }
4267 4268 4269 4270 4271 4272

    /* flush neverland mappings created during no-fault mode,
       so the sequential MMU faults report proper fault types */
    if (env->mmuregs[0] & MMU_NF) {
        tlb_flush(env, 1);
    }
4273 4274

    env = saved_env;
4275
}
P
Paul Brook 已提交
4276 4277 4278 4279 4280
#endif
#else
#if defined(CONFIG_USER_ONLY)
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
                          int is_asi, int size)
4281
#else
A
Anthony Liguori 已提交
4282
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4283
                          int is_asi, int size)
P
Paul Brook 已提交
4284
#endif
4285 4286 4287 4288 4289 4290 4291
{
    CPUState *saved_env;

    /* XXX: hack to restore env in all cases, even if not called from
       generated code */
    saved_env = env;
    env = cpu_single_env;
4292 4293

#ifdef DEBUG_UNASSIGNED
B
blueswir1 已提交
4294 4295
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
           "\n", addr, env->pc);
4296
#endif
4297

4298 4299 4300 4301
    if (is_exec)
        raise_exception(TT_CODE_ACCESS);
    else
        raise_exception(TT_DATA_ACCESS);
4302 4303

    env = saved_env;
4304 4305
}
#endif
4306

P
Paul Brook 已提交
4307

B
blueswir1 已提交
4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331
#ifdef TARGET_SPARC64
void helper_tick_set_count(void *opaque, uint64_t count)
{
#if !defined(CONFIG_USER_ONLY)
    cpu_tick_set_count(opaque, count);
#endif
}

uint64_t helper_tick_get_count(void *opaque)
{
#if !defined(CONFIG_USER_ONLY)
    return cpu_tick_get_count(opaque);
#else
    return 0;
#endif
}

void helper_tick_set_limit(void *opaque, uint64_t limit)
{
#if !defined(CONFIG_USER_ONLY)
    cpu_tick_set_limit(opaque, limit);
#endif
}
#endif