Statistics
| Branch: | Revision:

root / target-ppc / excp_helper.c @ 7d08d856

History | View | Annotate | Download (34.2 kB)

1 ad71ed68 Blue Swirl
/*
2 ad71ed68 Blue Swirl
 *  PowerPC exception emulation helpers for QEMU.
3 ad71ed68 Blue Swirl
 *
4 ad71ed68 Blue Swirl
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 ad71ed68 Blue Swirl
 *
6 ad71ed68 Blue Swirl
 * This library is free software; you can redistribute it and/or
7 ad71ed68 Blue Swirl
 * modify it under the terms of the GNU Lesser General Public
8 ad71ed68 Blue Swirl
 * License as published by the Free Software Foundation; either
9 ad71ed68 Blue Swirl
 * version 2 of the License, or (at your option) any later version.
10 ad71ed68 Blue Swirl
 *
11 ad71ed68 Blue Swirl
 * This library is distributed in the hope that it will be useful,
12 ad71ed68 Blue Swirl
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ad71ed68 Blue Swirl
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ad71ed68 Blue Swirl
 * Lesser General Public License for more details.
15 ad71ed68 Blue Swirl
 *
16 ad71ed68 Blue Swirl
 * You should have received a copy of the GNU Lesser General Public
17 ad71ed68 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 ad71ed68 Blue Swirl
 */
19 ad71ed68 Blue Swirl
#include "cpu.h"
20 ad71ed68 Blue Swirl
#include "helper.h"
21 ad71ed68 Blue Swirl
22 ad71ed68 Blue Swirl
#include "helper_regs.h"
23 ad71ed68 Blue Swirl
24 ad71ed68 Blue Swirl
//#define DEBUG_OP
25 ad71ed68 Blue Swirl
//#define DEBUG_EXCEPTIONS
26 ad71ed68 Blue Swirl
27 c79c73f6 Blue Swirl
#ifdef DEBUG_EXCEPTIONS
28 c79c73f6 Blue Swirl
#  define LOG_EXCP(...) qemu_log(__VA_ARGS__)
29 c79c73f6 Blue Swirl
#else
30 c79c73f6 Blue Swirl
#  define LOG_EXCP(...) do { } while (0)
31 c79c73f6 Blue Swirl
#endif
32 c79c73f6 Blue Swirl
33 c79c73f6 Blue Swirl
/*****************************************************************************/
34 c79c73f6 Blue Swirl
/* PowerPC Hypercall emulation */
35 c79c73f6 Blue Swirl
36 1b14670a Andreas Färber
void (*cpu_ppc_hypercall)(PowerPCCPU *);
37 c79c73f6 Blue Swirl
38 c79c73f6 Blue Swirl
/*****************************************************************************/
39 c79c73f6 Blue Swirl
/* Exception processing */
40 c79c73f6 Blue Swirl
#if defined(CONFIG_USER_ONLY)
41 97a8ea5a Andreas Färber
void ppc_cpu_do_interrupt(CPUState *cs)
42 c79c73f6 Blue Swirl
{
43 97a8ea5a Andreas Färber
    PowerPCCPU *cpu = POWERPC_CPU(cs);
44 97a8ea5a Andreas Färber
    CPUPPCState *env = &cpu->env;
45 97a8ea5a Andreas Färber
46 c79c73f6 Blue Swirl
    env->exception_index = POWERPC_EXCP_NONE;
47 c79c73f6 Blue Swirl
    env->error_code = 0;
48 c79c73f6 Blue Swirl
}
49 c79c73f6 Blue Swirl
50 c79c73f6 Blue Swirl
void ppc_hw_interrupt(CPUPPCState *env)
51 c79c73f6 Blue Swirl
{
52 c79c73f6 Blue Swirl
    env->exception_index = POWERPC_EXCP_NONE;
53 c79c73f6 Blue Swirl
    env->error_code = 0;
54 c79c73f6 Blue Swirl
}
55 c79c73f6 Blue Swirl
#else /* defined(CONFIG_USER_ONLY) */
56 c79c73f6 Blue Swirl
static inline void dump_syscall(CPUPPCState *env)
57 c79c73f6 Blue Swirl
{
58 c79c73f6 Blue Swirl
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
59 c79c73f6 Blue Swirl
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
60 c79c73f6 Blue Swirl
                  " nip=" TARGET_FMT_lx "\n",
61 c79c73f6 Blue Swirl
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
62 c79c73f6 Blue Swirl
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
63 c79c73f6 Blue Swirl
                  ppc_dump_gpr(env, 6), env->nip);
64 c79c73f6 Blue Swirl
}
65 c79c73f6 Blue Swirl
66 c79c73f6 Blue Swirl
/* Note that this function should be greatly optimized
67 c79c73f6 Blue Swirl
 * when called with a constant excp, from ppc_hw_interrupt
68 c79c73f6 Blue Swirl
 */
69 5c26a5b3 Andreas Färber
static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
70 c79c73f6 Blue Swirl
{
71 5c26a5b3 Andreas Färber
    CPUPPCState *env = &cpu->env;
72 259186a7 Andreas Färber
    CPUState *cs;
73 c79c73f6 Blue Swirl
    target_ulong msr, new_msr, vector;
74 c79c73f6 Blue Swirl
    int srr0, srr1, asrr0, asrr1;
75 c79c73f6 Blue Swirl
    int lpes0, lpes1, lev;
76 c79c73f6 Blue Swirl
77 c79c73f6 Blue Swirl
    if (0) {
78 c79c73f6 Blue Swirl
        /* XXX: find a suitable condition to enable the hypervisor mode */
79 c79c73f6 Blue Swirl
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
80 c79c73f6 Blue Swirl
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
81 c79c73f6 Blue Swirl
    } else {
82 c79c73f6 Blue Swirl
        /* Those values ensure we won't enter the hypervisor mode */
83 c79c73f6 Blue Swirl
        lpes0 = 0;
84 c79c73f6 Blue Swirl
        lpes1 = 1;
85 c79c73f6 Blue Swirl
    }
86 c79c73f6 Blue Swirl
87 c79c73f6 Blue Swirl
    qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
88 c79c73f6 Blue Swirl
                  " => %08x (%02x)\n", env->nip, excp, env->error_code);
89 c79c73f6 Blue Swirl
90 c79c73f6 Blue Swirl
    /* new srr1 value excluding must-be-zero bits */
91 a1bb7384 Scott Wood
    if (excp_model == POWERPC_EXCP_BOOKE) {
92 a1bb7384 Scott Wood
        msr = env->msr;
93 a1bb7384 Scott Wood
    } else {
94 a1bb7384 Scott Wood
        msr = env->msr & ~0x783f0000ULL;
95 a1bb7384 Scott Wood
    }
96 c79c73f6 Blue Swirl
97 c79c73f6 Blue Swirl
    /* new interrupt handler msr */
98 c79c73f6 Blue Swirl
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
99 c79c73f6 Blue Swirl
100 c79c73f6 Blue Swirl
    /* target registers */
101 c79c73f6 Blue Swirl
    srr0 = SPR_SRR0;
102 c79c73f6 Blue Swirl
    srr1 = SPR_SRR1;
103 c79c73f6 Blue Swirl
    asrr0 = -1;
104 c79c73f6 Blue Swirl
    asrr1 = -1;
