Revision 056401ea

b/target-ppc/cpu.h
651 651
    /* Those resources are used only in Qemu core */
652 652
    jmp_buf jmp_env;
653 653
    int user_mode_only; /* user mode only simulation */
654
    target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */
654
    target_ulong hflags;      /* hflags is a MSR & HFLAGS_MASK         */
655
    target_ulong hflags_nmsr; /* specific hflags, not comming from MSR */
655 656
    int mmu_idx;         /* precomputed MMU index to speed up mem accesses */
656 657

  
657 658
    /* Power management */
......
698 699
target_ulong do_load_dbatl (CPUPPCState *env, int nr);
699 700
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
700 701
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
702
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
703
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
701 704
target_ulong do_load_sdr1 (CPUPPCState *env);
702 705
void do_store_sdr1 (CPUPPCState *env, target_ulong value);
703 706
#if defined(TARGET_PPC64)
b/target-ppc/helper.c
482 482
    int key, pp, valid, prot;
483 483

  
484 484
    bl = (*BATl & 0x0000003F) << 17;
485
#if defined (DEBUG_BATS)
485 486
    if (loglevel != 0) {
486 487
        fprintf(logfile, "b %02x ==> bl %08x msk %08x\n",
487 488
                *BATl & 0x0000003F, bl, ~bl);
488 489
    }
490
#endif
489 491
    prot = 0;
490 492
    valid = (*BATl >> 6) & 1;
491 493
    if (valid) {
......
1836 1838
    env->DBAT[1][nr] = value;
1837 1839
}
1838 1840

  
1841
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1842
{
1843
    target_ulong mask;
1844
    int do_inval;
1845

  
1846
    dump_store_bat(env, 'I', 0, nr, value);
1847
    if (env->IBAT[0][nr] != value) {
1848
        do_inval = 0;
1849
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1850
        if (env->IBAT[1][nr] & 0x40) {
1851
            /* Invalidate BAT only if it is valid */
1852
#if !defined(FLUSH_ALL_TLBS)
1853
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1854
#else
1855
            do_inval = 1;
1856
#endif
1857
        }
1858
        /* When storing valid upper BAT, mask BEPI and BRPN
1859
         * and invalidate all TLBs covered by this BAT
1860
         */
1861
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1862
            (value & ~0x0001FFFFUL & ~mask);
1863
        env->DBAT[0][nr] = env->IBAT[0][nr];
1864
        if (env->IBAT[1][nr] & 0x40) {
1865
#if !defined(FLUSH_ALL_TLBS)
1866
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1867
#else
1868
            do_inval = 1;
1869
#endif
1870
        }
1871
#if defined(FLUSH_ALL_TLBS)
1872
        if (do_inval)
1873
            tlb_flush(env, 1);
1874
#endif
1875
    }
1876
}
1877

  
1878
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1879
{
1880
    target_ulong mask;
1881
    int do_inval;
1882

  
1883
    dump_store_bat(env, 'I', 1, nr, value);
1884
    if (env->IBAT[1][nr] != value) {
1885
        do_inval = 0;
1886
        if (env->IBAT[1][nr] & 0x40) {
1887
#if !defined(FLUSH_ALL_TLBS)
1888
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1889
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1890
#else
1891
            do_inval = 1;
1892
#endif
1893
        }
1894
        if (value & 0x40) {
1895
#if !defined(FLUSH_ALL_TLBS)
1896
            mask = (value << 17) & 0x0FFE0000UL;
1897
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1898
#else
1899
            do_inval = 1;
1900
#endif
1901
        }
1902
        env->IBAT[1][nr] = value;
1903
        env->DBAT[1][nr] = value;
1904
#if defined(FLUSH_ALL_TLBS)
1905
        if (do_inval)
1906
            tlb_flush(env, 1);
1907
#endif
1908
    }
1909
}
1910

  
1839 1911
/*****************************************************************************/
1840 1912
/* TLB management */
1841 1913
void ppc_tlb_invalidate_all (CPUPPCState *env)
......
2684 2756
     *      any special case that could occur. Just store MSR and update hflags
2685 2757
     */
2686 2758
    env->msr = new_msr;
