misc_helper.c 5.9 KB
Newer Older
B
Blue Swirl 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Miscellaneous PowerPC emulation helpers for QEMU.
 *
 *  Copyright (c) 2003-2007 Jocelyn Mayer
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
P
Peter Maydell 已提交
19
#include "qemu/osdep.h"
B
Blue Swirl 已提交
20
#include "cpu.h"
21
#include "exec/exec-all.h"
22
#include "exec/helper-proto.h"
B
Blue Swirl 已提交
23 24 25 26 27

#include "helper_regs.h"

/*****************************************************************************/
/* SPR accesses */
B
Blue Swirl 已提交
28
void helper_load_dump_spr(CPUPPCState *env, uint32_t sprn)
B
Blue Swirl 已提交
29 30 31 32 33
{
    qemu_log("Read SPR %d %03x => " TARGET_FMT_lx "\n", sprn, sprn,
             env->spr[sprn]);
}

B
Blue Swirl 已提交
34
void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
B
Blue Swirl 已提交
35 36 37 38
{
    qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
             env->spr[sprn]);
}
39 40 41

#ifdef TARGET_PPC64
static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
42 43
                               uint32_t sprn, uint32_t cause,
                               uintptr_t raddr)
44 45 46 47 48 49 50
{
    qemu_log("Facility SPR %d is unavailable (SPR FSCR:%d)\n", sprn, bit);

    env->spr[SPR_FSCR] &= ~((target_ulong)FSCR_IC_MASK << FSCR_IC_POS);
    cause &= FSCR_IC_MASK;
    env->spr[SPR_FSCR] |= (target_ulong)cause << FSCR_IC_POS;

51
    raise_exception_err_ra(env, POWERPC_EXCP_FU, 0, raddr);
52 53 54 55 56 57 58 59 60 61 62
}
#endif

void helper_fscr_facility_check(CPUPPCState *env, uint32_t bit,
                                uint32_t sprn, uint32_t cause)
{
#ifdef TARGET_PPC64
    if (env->spr[SPR_FSCR] & (1ULL << bit)) {
        /* Facility is enabled, continue */
        return;
    }
63
    raise_fu_exception(env, bit, sprn, cause, GETPC());
64 65 66
#endif
}

67 68 69 70 71 72 73 74
void helper_msr_facility_check(CPUPPCState *env, uint32_t bit,
                               uint32_t sprn, uint32_t cause)
{
#ifdef TARGET_PPC64
    if (env->msr & (1ULL << bit)) {
        /* Facility is enabled, continue */
        return;
    }
75
    raise_fu_exception(env, bit, sprn, cause, GETPC());
76 77 78
#endif
}

B
Blue Swirl 已提交
79 80
#if !defined(CONFIG_USER_ONLY)

B
Blue Swirl 已提交
81
void helper_store_sdr1(CPUPPCState *env, target_ulong val)
B
Blue Swirl 已提交
82
{
83 84
    PowerPCCPU *cpu = ppc_env_get_cpu(env);

85
    if (!env->external_htab) {
86 87 88 89
        if (env->spr[SPR_SDR1] != val) {
            ppc_store_sdr1(env, val);
            tlb_flush(CPU(cpu), 1);
        }
90
    }
B
Blue Swirl 已提交
91 92
}

B
Blue Swirl 已提交
93
void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
B
Blue Swirl 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
{
    target_ulong hid0;

    hid0 = env->spr[SPR_HID0];
    if ((val ^ hid0) & 0x00000008) {
        /* Change current endianness */
        env->hflags &= ~(1 << MSR_LE);
        env->hflags_nmsr &= ~(1 << MSR_LE);
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
        env->hflags |= env->hflags_nmsr;
        qemu_log("%s: set endianness to %c => " TARGET_FMT_lx "\n", __func__,
                 val & 0x8 ? 'l' : 'b', env->hflags);
    }
    env->spr[SPR_HID0] = (uint32_t)val;
}

B
Blue Swirl 已提交
110
void helper_store_403_pbr(CPUPPCState *env, uint32_t num, target_ulong value)
B
Blue Swirl 已提交
111
{
112 113
    PowerPCCPU *cpu = ppc_env_get_cpu(env);

B
Blue Swirl 已提交
114 115 116
    if (likely(env->pb[num] != value)) {
        env->pb[num] = value;
        /* Should be optimized */
117
        tlb_flush(CPU(cpu), 1);
B
Blue Swirl 已提交
118 119 120
    }
}

B
Blue Swirl 已提交
121
void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val)
B
Blue Swirl 已提交
122 123 124 125
{
    store_40x_dbcr0(env, val);
}

B
Blue Swirl 已提交
126
void helper_store_40x_sler(CPUPPCState *env, target_ulong val)
B
Blue Swirl 已提交
127 128 129 130 131 132 133
{
    store_40x_sler(env, val);
}
#endif
/*****************************************************************************/
/* PowerPC 601 specific instructions (POWER bridge) */

B
Blue Swirl 已提交
134
target_ulong helper_clcs(CPUPPCState *env, uint32_t arg)
B
Blue Swirl 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
{
    switch (arg) {
    case 0x0CUL:
        /* Instruction cache line size */
        return env->icache_line_size;
        break;
    case 0x0DUL:
        /* Data cache line size */
        return env->dcache_line_size;
        break;
    case 0x0EUL:
        /* Minimum cache line size */
        return (env->icache_line_size < env->dcache_line_size) ?
            env->icache_line_size : env->dcache_line_size;
        break;
    case 0x0FUL:
        /* Maximum cache line size */
        return (env->icache_line_size > env->dcache_line_size) ?
            env->icache_line_size : env->dcache_line_size;
        break;
    default:
        /* Undefined */
        return 0;
        break;
    }
}
161 162 163 164 165 166 167 168 169

/*****************************************************************************/
/* Special registers manipulation */

/* GDBstub can read and write MSR... */
void ppc_store_msr(CPUPPCState *env, target_ulong value)
{
    hreg_store_msr(env, value, 0);
}
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

/* This code is lifted from MacOnLinux. It is called whenever
 * THRM1,2 or 3 is read an fixes up the values in such a way
 * that will make MacOS not hang. These registers exist on some
 * 75x and 74xx processors.
 */
void helper_fixup_thrm(CPUPPCState *env)
{
    target_ulong v, t;
    int i;

#define THRM1_TIN       (1 << 31)
#define THRM1_TIV       (1 << 30)
#define THRM1_THRES(x)  (((x) & 0x7f) << 23)
#define THRM1_TID       (1 << 2)
#define THRM1_TIE       (1 << 1)
#define THRM1_V         (1 << 0)
#define THRM3_E         (1 << 0)

    if (!(env->spr[SPR_THRM3] & THRM3_E)) {
        return;
    }

    /* Note: Thermal interrupts are unimplemented */
    for (i = SPR_THRM1; i <= SPR_THRM2; i++) {
        v = env->spr[i];
        if (!(v & THRM1_V)) {
            continue;
        }
        v |= THRM1_TIV;
        v &= ~THRM1_TIN;
        t = v & THRM1_THRES(127);
        if ((v & THRM1_TID) && t < THRM1_THRES(24)) {
            v |= THRM1_TIN;
        }
        if (!(v & THRM1_TID) && t > THRM1_THRES(24)) {
            v |= THRM1_TIN;
        }
        env->spr[i] = v;
    }
}