105 c79c73f6 Blue Swirl
106 c79c73f6 Blue Swirl
    switch (excp) {
107 c79c73f6 Blue Swirl
    case POWERPC_EXCP_NONE:
108 c79c73f6 Blue Swirl
        /* Should never happen */
109 c79c73f6 Blue Swirl
        return;
110 c79c73f6 Blue Swirl
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
111 c79c73f6 Blue Swirl
        switch (excp_model) {
112 c79c73f6 Blue Swirl
        case POWERPC_EXCP_40x:
113 c79c73f6 Blue Swirl
            srr0 = SPR_40x_SRR2;
114 c79c73f6 Blue Swirl
            srr1 = SPR_40x_SRR3;
115 c79c73f6 Blue Swirl
            break;
116 c79c73f6 Blue Swirl
        case POWERPC_EXCP_BOOKE:
117 c79c73f6 Blue Swirl
            srr0 = SPR_BOOKE_CSRR0;
118 c79c73f6 Blue Swirl
            srr1 = SPR_BOOKE_CSRR1;
119 c79c73f6 Blue Swirl
            break;
120 c79c73f6 Blue Swirl
        case POWERPC_EXCP_G2:
121 c79c73f6 Blue Swirl
            break;
122 c79c73f6 Blue Swirl
        default:
123 c79c73f6 Blue Swirl
            goto excp_invalid;
124 c79c73f6 Blue Swirl
        }
125 c79c73f6 Blue Swirl
        goto store_next;
126 c79c73f6 Blue Swirl
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
127 c79c73f6 Blue Swirl
        if (msr_me == 0) {
128 c79c73f6 Blue Swirl
            /* Machine check exception is not enabled.
129 c79c73f6 Blue Swirl
             * Enter checkstop state.
130 c79c73f6 Blue Swirl
             */
131 c79c73f6 Blue Swirl
            if (qemu_log_enabled()) {
132 c79c73f6 Blue Swirl
                qemu_log("Machine check while not allowed. "
133 c79c73f6 Blue Swirl
                        "Entering checkstop state\n");
134 c79c73f6 Blue Swirl
            } else {
135 c79c73f6 Blue Swirl
                fprintf(stderr, "Machine check while not allowed. "
136 c79c73f6 Blue Swirl
                        "Entering checkstop state\n");
137 c79c73f6 Blue Swirl
            }
138 259186a7 Andreas Färber
            cs = CPU(cpu);
139 259186a7 Andreas Färber
            cs->halted = 1;
140 259186a7 Andreas Färber
            cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
141 c79c73f6 Blue Swirl
        }
142 c79c73f6 Blue Swirl
        if (0) {
143 c79c73f6 Blue Swirl
            /* XXX: find a suitable condition to enable the hypervisor mode */
144 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
145 c79c73f6 Blue Swirl
        }
146 c79c73f6 Blue Swirl
147 c79c73f6 Blue Swirl
        /* machine check exceptions don't have ME set */
148 c79c73f6 Blue Swirl
        new_msr &= ~((target_ulong)1 << MSR_ME);
149 c79c73f6 Blue Swirl
150 c79c73f6 Blue Swirl
        /* XXX: should also have something loaded in DAR / DSISR */
151 c79c73f6 Blue Swirl
        switch (excp_model) {
152 c79c73f6 Blue Swirl
        case POWERPC_EXCP_40x:
153 c79c73f6 Blue Swirl
            srr0 = SPR_40x_SRR2;
154 c79c73f6 Blue Swirl
            srr1 = SPR_40x_SRR3;
155 c79c73f6 Blue Swirl
            break;
156 c79c73f6 Blue Swirl
        case POWERPC_EXCP_BOOKE:
157 a1bb7384 Scott Wood
            /* FIXME: choose one or the other based on CPU type */
158 c79c73f6 Blue Swirl
            srr0 = SPR_BOOKE_MCSRR0;
159 c79c73f6 Blue Swirl
            srr1 = SPR_BOOKE_MCSRR1;
160 c79c73f6 Blue Swirl
            asrr0 = SPR_BOOKE_CSRR0;
161 c79c73f6 Blue Swirl
            asrr1 = SPR_BOOKE_CSRR1;
162 c79c73f6 Blue Swirl
            break;
163 c79c73f6 Blue Swirl
        default:
164 c79c73f6 Blue Swirl
            break;
165 c79c73f6 Blue Swirl
        }
166 c79c73f6 Blue Swirl
        goto store_next;
167 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
168 c79c73f6 Blue Swirl
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
169 c79c73f6 Blue Swirl
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
170 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
171 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
172 c79c73f6 Blue Swirl
        }
173 c79c73f6 Blue Swirl
        goto store_next;
174 c79c73f6 Blue Swirl
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
175 c79c73f6 Blue Swirl
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
176 c79c73f6 Blue Swirl
                 "\n", msr, env->nip);
177 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
178 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
179 c79c73f6 Blue Swirl
        }
180 c79c73f6 Blue Swirl
        msr |= env->error_code;
181 c79c73f6 Blue Swirl
        goto store_next;
182 c79c73f6 Blue Swirl
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
183 c79c73f6 Blue Swirl
        if (lpes0 == 1) {
184 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
185 c79c73f6 Blue Swirl
        }
186 68c2dd70 Alexander Graf
        if (env->mpic_proxy) {
187 68c2dd70 Alexander Graf
            /* IACK the IRQ on delivery */
188 68c2dd70 Alexander Graf
            env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
189 68c2dd70 Alexander Graf
        }
190 c79c73f6 Blue Swirl
        goto store_next;
191 c79c73f6 Blue Swirl
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
192 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
193 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
194 c79c73f6 Blue Swirl
        }
195 c79c73f6 Blue Swirl
        /* XXX: this is false */
196 c79c73f6 Blue Swirl
        /* Get rS/rD and rA from faulting opcode */
197 2f5a189c Blue Swirl
        env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
198 2f5a189c Blue Swirl
                                & 0x03FF0000) >> 16;
199 c79c73f6 Blue Swirl
        goto store_current;
200 c79c73f6 Blue Swirl
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
201 c79c73f6 Blue Swirl
        switch (env->error_code & ~0xF) {
202 c79c73f6 Blue Swirl
        case POWERPC_EXCP_FP:
203 c79c73f6 Blue Swirl
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
204 c79c73f6 Blue Swirl
                LOG_EXCP("Ignore floating point exception\n");
205 c79c73f6 Blue Swirl
                env->exception_index = POWERPC_EXCP_NONE;
206 c79c73f6 Blue Swirl
                env->error_code = 0;
207 c79c73f6 Blue Swirl
                return;
208 c79c73f6 Blue Swirl
            }
209 c79c73f6 Blue Swirl
            if (lpes1 == 0) {
210 c79c73f6 Blue Swirl
                new_msr |= (target_ulong)MSR_HVB;
211 c79c73f6 Blue Swirl
            }
212 c79c73f6 Blue Swirl
            msr |= 0x00100000;
213 c79c73f6 Blue Swirl
            if (msr_fe0 == msr_fe1) {
214 c79c73f6 Blue Swirl
                goto store_next;
215 c79c73f6 Blue Swirl
            }
216 c79c73f6 Blue Swirl
            msr |= 0x00010000;
217 c79c73f6 Blue Swirl
            break;
218 c79c73f6 Blue Swirl
        case POWERPC_EXCP_INVAL:
219 c79c73f6 Blue Swirl
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
220 c79c73f6 Blue Swirl
            if (lpes1 == 0) {
221 c79c73f6 Blue Swirl
                new_msr |= (target_ulong)MSR_HVB;
222 c79c73f6 Blue Swirl
            }
223 c79c73f6 Blue Swirl
            msr |= 0x00080000;
224 c79c73f6 Blue Swirl
            env->spr[SPR_BOOKE_ESR] = ESR_PIL;
225 c79c73f6 Blue Swirl
            break;
226 c79c73f6 Blue Swirl
        case POWERPC_EXCP_PRIV:
227 c79c73f6 Blue Swirl
            if (lpes1 == 0) {
228 c79c73f6 Blue Swirl
                new_msr |= (target_ulong)MSR_HVB;
229 c79c73f6 Blue Swirl
            }
230 c79c73f6 Blue Swirl
            msr |= 0x00040000;
231 c79c73f6 Blue Swirl
            env->spr[SPR_BOOKE_ESR] = ESR_PPR;