2759
    env->hflags_nmsr = 0x00000000;
2687 2760
    hreg_compute_hflags(env);
2688 2761
    env->nip = vector;
2689 2762
    /* Reset exception state */
b/target-ppc/helper_regs.h
58 58
    env->tgpr[3] = tmp;
59 59
}
60 60

  
61
static always_inline void hreg_compute_mem_idx (CPUPPCState *env)
62
{
63
#if defined (TARGET_PPC64H)
64
    /* Precompute MMU index */
65
    if (msr_pr == 0 && msr_hv != 0)
66
        env->mmu_idx = 2;
67
    else
68
#endif
69
        env->mmu_idx = 1 - msr_pr;
70
}
71

  
61 72
static always_inline void hreg_compute_hflags (CPUPPCState *env)
62 73
{
63 74
    target_ulong hflags_mask;
......
70 81
    hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF);
71 82
#if defined (TARGET_PPC64H)
72 83
    hflags_mask |= 1ULL << MSR_HV;
73
    /* Precompute MMU index */
74
    if (msr_pr == 0 && msr_hv != 0)
75
        env->mmu_idx = 2;
76
    else
77 84
#endif
78 85
#endif
79
        env->mmu_idx = 1 - msr_pr;
86
    hreg_compute_mem_idx(env);
80 87
    env->hflags = env->msr & hflags_mask;
88
    /* Merge with hflags coming from other registers */
89
    env->hflags |= env->hflags_nmsr;
81 90
}
82 91

  
83 92
static always_inline int hreg_store_msr (CPUPPCState *env, target_ulong value)
b/target-ppc/op.c
2190 2190
    RETURN();
2191 2191
}
2192 2192

  
2193
void OPPROTO op_store_hid0_601 (void)
2194
{
2195
    do_store_hid0_601();
2196
    RETURN();
2197
}
2198

  
2193 2199
void OPPROTO op_load_601_bat (void)
2194 2200
{
2195 2201
    T0 = env->IBAT[PARAM1][PARAM2];
2196 2202
    RETURN();
2197 2203
}
2198
#endif /* !defined(CONFIG_USER_ONLY) */
2199 2204

  
2200
/* 601 unified BATs store.
2201
 * To avoid using specific MMU code for 601, we store BATs in
2202
 * IBAT and DBAT simultaneously, then emulate unified BATs.
2203
 */
2204
#if !defined(CONFIG_USER_ONLY)
2205 2205
void OPPROTO op_store_601_batl (void)
2206 2206
{
2207
    int nr = PARAM1;
2208

  
2209
    env->IBAT[1][nr] = T0;
2210
    env->DBAT[1][nr] = T0;
2207
    do_store_ibatl_601(env, PARAM1, T0);
2211 2208
    RETURN();
2212 2209
}
2213 2210

  
2214 2211
void OPPROTO op_store_601_batu (void)
2215 2212
{
2216
    do_store_601_batu(PARAM1);
2213
    do_store_ibatu_601(env, PARAM1, T0);
2217 2214
    RETURN();
2218 2215
}
2219 2216
#endif /* !defined(CONFIG_USER_ONLY) */
b/target-ppc/op_helper.c
1701 1701
    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1702 1702
}
1703 1703

  
1704
/* PowerPC 601 BAT management helper */
1705
void do_store_601_batu (int nr)
1704
void do_store_hid0_601 (void)
1706 1705
{
1707
    do_store_ibatu(env, nr, (uint32_t)T0);
1708
    env->DBAT[0][nr] = env->IBAT[0][nr];
1709
    env->DBAT[1][nr] = env->IBAT[1][nr];
1706
    uint32_t hid0;
1707

  
1708
    hid0 = env->spr[SPR_HID0];
1709
    if ((T0 ^ hid0) & 0x00000008) {
1710
        /* Change current endianness */
1711
        env->hflags &= ~(1 << MSR_LE);
1712
        env->hflags_nmsr &= ~(1 << MSR_LE);
1713
        env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
1714
        env->hflags |= env->hflags_nmsr;
1715
        if (loglevel != 0) {
1716
            fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
1717
                    __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
1718
        }
1719
    }
1720
    env->spr[SPR_HID0] = T0;
1710 1721
}
1711 1722
#endif
1712 1723

  
b/target-ppc/op_helper.h
155 155
#endif
156 156

  
157 157
/* POWER / PowerPC 601 specific helpers */
158
void do_store_601_batu (int nr);
159 158
void do_POWER_abso (void);
160 159
void do_POWER_clcs (void);
161 160
void do_POWER_div (void);
......
168 167
#if !defined(CONFIG_USER_ONLY)
169 168
void do_POWER_rac (void);
170 169
void do_POWER_rfsvc (void);
170
void do_store_hid0_601 (void);
171 171
#endif
172 172

  
173 173
/* PowerPC 602 specific helper */
b/target-ppc/translate.c
6801 6801
    opc_handler_t **table, *handler;