232 c79c73f6 Blue Swirl
            break;
233 c79c73f6 Blue Swirl
        case POWERPC_EXCP_TRAP:
234 c79c73f6 Blue Swirl
            if (lpes1 == 0) {
235 c79c73f6 Blue Swirl
                new_msr |= (target_ulong)MSR_HVB;
236 c79c73f6 Blue Swirl
            }
237 c79c73f6 Blue Swirl
            msr |= 0x00020000;
238 c79c73f6 Blue Swirl
            env->spr[SPR_BOOKE_ESR] = ESR_PTR;
239 c79c73f6 Blue Swirl
            break;
240 c79c73f6 Blue Swirl
        default:
241 c79c73f6 Blue Swirl
            /* Should never occur */
242 c79c73f6 Blue Swirl
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
243 c79c73f6 Blue Swirl
                      env->error_code);
244 c79c73f6 Blue Swirl
            break;
245 c79c73f6 Blue Swirl
        }
246 c79c73f6 Blue Swirl
        goto store_current;
247 c79c73f6 Blue Swirl
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
248 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
249 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
250 c79c73f6 Blue Swirl
        }
251 c79c73f6 Blue Swirl
        goto store_current;
252 c79c73f6 Blue Swirl
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
253 c79c73f6 Blue Swirl
        dump_syscall(env);
254 c79c73f6 Blue Swirl
        lev = env->error_code;
255 c79c73f6 Blue Swirl
        if ((lev == 1) && cpu_ppc_hypercall) {
256 1b14670a Andreas Färber
            cpu_ppc_hypercall(cpu);
257 c79c73f6 Blue Swirl
            return;
258 c79c73f6 Blue Swirl
        }
259 c79c73f6 Blue Swirl
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
260 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
261 c79c73f6 Blue Swirl
        }
262 c79c73f6 Blue Swirl
        goto store_next;
263 c79c73f6 Blue Swirl
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
264 c79c73f6 Blue Swirl
        goto store_current;
265 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
266 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
267 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
268 c79c73f6 Blue Swirl
        }
269 c79c73f6 Blue Swirl
        goto store_next;
270 c79c73f6 Blue Swirl
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
271 c79c73f6 Blue Swirl
        /* FIT on 4xx */
272 c79c73f6 Blue Swirl
        LOG_EXCP("FIT exception\n");
273 c79c73f6 Blue Swirl
        goto store_next;
274 c79c73f6 Blue Swirl
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
275 c79c73f6 Blue Swirl
        LOG_EXCP("WDT exception\n");
276 c79c73f6 Blue Swirl
        switch (excp_model) {
277 c79c73f6 Blue Swirl
        case POWERPC_EXCP_BOOKE:
278 c79c73f6 Blue Swirl
            srr0 = SPR_BOOKE_CSRR0;
279 c79c73f6 Blue Swirl
            srr1 = SPR_BOOKE_CSRR1;
280 c79c73f6 Blue Swirl
            break;
281 c79c73f6 Blue Swirl
        default:
282 c79c73f6 Blue Swirl
            break;
283 c79c73f6 Blue Swirl
        }
284 c79c73f6 Blue Swirl
        goto store_next;
285 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
286 c79c73f6 Blue Swirl
        goto store_next;
287 c79c73f6 Blue Swirl
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
288 c79c73f6 Blue Swirl
        goto store_next;
289 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
290 c79c73f6 Blue Swirl
        switch (excp_model) {
291 c79c73f6 Blue Swirl
        case POWERPC_EXCP_BOOKE:
292 a1bb7384 Scott Wood
            /* FIXME: choose one or the other based on CPU type */
293 c79c73f6 Blue Swirl
            srr0 = SPR_BOOKE_DSRR0;
294 c79c73f6 Blue Swirl
            srr1 = SPR_BOOKE_DSRR1;
295 c79c73f6 Blue Swirl
            asrr0 = SPR_BOOKE_CSRR0;
296 c79c73f6 Blue Swirl
            asrr1 = SPR_BOOKE_CSRR1;
297 c79c73f6 Blue Swirl
            break;
298 c79c73f6 Blue Swirl
        default:
299 c79c73f6 Blue Swirl
            break;
300 c79c73f6 Blue Swirl
        }
301 c79c73f6 Blue Swirl
        /* XXX: TODO */
302 c79c73f6 Blue Swirl
        cpu_abort(env, "Debug exception is not implemented yet !\n");
303 c79c73f6 Blue Swirl
        goto store_next;
304 c79c73f6 Blue Swirl
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
305 c79c73f6 Blue Swirl
        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
306 c79c73f6 Blue Swirl
        goto store_current;
307 c79c73f6 Blue Swirl
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
308 c79c73f6 Blue Swirl
        /* XXX: TODO */
309 c79c73f6 Blue Swirl
        cpu_abort(env, "Embedded floating point data exception "
310 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
311 c79c73f6 Blue Swirl
        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
312 c79c73f6 Blue Swirl
        goto store_next;
313 c79c73f6 Blue Swirl
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
314 c79c73f6 Blue Swirl
        /* XXX: TODO */
315 c79c73f6 Blue Swirl
        cpu_abort(env, "Embedded floating point round exception "
316 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
317 c79c73f6 Blue Swirl
        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
318 c79c73f6 Blue Swirl
        goto store_next;
319 c79c73f6 Blue Swirl
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
320 c79c73f6 Blue Swirl
        /* XXX: TODO */
321 c79c73f6 Blue Swirl
        cpu_abort(env,
322 c79c73f6 Blue Swirl
                  "Performance counter exception is not implemented yet !\n");
323 c79c73f6 Blue Swirl
        goto store_next;
324 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
325 c79c73f6 Blue Swirl
        goto store_next;
326 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
327 c79c73f6 Blue Swirl
        srr0 = SPR_BOOKE_CSRR0;
328 c79c73f6 Blue Swirl
        srr1 = SPR_BOOKE_CSRR1;
329 c79c73f6 Blue Swirl
        goto store_next;
330 c79c73f6 Blue Swirl
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
331 c79c73f6 Blue Swirl
        if (msr_pow) {
332 c79c73f6 Blue Swirl
            /* indicate that we resumed from power save mode */
333 c79c73f6 Blue Swirl
            msr |= 0x10000;
334 c79c73f6 Blue Swirl
        } else {
335 c79c73f6 Blue Swirl
            new_msr &= ~((target_ulong)1 << MSR_ME);
336 c79c73f6 Blue Swirl
        }
337 c79c73f6 Blue Swirl
338 c79c73f6 Blue Swirl
        if (0) {
339 c79c73f6 Blue Swirl
            /* XXX: find a suitable condition to enable the hypervisor mode */
340 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
341 c79c73f6 Blue Swirl
        }
342 c79c73f6 Blue Swirl
        goto store_next;
343 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
344 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
345 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
346 c79c73f6 Blue Swirl
        }
347 c79c73f6 Blue Swirl
        goto store_next;
348 c79c73f6 Blue Swirl
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
349 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
350 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
351 c79c73f6 Blue Swirl
        }
352 c79c73f6 Blue Swirl
        goto store_next;
353 c79c73f6 Blue Swirl
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
354 c79c73f6 Blue Swirl
        srr0 = SPR_HSRR0;
355 c79c73f6 Blue Swirl
        srr1 = SPR_HSRR1;
356 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)MSR_HVB;
357 c79c73f6 Blue Swirl
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
358 c79c73f6 Blue Swirl
        goto store_next;
359 c79c73f6 Blue Swirl
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
360 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
361 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
362 c79c73f6 Blue Swirl
        }
363 c79c73f6 Blue Swirl
        goto store_next;
364 c79c73f6 Blue Swirl
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
365 c79c73f6 Blue Swirl
        srr0 = SPR_HSRR0;
366 c79c73f6 Blue Swirl
        srr1 = SPR_HSRR1;
367 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)MSR_HVB;
368 c79c73f6 Blue Swirl
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
369 c79c73f6 Blue Swirl
        goto store_next;
370 c79c73f6 Blue Swirl
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
371 c79c73f6 Blue Swirl
        srr0 = SPR_HSRR0;
372 c79c73f6 Blue Swirl
        srr1 = SPR_HSRR1;
373 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)MSR_HVB;
374 c79c73f6 Blue Swirl
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
375 c79c73f6 Blue Swirl
        goto store_next;
376 c79c73f6 Blue Swirl
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
377 c79c73f6 Blue Swirl
        srr0 = SPR_HSRR0;
378 c79c73f6 Blue Swirl
        srr1 = SPR_HSRR1;
379 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)MSR_HVB;
380 c79c73f6 Blue Swirl
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
381 c79c73f6 Blue Swirl
        goto store_next;
382 c79c73f6 Blue Swirl
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
383 c79c73f6 Blue Swirl
        srr0 = SPR_HSRR0;
384 c79c73f6 Blue Swirl
        srr1 = SPR_HSRR1;
385 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)MSR_HVB;
386 c79c73f6 Blue Swirl
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
387 c79c73f6 Blue Swirl
        goto store_next;
388 c79c73f6 Blue Swirl
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
389 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
390 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
391 c79c73f6 Blue Swirl
        }
392 c79c73f6 Blue Swirl
        goto store_current;
393 c79c73f6 Blue Swirl
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
394 c79c73f6 Blue Swirl
        LOG_EXCP("PIT exception\n");
395 c79c73f6 Blue Swirl
        goto store_next;
396 c79c73f6 Blue Swirl
    case POWERPC_EXCP_IO:        /* IO error exception                       */
397 c79c73f6 Blue Swirl
        /* XXX: TODO */
398 c79c73f6 Blue Swirl
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
399 c79c73f6 Blue Swirl
        goto store_next;
400 c79c73f6 Blue Swirl
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
401 c79c73f6 Blue Swirl
        /* XXX: TODO */
402 c79c73f6 Blue Swirl
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
403 c79c73f6 Blue Swirl
        goto store_next;
404 c79c73f6 Blue Swirl
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
405 c79c73f6 Blue Swirl
        /* XXX: TODO */
406 c79c73f6 Blue Swirl
        cpu_abort(env, "602 emulation trap exception "
407 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
408 c79c73f6 Blue Swirl
        goto store_next;
409 c79c73f6 Blue Swirl
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
410 c79c73f6 Blue Swirl
        if (lpes1 == 0) { /* XXX: check this */
411 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
412 c79c73f6 Blue Swirl
        }
413 c79c73f6 Blue Swirl
        switch (excp_model) {
414 c79c73f6 Blue Swirl
        case POWERPC_EXCP_602:
415 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603:
416 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603E:
417 c79c73f6 Blue Swirl
        case POWERPC_EXCP_G2:
418 c79c73f6 Blue Swirl
            goto tlb_miss_tgpr;
419 c79c73f6 Blue Swirl
        case POWERPC_EXCP_7x5:
420 c79c73f6 Blue Swirl
            goto tlb_miss;
421 c79c73f6 Blue Swirl
        case POWERPC_EXCP_74xx:
422 c79c73f6 Blue Swirl
            goto tlb_miss_74xx;
423 c79c73f6 Blue Swirl
        default:
424 c79c73f6 Blue Swirl
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
425 c79c73f6 Blue Swirl
            break;
426 c79c73f6 Blue Swirl
        }
427 c79c73f6 Blue Swirl
        break;
428 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
429 c79c73f6 Blue Swirl
        if (lpes1 == 0) { /* XXX: check this */
430 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
431 c79c73f6 Blue Swirl
        }
432 c79c73f6 Blue Swirl
        switch (excp_model) {
433 c79c73f6 Blue Swirl
        case POWERPC_EXCP_602:
434 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603:
435 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603E:
436 c79c73f6 Blue Swirl
        case POWERPC_EXCP_G2:
437 c79c73f6 Blue Swirl
            goto tlb_miss_tgpr;
438 c79c73f6 Blue Swirl
        case POWERPC_EXCP_7x5:
439 c79c73f6 Blue Swirl
            goto tlb_miss;
440 c79c73f6 Blue Swirl
        case POWERPC_EXCP_74xx:
441 c79c73f6 Blue Swirl
            goto tlb_miss_74xx;
442 c79c73f6 Blue Swirl
        default:
443 c79c73f6 Blue Swirl
            cpu_abort(env, "Invalid data load TLB miss exception\n");
444 c79c73f6 Blue Swirl
            break;
445 c79c73f6 Blue Swirl
        }
446 c79c73f6 Blue Swirl
        break;
447 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
448 c79c73f6 Blue Swirl
        if (lpes1 == 0) { /* XXX: check this */
449 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
450 c79c73f6 Blue Swirl
        }
451 c79c73f6 Blue Swirl
        switch (excp_model) {
452 c79c73f6 Blue Swirl
        case POWERPC_EXCP_602:
453 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603:
454 c79c73f6 Blue Swirl
        case POWERPC_EXCP_603E:
455 c79c73f6 Blue Swirl
        case POWERPC_EXCP_G2:
456 c79c73f6 Blue Swirl
        tlb_miss_tgpr:
457 c79c73f6 Blue Swirl
            /* Swap temporary saved registers with GPRs */
458 c79c73f6 Blue Swirl
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
459 c79c73f6 Blue Swirl
                new_msr |= (target_ulong)1 << MSR_TGPR;
460 c79c73f6 Blue Swirl
                hreg_swap_gpr_tgpr(env);
461 c79c73f6 Blue Swirl
            }
462 c79c73f6 Blue Swirl
            goto tlb_miss;
463 c79c73f6 Blue Swirl
        case POWERPC_EXCP_7x5:
464 c79c73f6 Blue Swirl
        tlb_miss:
465 c79c73f6 Blue Swirl
#if defined(DEBUG_SOFTWARE_TLB)
466 c79c73f6 Blue Swirl
            if (qemu_log_enabled()) {
467 c79c73f6 Blue Swirl
                const char *es;
468 c79c73f6 Blue Swirl
                target_ulong *miss, *cmp;
469 c79c73f6 Blue Swirl
                int en;
470 c79c73f6 Blue Swirl
471 c79c73f6 Blue Swirl
                if (excp == POWERPC_EXCP_IFTLB) {
472 c79c73f6 Blue Swirl
                    es = "I";
473 c79c73f6 Blue Swirl
                    en = 'I';
474 c79c73f6 Blue Swirl
                    miss = &env->spr[SPR_IMISS];
475 c79c73f6 Blue Swirl
                    cmp = &env->spr[SPR_ICMP];
476 c79c73f6 Blue Swirl
                } else {
477 c79c73f6 Blue Swirl
                    if (excp == POWERPC_EXCP_DLTLB) {
478 c79c73f6 Blue Swirl
                        es = "DL";
479 c79c73f6 Blue Swirl
                    } else {
480 c79c73f6 Blue Swirl
                        es = "DS";
481 c79c73f6 Blue Swirl
                    }
482 c79c73f6 Blue Swirl
                    en = 'D';
483 c79c73f6 Blue Swirl
                    miss = &env->spr[SPR_DMISS];
484 c79c73f6 Blue Swirl
                    cmp = &env->spr[SPR_DCMP];
485 c79c73f6 Blue Swirl
                }
486 c79c73f6 Blue Swirl
                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
487 c79c73f6 Blue Swirl
                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
488 c79c73f6 Blue Swirl
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
489 c79c73f6 Blue Swirl
                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
490 c79c73f6 Blue Swirl
                         env->error_code);
491 c79c73f6 Blue Swirl
            }