6802 6802
    target_ulong pc_start;
6803 6803
    uint16_t *gen_opc_end;
6804
    int supervisor;
6804
    int supervisor, little_endian;
6805 6805
    int single_step, branch_step;
6806 6806
    int j, lj = -1;
6807 6807

  
......
6821 6821
#if !defined(CONFIG_USER_ONLY)
6822 6822
    ctx.supervisor = supervisor;
6823 6823
#endif
6824
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6824 6825
#if defined(TARGET_PPC64)
6825 6826
    ctx.sf_mode = msr_sf;
6826
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
6827
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6827 6828
#else
6828
    ctx.mem_idx = (supervisor << 1) | msr_le;
6829
    ctx.mem_idx = (supervisor << 1) | little_endian;
6829 6830
#endif
6830 6831
    ctx.dcache_line_size = env->dcache_line_size;
6831 6832
    ctx.fpu_enabled = msr_fp;
......
6880 6881
                    ctx.nip, supervisor, (int)msr_ir);
6881 6882
        }
6882 6883
#endif
6883
        ctx.opcode = ldl_code(ctx.nip);
6884
        if (msr_le) {
6885
            ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
6886
                ((ctx.opcode & 0x00FF0000) >> 8) |
6887
                ((ctx.opcode & 0x0000FF00) << 8) |
6888
                ((ctx.opcode & 0x000000FF) << 24);
6884
        if (unlikely(little_endian)) {
6885
            ctx.opcode = bswap32(ldl_code(ctx.nip));
6886
        } else {
6887
            ctx.opcode = ldl_code(ctx.nip);
6889 6888
        }
6890 6889
#if defined PPC_DEBUG_DISAS
6891 6890
        if (loglevel & CPU_LOG_TB_IN_ASM) {
6892 6891
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6893 6892
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6894
                    opc3(ctx.opcode), msr_le ? "little" : "big");
6893
                    opc3(ctx.opcode), little_endian ? "little" : "big");
6895 6894
        }
6896 6895
#endif
6897 6896
        ctx.nip += 4;
......
6986 6985
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6987 6986
        int flags;
6988 6987
        flags = env->bfd_mach;
6989
        flags |= msr_le << 16;
6988
        flags |= little_endian << 16;
6990 6989
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6991 6990
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
6992 6991
        fprintf(logfile, "\n");
b/target-ppc/translate_init.c
314 314
{
315 315
    gen_op_store_601_rtcl();
316 316
}
317

  
318
static void spr_write_hid0_601 (void *opaque, int sprn)
319
{
320
    DisasContext *ctx = opaque;
321

  
322
    gen_op_store_hid0_601();
323
    /* Must stop the translation as endianness may have changed */
324
    GEN_STOP(ctx);
325
}
317 326
#endif
318 327

  
319 328
/* Unified bats */
......
3259 3268
    /* XXX : not implemented */
3260 3269
    spr_register(env, SPR_HID0, "HID0",
3261 3270
                 SPR_NOACCESS, SPR_NOACCESS,
3262
                 &spr_read_generic, &spr_write_generic,
3271
                 &spr_read_generic, &spr_write_hid0_601,
3263 3272
                 0x80010080);
3264 3273
    /* XXX : not implemented */
3265 3274
    spr_register(env, SPR_HID1, "HID1",

Also available in: Unified diff