492 c79c73f6 Blue Swirl
#endif
493 c79c73f6 Blue Swirl
            msr |= env->crf[0] << 28;
494 c79c73f6 Blue Swirl
            msr |= env->error_code; /* key, D/I, S/L bits */
495 c79c73f6 Blue Swirl
            /* Set way using a LRU mechanism */
496 c79c73f6 Blue Swirl
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
497 c79c73f6 Blue Swirl
            break;
498 c79c73f6 Blue Swirl
        case POWERPC_EXCP_74xx:
499 c79c73f6 Blue Swirl
        tlb_miss_74xx:
500 c79c73f6 Blue Swirl
#if defined(DEBUG_SOFTWARE_TLB)
501 c79c73f6 Blue Swirl
            if (qemu_log_enabled()) {
502 c79c73f6 Blue Swirl
                const char *es;
503 c79c73f6 Blue Swirl
                target_ulong *miss, *cmp;
504 c79c73f6 Blue Swirl
                int en;
505 c79c73f6 Blue Swirl
506 c79c73f6 Blue Swirl
                if (excp == POWERPC_EXCP_IFTLB) {
507 c79c73f6 Blue Swirl
                    es = "I";
508 c79c73f6 Blue Swirl
                    en = 'I';
509 c79c73f6 Blue Swirl
                    miss = &env->spr[SPR_TLBMISS];
510 c79c73f6 Blue Swirl
                    cmp = &env->spr[SPR_PTEHI];
511 c79c73f6 Blue Swirl
                } else {
512 c79c73f6 Blue Swirl
                    if (excp == POWERPC_EXCP_DLTLB) {
513 c79c73f6 Blue Swirl
                        es = "DL";
514 c79c73f6 Blue Swirl
                    } else {
515 c79c73f6 Blue Swirl
                        es = "DS";
516 c79c73f6 Blue Swirl
                    }
517 c79c73f6 Blue Swirl
                    en = 'D';
518 c79c73f6 Blue Swirl
                    miss = &env->spr[SPR_TLBMISS];
519 c79c73f6 Blue Swirl
                    cmp = &env->spr[SPR_PTEHI];
520 c79c73f6 Blue Swirl
                }
521 c79c73f6 Blue Swirl
                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
522 c79c73f6 Blue Swirl
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
523 c79c73f6 Blue Swirl
                         env->error_code);
524 c79c73f6 Blue Swirl
            }
525 c79c73f6 Blue Swirl
#endif
526 c79c73f6 Blue Swirl
            msr |= env->error_code; /* key bit */
527 c79c73f6 Blue Swirl
            break;
528 c79c73f6 Blue Swirl
        default:
529 c79c73f6 Blue Swirl
            cpu_abort(env, "Invalid data store TLB miss exception\n");
530 c79c73f6 Blue Swirl
            break;
531 c79c73f6 Blue Swirl
        }
532 c79c73f6 Blue Swirl
        goto store_next;
533 c79c73f6 Blue Swirl
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
534 c79c73f6 Blue Swirl
        /* XXX: TODO */
535 c79c73f6 Blue Swirl
        cpu_abort(env, "Floating point assist exception "
536 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
537 c79c73f6 Blue Swirl
        goto store_next;
538 c79c73f6 Blue Swirl
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
539 c79c73f6 Blue Swirl
        /* XXX: TODO */
540 c79c73f6 Blue Swirl
        cpu_abort(env, "DABR exception is not implemented yet !\n");
541 c79c73f6 Blue Swirl
        goto store_next;
542 c79c73f6 Blue Swirl
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
543 c79c73f6 Blue Swirl
        /* XXX: TODO */
544 c79c73f6 Blue Swirl
        cpu_abort(env, "IABR exception is not implemented yet !\n");
545 c79c73f6 Blue Swirl
        goto store_next;
546 c79c73f6 Blue Swirl
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
547 c79c73f6 Blue Swirl
        /* XXX: TODO */
548 c79c73f6 Blue Swirl
        cpu_abort(env, "SMI exception is not implemented yet !\n");
549 c79c73f6 Blue Swirl
        goto store_next;
550 c79c73f6 Blue Swirl
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
551 c79c73f6 Blue Swirl
        /* XXX: TODO */
552 c79c73f6 Blue Swirl
        cpu_abort(env, "Thermal management exception "
553 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
554 c79c73f6 Blue Swirl
        goto store_next;
555 c79c73f6 Blue Swirl
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
556 c79c73f6 Blue Swirl
        if (lpes1 == 0) {
557 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)MSR_HVB;
558 c79c73f6 Blue Swirl
        }
559 c79c73f6 Blue Swirl
        /* XXX: TODO */
560 c79c73f6 Blue Swirl
        cpu_abort(env,
561 c79c73f6 Blue Swirl
                  "Performance counter exception is not implemented yet !\n");
562 c79c73f6 Blue Swirl
        goto store_next;
563 c79c73f6 Blue Swirl
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
564 c79c73f6 Blue Swirl
        /* XXX: TODO */
565 c79c73f6 Blue Swirl
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
566 c79c73f6 Blue Swirl
        goto store_next;
567 c79c73f6 Blue Swirl
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
568 c79c73f6 Blue Swirl
        /* XXX: TODO */
569 c79c73f6 Blue Swirl
        cpu_abort(env,
570 c79c73f6 Blue Swirl
                  "970 soft-patch exception is not implemented yet !\n");
571 c79c73f6 Blue Swirl
        goto store_next;
572 c79c73f6 Blue Swirl
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
573 c79c73f6 Blue Swirl
        /* XXX: TODO */
574 c79c73f6 Blue Swirl
        cpu_abort(env,
575 c79c73f6 Blue Swirl
                  "970 maintenance exception is not implemented yet !\n");
576 c79c73f6 Blue Swirl
        goto store_next;
577 c79c73f6 Blue Swirl
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
578 c79c73f6 Blue Swirl
        /* XXX: TODO */
579 c79c73f6 Blue Swirl
        cpu_abort(env, "Maskable external exception "
580 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
581 c79c73f6 Blue Swirl
        goto store_next;
582 c79c73f6 Blue Swirl
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
583 c79c73f6 Blue Swirl
        /* XXX: TODO */
584 c79c73f6 Blue Swirl
        cpu_abort(env, "Non maskable external exception "
585 c79c73f6 Blue Swirl
                  "is not implemented yet !\n");
586 c79c73f6 Blue Swirl
        goto store_next;
587 c79c73f6 Blue Swirl
    default:
588 c79c73f6 Blue Swirl
    excp_invalid:
589 c79c73f6 Blue Swirl
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
590 c79c73f6 Blue Swirl
        break;
591 c79c73f6 Blue Swirl
    store_current:
592 c79c73f6 Blue Swirl
        /* save current instruction location */
593 c79c73f6 Blue Swirl
        env->spr[srr0] = env->nip - 4;
594 c79c73f6 Blue Swirl
        break;
595 c79c73f6 Blue Swirl
    store_next:
596 c79c73f6 Blue Swirl
        /* save next instruction location */
597 c79c73f6 Blue Swirl
        env->spr[srr0] = env->nip;
598 c79c73f6 Blue Swirl
        break;
599 c79c73f6 Blue Swirl
    }
600 c79c73f6 Blue Swirl
    /* Save MSR */
601 c79c73f6 Blue Swirl
    env->spr[srr1] = msr;
602 c79c73f6 Blue Swirl
    /* If any alternate SRR register are defined, duplicate saved values */
603 c79c73f6 Blue Swirl
    if (asrr0 != -1) {
604 c79c73f6 Blue Swirl
        env->spr[asrr0] = env->spr[srr0];
605 c79c73f6 Blue Swirl
    }
606 c79c73f6 Blue Swirl
    if (asrr1 != -1) {
607 c79c73f6 Blue Swirl
        env->spr[asrr1] = env->spr[srr1];
608 c79c73f6 Blue Swirl
    }
609 c79c73f6 Blue Swirl
    /* If we disactivated any translation, flush TLBs */
610 c79c73f6 Blue Swirl
    if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
611 c79c73f6 Blue Swirl
        tlb_flush(env, 1);
612 c79c73f6 Blue Swirl
    }
613 c79c73f6 Blue Swirl
614 c79c73f6 Blue Swirl
    if (msr_ile) {
615 c79c73f6 Blue Swirl
        new_msr |= (target_ulong)1 << MSR_LE;
616 c79c73f6 Blue Swirl
    }
617 c79c73f6 Blue Swirl
618 c79c73f6 Blue Swirl
    /* Jump to handler */
619 c79c73f6 Blue Swirl
    vector = env->excp_vectors[excp];
620 c79c73f6 Blue Swirl
    if (vector == (target_ulong)-1ULL) {
621 c79c73f6 Blue Swirl
        cpu_abort(env, "Raised an exception without defined vector %d\n",
622 c79c73f6 Blue Swirl
                  excp);
623 c79c73f6 Blue Swirl
    }
624 c79c73f6 Blue Swirl
    vector |= env->excp_prefix;
625 c79c73f6 Blue Swirl
#if defined(TARGET_PPC64)
626 c79c73f6 Blue Swirl
    if (excp_model == POWERPC_EXCP_BOOKE) {
627 e42a61f1 Alexander Graf
        if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
628 e42a61f1 Alexander Graf
            /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
629 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)1 << MSR_CM;
630 e42a61f1 Alexander Graf
        } else {
631 e42a61f1 Alexander Graf
            vector = (uint32_t)vector;
632 c79c73f6 Blue Swirl
        }
633 c79c73f6 Blue Swirl
    } else {
634 c79c73f6 Blue Swirl
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
635 c79c73f6 Blue Swirl
            vector = (uint32_t)vector;
636 c79c73f6 Blue Swirl
        } else {
637 c79c73f6 Blue Swirl
            new_msr |= (target_ulong)1 << MSR_SF;
638 c79c73f6 Blue Swirl
        }
639 c79c73f6 Blue Swirl
    }
640 c79c73f6 Blue Swirl
#endif
641 c79c73f6 Blue Swirl
    /* XXX: we don't use hreg_store_msr here as already have treated
642 c79c73f6 Blue Swirl
     *      any special case that could occur. Just store MSR and update hflags
643 c79c73f6 Blue Swirl
     */
644 c79c73f6 Blue Swirl
    env->msr = new_msr & env->msr_mask;
645 c79c73f6 Blue Swirl
    hreg_compute_hflags(env);
646 c79c73f6 Blue Swirl
    env->nip = vector;
647 c79c73f6 Blue Swirl
    /* Reset exception state */
648 c79c73f6 Blue Swirl
    env->exception_index = POWERPC_EXCP_NONE;
649 c79c73f6 Blue Swirl
    env->error_code = 0;
650 c79c73f6 Blue Swirl
651 c79c73f6 Blue Swirl
    if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
652 c79c73f6 Blue Swirl
        (env->mmu_model == POWERPC_MMU_BOOKE206)) {
653 c79c73f6 Blue Swirl
        /* XXX: The BookE changes address space when switching modes,
654 c79c73f6 Blue Swirl
                we should probably implement that as different MMU indexes,
655 c79c73f6 Blue Swirl
                but for the moment we do it the slow way and flush all.  */
656 c79c73f6 Blue Swirl
        tlb_flush(env, 1);
657 c79c73f6 Blue Swirl
    }
658 c79c73f6 Blue Swirl
}
659 c79c73f6 Blue Swirl
660 97a8ea5a Andreas Färber
void ppc_cpu_do_interrupt(CPUState *cs)
661 c79c73f6 Blue Swirl
{
662 97a8ea5a Andreas Färber
    PowerPCCPU *cpu = POWERPC_CPU(cs);
663 97a8ea5a Andreas Färber
    CPUPPCState *env = &cpu->env;
664 5c26a5b3 Andreas Färber
665 5c26a5b3 Andreas Färber
    powerpc_excp(cpu, env->excp_model, env->exception_index);
666 c79c73f6 Blue Swirl
}
667 c79c73f6 Blue Swirl
668 c79c73f6 Blue Swirl
void ppc_hw_interrupt(CPUPPCState *env)
669 c79c73f6 Blue Swirl
{
670 5c26a5b3 Andreas Färber
    PowerPCCPU *cpu = ppc_env_get_cpu(env);
671 c79c73f6 Blue Swirl
    int hdice;
672 c79c73f6 Blue Swirl
#if 0
673 259186a7 Andreas Färber
    CPUState *cs = CPU(cpu);
674 259186a7 Andreas Färber

675 c79c73f6 Blue Swirl
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
676 259186a7 Andreas Färber
                  __func__, env, env->pending_interrupts,
677 259186a7 Andreas Färber
                  cs->interrupt_request, (int)msr_me, (int)msr_ee);
678 c79c73f6 Blue Swirl
#endif
679 c79c73f6 Blue Swirl
    /* External reset */
680 c79c73f6 Blue Swirl
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
681 c79c73f6 Blue Swirl
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
682 5c26a5b3 Andreas Färber
        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
683 c79c73f6 Blue Swirl
        return;
684 c79c73f6 Blue Swirl
    }
685 c79c73f6 Blue Swirl
    /* Machine check exception */
686 c79c73f6 Blue Swirl
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
687 c79c73f6 Blue Swirl
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
688 5c26a5b3 Andreas Färber
        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
689 c79c73f6 Blue Swirl
        return;
690 c79c73f6 Blue Swirl
    }
691 c79c73f6 Blue Swirl
#if 0 /* TODO */
692 c79c73f6 Blue Swirl
    /* External debug exception */
693 c79c73f6 Blue Swirl
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
694 c79c73f6 Blue Swirl
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
695 5c26a5b3 Andreas Färber
        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
696 c79c73f6 Blue Swirl
        return;
697 c79c73f6 Blue Swirl
    }
698 c79c73f6 Blue Swirl
#endif
699 c79c73f6 Blue Swirl
    if (0) {
700 c79c73f6 Blue Swirl
        /* XXX: find a suitable condition to enable the hypervisor mode */
701 c79c73f6 Blue Swirl
        hdice = env->spr[SPR_LPCR] & 1;
702 c79c73f6 Blue Swirl
    } else {
703 c79c73f6 Blue Swirl
        hdice = 0;
704 c79c73f6 Blue Swirl
    }
705 c79c73f6 Blue Swirl
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
706 c79c73f6 Blue Swirl
        /* Hypervisor decrementer exception */
707 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
708 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
709 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
710 c79c73f6 Blue Swirl
            return;
711 c79c73f6 Blue Swirl
        }
712 c79c73f6 Blue Swirl
    }
713 c79c73f6 Blue Swirl
    if (msr_ce != 0) {
714 c79c73f6 Blue Swirl
        /* External critical interrupt */
715 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
716 c79c73f6 Blue Swirl
            /* Taking a critical external interrupt does not clear the external
717 c79c73f6 Blue Swirl
             * critical interrupt status
718 c79c73f6 Blue Swirl
             */
719 c79c73f6 Blue Swirl
#if 0
720 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
721 c79c73f6 Blue Swirl
#endif
722 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
723 c79c73f6 Blue Swirl
            return;
724 c79c73f6 Blue Swirl
        }
725 c79c73f6 Blue Swirl
    }
726 c79c73f6 Blue Swirl
    if (msr_ee != 0) {
727 c79c73f6 Blue Swirl
        /* Watchdog timer on embedded PowerPC */
728 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
729 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
730 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
731 c79c73f6 Blue Swirl
            return;
732 c79c73f6 Blue Swirl
        }
733 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
734 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
735 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
736 c79c73f6 Blue Swirl
            return;
737 c79c73f6 Blue Swirl
        }
738 c79c73f6 Blue Swirl
        /* Fixed interval timer on embedded PowerPC */
739 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
740 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
741 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
742 c79c73f6 Blue Swirl
            return;
743 c79c73f6 Blue Swirl
        }
744 c79c73f6 Blue Swirl
        /* Programmable interval timer on embedded PowerPC */
745 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
746 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
747 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
748 c79c73f6 Blue Swirl
            return;
749 c79c73f6 Blue Swirl
        }
750 c79c73f6 Blue Swirl
        /* Decrementer exception */
751 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
752 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
753 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
754 c79c73f6 Blue Swirl
            return;
755 c79c73f6 Blue Swirl
        }
756 c79c73f6 Blue Swirl
        /* External interrupt */
757 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
758 c79c73f6 Blue Swirl
            /* Taking an external interrupt does not clear the external
759 c79c73f6 Blue Swirl
             * interrupt status
760 c79c73f6 Blue Swirl
             */
761 c79c73f6 Blue Swirl
#if 0
762 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
763 c79c73f6 Blue Swirl
#endif
764 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
765 c79c73f6 Blue Swirl
            return;
766 c79c73f6 Blue Swirl
        }
767 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
768 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
769 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
770 c79c73f6 Blue Swirl
            return;
771 c79c73f6 Blue Swirl
        }
772 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
773 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
774 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
775 c79c73f6 Blue Swirl
            return;
776 c79c73f6 Blue Swirl
        }
777 c79c73f6 Blue Swirl
        /* Thermal interrupt */
778 c79c73f6 Blue Swirl
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
779 c79c73f6 Blue Swirl
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
780 5c26a5b3 Andreas Färber
            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
781 c79c73f6 Blue Swirl
            return;
782 c79c73f6 Blue Swirl
        }
783 c79c73f6 Blue Swirl
    }
784 c79c73f6 Blue Swirl
}
785 c79c73f6 Blue Swirl
#endif /* !CONFIG_USER_ONLY */
786 c79c73f6 Blue Swirl
787 c79c73f6 Blue Swirl
#if defined(DEBUG_OP)
788 c79c73f6 Blue Swirl
static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
789 c79c73f6 Blue Swirl
{
790 c79c73f6 Blue Swirl
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
791 c79c73f6 Blue Swirl
             TARGET_FMT_lx "\n", RA, msr);
792 c79c73f6 Blue Swirl
}
793 c79c73f6 Blue Swirl
#endif
794 c79c73f6 Blue Swirl
795 ad71ed68 Blue Swirl
/*****************************************************************************/
796 ad71ed68 Blue Swirl
/* Exceptions processing helpers */
797 ad71ed68 Blue Swirl
798 e5f17ac6 Blue Swirl
void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
799 e5f17ac6 Blue Swirl
                                uint32_t error_code)
800 ad71ed68 Blue Swirl
{
801 ad71ed68 Blue Swirl
#if 0
802 ad71ed68 Blue Swirl
    printf("Raise exception %3x code : %d\n", exception, error_code);
803 ad71ed68 Blue Swirl
#endif
804 ad71ed68 Blue Swirl
    env->exception_index = exception;
805 ad71ed68 Blue Swirl
    env->error_code = error_code;
806 ad71ed68 Blue Swirl
    cpu_loop_exit(env);
807 ad71ed68 Blue Swirl
}
808 ad71ed68 Blue Swirl
809 e5f17ac6 Blue Swirl
void helper_raise_exception(CPUPPCState *env, uint32_t exception)
810 ad71ed68 Blue Swirl
{
811 e5f17ac6 Blue Swirl
    helper_raise_exception_err(env, exception, 0);
812 ad71ed68 Blue Swirl
}
813 ad71ed68 Blue Swirl
814 ad71ed68 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
815 e5f17ac6 Blue Swirl
void helper_store_msr(CPUPPCState *env, target_ulong val)
816 ad71ed68 Blue Swirl
{
817 259186a7 Andreas Färber
    CPUState *cs;
818 259186a7 Andreas Färber
819 ad71ed68 Blue Swirl
    val = hreg_store_msr(env, val, 0);
820 ad71ed68 Blue Swirl
    if (val != 0) {
821 259186a7 Andreas Färber
        cs = CPU(ppc_env_get_cpu(env));
822 259186a7 Andreas Färber
        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
823 e5f17ac6 Blue Swirl
        helper_raise_exception(env, val);
824 ad71ed68 Blue Swirl
    }
825 ad71ed68 Blue Swirl
}
826 ad71ed68 Blue Swirl
827 e5f17ac6 Blue Swirl
static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
828 ad71ed68 Blue Swirl
                          target_ulong msrm, int keep_msrh)
829 ad71ed68 Blue Swirl
{
830 259186a7 Andreas Färber
    CPUState *cs = CPU(ppc_env_get_cpu(env));
831 259186a7 Andreas Färber
832 ad71ed68 Blue Swirl
#if defined(TARGET_PPC64)
833 e42a61f1 Alexander Graf
    if (msr_is_64bit(env, msr)) {
834 ad71ed68 Blue Swirl
        nip = (uint64_t)nip;
835 ad71ed68 Blue Swirl
        msr &= (uint64_t)msrm;
836 ad71ed68 Blue Swirl
    } else {
837 ad71ed68 Blue Swirl
        nip = (uint32_t)nip;
838 ad71ed68 Blue Swirl
        msr = (uint32_t)(msr & msrm);
839 ad71ed68 Blue Swirl
        if (keep_msrh) {
840 ad71ed68 Blue Swirl
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
841 ad71ed68 Blue Swirl
        }
842 ad71ed68 Blue Swirl
    }
843 ad71ed68 Blue Swirl
#else
844 ad71ed68 Blue Swirl
    nip = (uint32_t)nip;
845 ad71ed68 Blue Swirl
    msr &= (uint32_t)msrm;
846 ad71ed68 Blue Swirl
#endif
847 ad71ed68 Blue Swirl
    /* XXX: beware: this is false if VLE is supported */
848 ad71ed68 Blue Swirl
    env->nip = nip & ~((target_ulong)0x00000003);
849 ad71ed68 Blue Swirl
    hreg_store_msr(env, msr, 1);
850 ad71ed68 Blue Swirl
#if defined(DEBUG_OP)
851 ad71ed68 Blue Swirl
    cpu_dump_rfi(env->nip, env->msr);
852 ad71ed68 Blue Swirl
#endif
853 ad71ed68 Blue Swirl
    /* No need to raise an exception here,
854 ad71ed68 Blue Swirl
     * as rfi is always the last insn of a TB
855 ad71ed68 Blue Swirl
     */
856 259186a7 Andreas Färber
    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
857 ad71ed68 Blue Swirl
}
858 ad71ed68 Blue Swirl
859 e5f17ac6 Blue Swirl
void helper_rfi(CPUPPCState *env)
860 ad71ed68 Blue Swirl
{
861 a1bb7384 Scott Wood
    if (env->excp_model == POWERPC_EXCP_BOOKE) {
862 a1bb7384 Scott Wood
        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
863 a1bb7384 Scott Wood
               ~((target_ulong)0), 0);
864 a1bb7384 Scott Wood
    } else {
865 a1bb7384 Scott Wood
        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
866 a1bb7384 Scott Wood
               ~((target_ulong)0x783F0000), 1);
867 a1bb7384 Scott Wood
    }
868 ad71ed68 Blue Swirl
}
869 ad71ed68 Blue Swirl
870 ad71ed68 Blue Swirl
#if defined(TARGET_PPC64)
871 e5f17ac6 Blue Swirl
void helper_rfid(CPUPPCState *env)
872 ad71ed68 Blue Swirl
{
873 e5f17ac6 Blue Swirl
    do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
874 ad71ed68 Blue Swirl
           ~((target_ulong)0x783F0000), 0);
875 ad71ed68 Blue Swirl
}
876 ad71ed68 Blue Swirl
877 e5f17ac6 Blue Swirl
void helper_hrfid(CPUPPCState *env)
878 ad71ed68 Blue Swirl
{
879 e5f17ac6 Blue Swirl
    do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
880 ad71ed68 Blue Swirl
           ~((target_ulong)0x783F0000), 0);
881 ad71ed68 Blue Swirl
}
882 ad71ed68 Blue Swirl
#endif
883 ad71ed68 Blue Swirl
884 ad71ed68 Blue Swirl
/*****************************************************************************/
885 ad71ed68 Blue Swirl
/* Embedded PowerPC specific helpers */
886 e5f17ac6 Blue Swirl
void helper_40x_rfci(CPUPPCState *env)
887 ad71ed68 Blue Swirl
{
888 e5f17ac6 Blue Swirl
    do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
889 ad71ed68 Blue Swirl
           ~((target_ulong)0xFFFF0000), 0);
890 ad71ed68 Blue Swirl
}
891 ad71ed68 Blue Swirl
892 e5f17ac6 Blue Swirl
void helper_rfci(CPUPPCState *env)
893 ad71ed68 Blue Swirl
{
894 a1bb7384 Scott Wood
    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
895 a1bb7384 Scott Wood
           ~((target_ulong)0), 0);
896 ad71ed68 Blue Swirl
}
897 ad71ed68 Blue Swirl
898 e5f17ac6 Blue Swirl
void helper_rfdi(CPUPPCState *env)
899 ad71ed68 Blue Swirl
{
900 a1bb7384 Scott Wood
    /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
901 a1bb7384 Scott Wood
    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
902 a1bb7384 Scott Wood
           ~((target_ulong)0), 0);
903 ad71ed68 Blue Swirl
}
904 ad71ed68 Blue Swirl
905 e5f17ac6 Blue Swirl
void helper_rfmci(CPUPPCState *env)
906 ad71ed68 Blue Swirl
{
907 a1bb7384 Scott Wood
    /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
908 a1bb7384 Scott Wood
    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
909 a1bb7384 Scott Wood
           ~((target_ulong)0), 0);
910 ad71ed68 Blue Swirl
}
911 ad71ed68 Blue Swirl
#endif
912 ad71ed68 Blue Swirl
913 e5f17ac6 Blue Swirl
void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
914 e5f17ac6 Blue Swirl
               uint32_t flags)
915 ad71ed68 Blue Swirl
{
916 ad71ed68 Blue Swirl
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
917 ad71ed68 Blue Swirl
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
918 ad71ed68 Blue Swirl
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
919 ad71ed68 Blue Swirl
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
920 ad71ed68 Blue Swirl
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
921 e5f17ac6 Blue Swirl
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
922 e5f17ac6 Blue Swirl
                                   POWERPC_EXCP_TRAP);
923 ad71ed68 Blue Swirl
    }
924 ad71ed68 Blue Swirl
}
925 ad71ed68 Blue Swirl
926 ad71ed68 Blue Swirl
#if defined(TARGET_PPC64)
927 e5f17ac6 Blue Swirl
void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
928 e5f17ac6 Blue Swirl
               uint32_t flags)
929 ad71ed68 Blue Swirl
{
930 ad71ed68 Blue Swirl
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
931 ad71ed68 Blue Swirl
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
932 ad71ed68 Blue Swirl
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
933 ad71ed68 Blue Swirl
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
934 ad71ed68 Blue Swirl
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
935 e5f17ac6 Blue Swirl
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
936 e5f17ac6 Blue Swirl
                                   POWERPC_EXCP_TRAP);
937 ad71ed68 Blue Swirl
    }
938 ad71ed68 Blue Swirl
}
939 ad71ed68 Blue Swirl
#endif
940 ad71ed68 Blue Swirl
941 ad71ed68 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
942 ad71ed68 Blue Swirl
/*****************************************************************************/
943 ad71ed68 Blue Swirl
/* PowerPC 601 specific instructions (POWER bridge) */
944 ad71ed68 Blue Swirl
945 e5f17ac6 Blue Swirl
void helper_rfsvc(CPUPPCState *env)
946 ad71ed68 Blue Swirl
{
947 e5f17ac6 Blue Swirl
    do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
948 ad71ed68 Blue Swirl
}
949 ad71ed68 Blue Swirl
950 ad71ed68 Blue Swirl
/* Embedded.Processor Control */
951 ad71ed68 Blue Swirl
static int dbell2irq(target_ulong rb)
952 ad71ed68 Blue Swirl
{
953 ad71ed68 Blue Swirl
    int msg = rb & DBELL_TYPE_MASK;
954 ad71ed68 Blue Swirl
    int irq = -1;
955 ad71ed68 Blue Swirl
956 ad71ed68 Blue Swirl
    switch (msg) {
957 ad71ed68 Blue Swirl
    case DBELL_TYPE_DBELL:
958 ad71ed68 Blue Swirl
        irq = PPC_INTERRUPT_DOORBELL;
959 ad71ed68 Blue Swirl
        break;
960 ad71ed68 Blue Swirl
    case DBELL_TYPE_DBELL_CRIT:
961 ad71ed68 Blue Swirl
        irq = PPC_INTERRUPT_CDOORBELL;
962 ad71ed68 Blue Swirl
        break;
963 ad71ed68 Blue Swirl
    case DBELL_TYPE_G_DBELL:
964 ad71ed68 Blue Swirl
    case DBELL_TYPE_G_DBELL_CRIT:
965 ad71ed68 Blue Swirl
    case DBELL_TYPE_G_DBELL_MC:
966 ad71ed68 Blue Swirl
        /* XXX implement */
967 ad71ed68 Blue Swirl
    default:
968 ad71ed68 Blue Swirl
        break;
969 ad71ed68 Blue Swirl
    }
970 ad71ed68 Blue Swirl
971 ad71ed68 Blue Swirl
    return irq;
972 ad71ed68 Blue Swirl
}
973 ad71ed68 Blue Swirl
974 e5f17ac6 Blue Swirl
void helper_msgclr(CPUPPCState *env, target_ulong rb)
975 ad71ed68 Blue Swirl
{
976 ad71ed68 Blue Swirl
    int irq = dbell2irq(rb);
977 ad71ed68 Blue Swirl
978 ad71ed68 Blue Swirl
    if (irq < 0) {
979 ad71ed68 Blue Swirl
        return;
980 ad71ed68 Blue Swirl
    }
981 ad71ed68 Blue Swirl
982 ad71ed68 Blue Swirl
    env->pending_interrupts &= ~(1 << irq);
983 ad71ed68 Blue Swirl
}
984 ad71ed68 Blue Swirl
985 ad71ed68 Blue Swirl
void helper_msgsnd(target_ulong rb)
986 ad71ed68 Blue Swirl
{
987 ad71ed68 Blue Swirl
    int irq = dbell2irq(rb);
988 ad71ed68 Blue Swirl
    int pir = rb & DBELL_PIRTAG_MASK;
989 ad71ed68 Blue Swirl
    CPUPPCState *cenv;
990 ad71ed68 Blue Swirl
991 ad71ed68 Blue Swirl
    if (irq < 0) {
992 ad71ed68 Blue Swirl
        return;
993 ad71ed68 Blue Swirl
    }
994 ad71ed68 Blue Swirl
995 ad71ed68 Blue Swirl
    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
996 ad71ed68 Blue Swirl
        if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
997 ad71ed68 Blue Swirl
            cenv->pending_interrupts |= 1 << irq;
998 c3affe56 Andreas Färber
            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
999 ad71ed68 Blue Swirl
        }
1000 ad71ed68 Blue Swirl
    }
1001 ad71ed68 Blue Swirl
}
1002 ad71ed68 Blue Swirl
#endif