Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ a8170e5e

History | View | Annotate | Download (13.5 kB)

1 4c9649a9 j_mayer
/*
2 4c9649a9 j_mayer
 *  Alpha emulation cpu helpers for qemu.
3 5fafdf24 ths
 *
4 4c9649a9 j_mayer
 *  Copyright (c) 2007 Jocelyn Mayer
5 4c9649a9 j_mayer
 *
6 4c9649a9 j_mayer
 * This library is free software; you can redistribute it and/or
7 4c9649a9 j_mayer
 * modify it under the terms of the GNU Lesser General Public
8 4c9649a9 j_mayer
 * License as published by the Free Software Foundation; either
9 4c9649a9 j_mayer
 * version 2 of the License, or (at your option) any later version.
10 4c9649a9 j_mayer
 *
11 4c9649a9 j_mayer
 * This library is distributed in the hope that it will be useful,
12 4c9649a9 j_mayer
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 4c9649a9 j_mayer
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4c9649a9 j_mayer
 * Lesser General Public License for more details.
15 4c9649a9 j_mayer
 *
16 4c9649a9 j_mayer
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 4c9649a9 j_mayer
 */
19 4c9649a9 j_mayer
20 4c9649a9 j_mayer
#include <stdint.h>
21 4c9649a9 j_mayer
#include <stdlib.h>
22 4c9649a9 j_mayer
#include <stdio.h>
23 4c9649a9 j_mayer
24 4c9649a9 j_mayer
#include "cpu.h"
25 ba0e276d Richard Henderson
#include "softfloat.h"
26 b9f0923e Richard Henderson
#include "helper.h"
27 ba0e276d Richard Henderson
28 4d5712f1 Andreas Färber
uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
29 ba0e276d Richard Henderson
{
30 8443effb Richard Henderson
    uint64_t r = 0;
31 8443effb Richard Henderson
    uint8_t t;
32 8443effb Richard Henderson
33 8443effb Richard Henderson
    t = env->fpcr_exc_status;
34 8443effb Richard Henderson
    if (t) {
35 8443effb Richard Henderson
        r = FPCR_SUM;
36 8443effb Richard Henderson
        if (t & float_flag_invalid) {
37 8443effb Richard Henderson
            r |= FPCR_INV;
38 8443effb Richard Henderson
        }
39 8443effb Richard Henderson
        if (t & float_flag_divbyzero) {
40 8443effb Richard Henderson
            r |= FPCR_DZE;
41 8443effb Richard Henderson
        }
42 8443effb Richard Henderson
        if (t & float_flag_overflow) {
43 8443effb Richard Henderson
            r |= FPCR_OVF;
44 8443effb Richard Henderson
        }
45 8443effb Richard Henderson
        if (t & float_flag_underflow) {
46 8443effb Richard Henderson
            r |= FPCR_UNF;
47 8443effb Richard Henderson
        }
48 8443effb Richard Henderson
        if (t & float_flag_inexact) {
49 8443effb Richard Henderson
            r |= FPCR_INE;
50 8443effb Richard Henderson
        }
51 8443effb Richard Henderson
    }
52 8443effb Richard Henderson
53 8443effb Richard Henderson
    t = env->fpcr_exc_mask;
54 8443effb Richard Henderson
    if (t & float_flag_invalid) {
55 8443effb Richard Henderson
        r |= FPCR_INVD;
56 8443effb Richard Henderson
    }
57 8443effb Richard Henderson
    if (t & float_flag_divbyzero) {
58 8443effb Richard Henderson
        r |= FPCR_DZED;
59 8443effb Richard Henderson
    }
60 8443effb Richard Henderson
    if (t & float_flag_overflow) {
61 8443effb Richard Henderson
        r |= FPCR_OVFD;
62 8443effb Richard Henderson
    }
63 8443effb Richard Henderson
    if (t & float_flag_underflow) {
64 8443effb Richard Henderson
        r |= FPCR_UNFD;
65 8443effb Richard Henderson
    }
66 8443effb Richard Henderson
    if (t & float_flag_inexact) {
67 8443effb Richard Henderson
        r |= FPCR_INED;
68 8443effb Richard Henderson
    }
69 8443effb Richard Henderson
70 8443effb Richard Henderson
    switch (env->fpcr_dyn_round) {
71 ba0e276d Richard Henderson
    case float_round_nearest_even:
72 8443effb Richard Henderson
        r |= FPCR_DYN_NORMAL;
73 ba0e276d Richard Henderson
        break;
74 ba0e276d Richard Henderson
    case float_round_down:
75 8443effb Richard Henderson
        r |= FPCR_DYN_MINUS;
76 ba0e276d Richard Henderson
        break;
77 ba0e276d Richard Henderson
    case float_round_up:
78 8443effb Richard Henderson
        r |= FPCR_DYN_PLUS;
79 ba0e276d Richard Henderson
        break;
80 ba0e276d Richard Henderson
    case float_round_to_zero:
81 8443effb Richard Henderson
        r |= FPCR_DYN_CHOPPED;
82 ba0e276d Richard Henderson
        break;
83 ba0e276d Richard Henderson
    }
84 8443effb Richard Henderson
85 74343409 Richard Henderson
    if (env->fp_status.flush_inputs_to_zero) {
86 8443effb Richard Henderson
        r |= FPCR_DNZ;
87 8443effb Richard Henderson
    }
88 8443effb Richard Henderson
    if (env->fpcr_dnod) {
89 8443effb Richard Henderson
        r |= FPCR_DNOD;
90 8443effb Richard Henderson
    }
91 8443effb Richard Henderson
    if (env->fpcr_undz) {
92 8443effb Richard Henderson
        r |= FPCR_UNDZ;
93 8443effb Richard Henderson
    }
94 8443effb Richard Henderson
95 8443effb Richard Henderson
    return r;
96 ba0e276d Richard Henderson
}
97 ba0e276d Richard Henderson
98 4d5712f1 Andreas Färber
void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
99 ba0e276d Richard Henderson
{
100 8443effb Richard Henderson
    uint8_t t;
101 8443effb Richard Henderson
102 8443effb Richard Henderson
    t = 0;
103 8443effb Richard Henderson
    if (val & FPCR_INV) {
104 8443effb Richard Henderson
        t |= float_flag_invalid;
105 8443effb Richard Henderson
    }
106 8443effb Richard Henderson
    if (val & FPCR_DZE) {
107 8443effb Richard Henderson
        t |= float_flag_divbyzero;
108 8443effb Richard Henderson
    }
109 8443effb Richard Henderson
    if (val & FPCR_OVF) {
110 8443effb Richard Henderson
        t |= float_flag_overflow;
111 8443effb Richard Henderson
    }
112 8443effb Richard Henderson
    if (val & FPCR_UNF) {
113 8443effb Richard Henderson
        t |= float_flag_underflow;
114 8443effb Richard Henderson
    }
115 8443effb Richard Henderson
    if (val & FPCR_INE) {
116 8443effb Richard Henderson
        t |= float_flag_inexact;
117 8443effb Richard Henderson
    }
118 8443effb Richard Henderson
    env->fpcr_exc_status = t;
119 8443effb Richard Henderson
120 8443effb Richard Henderson
    t = 0;
121 8443effb Richard Henderson
    if (val & FPCR_INVD) {
122 8443effb Richard Henderson
        t |= float_flag_invalid;
123 8443effb Richard Henderson
    }
124 8443effb Richard Henderson
    if (val & FPCR_DZED) {
125 8443effb Richard Henderson
        t |= float_flag_divbyzero;
126 8443effb Richard Henderson
    }
127 8443effb Richard Henderson
    if (val & FPCR_OVFD) {
128 8443effb Richard Henderson
        t |= float_flag_overflow;
129 8443effb Richard Henderson
    }
130 8443effb Richard Henderson
    if (val & FPCR_UNFD) {
131 8443effb Richard Henderson
        t |= float_flag_underflow;
132 8443effb Richard Henderson
    }
133 8443effb Richard Henderson
    if (val & FPCR_INED) {
134 8443effb Richard Henderson
        t |= float_flag_inexact;
135 8443effb Richard Henderson
    }
136 8443effb Richard Henderson
    env->fpcr_exc_mask = t;
137 8443effb Richard Henderson
138 8443effb Richard Henderson
    switch (val & FPCR_DYN_MASK) {
139 8443effb Richard Henderson
    case FPCR_DYN_CHOPPED:
140 8443effb Richard Henderson
        t = float_round_to_zero;
141 ba0e276d Richard Henderson
        break;
142 8443effb Richard Henderson
    case FPCR_DYN_MINUS:
143 8443effb Richard Henderson
        t = float_round_down;
144 ba0e276d Richard Henderson
        break;
145 8443effb Richard Henderson
    case FPCR_DYN_NORMAL:
146 8443effb Richard Henderson
        t = float_round_nearest_even;
147 ba0e276d Richard Henderson
        break;
148 8443effb Richard Henderson
    case FPCR_DYN_PLUS:
149 8443effb Richard Henderson
        t = float_round_up;
150 ba0e276d Richard Henderson
        break;
151 ba0e276d Richard Henderson
    }
152 8443effb Richard Henderson
    env->fpcr_dyn_round = t;
153 8443effb Richard Henderson
154 8443effb Richard Henderson
    env->fpcr_dnod = (val & FPCR_DNOD) != 0;
155 8443effb Richard Henderson
    env->fpcr_undz = (val & FPCR_UNDZ) != 0;
156 74343409 Richard Henderson
    env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz;
157 74343409 Richard Henderson
    env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0;
158 ba0e276d Richard Henderson
}
159 4c9649a9 j_mayer
160 a44a2777 Richard Henderson
uint64_t helper_load_fpcr(CPUAlphaState *env)
161 a44a2777 Richard Henderson
{
162 a44a2777 Richard Henderson
    return cpu_alpha_load_fpcr(env);
163 a44a2777 Richard Henderson
}
164 a44a2777 Richard Henderson
165 a44a2777 Richard Henderson
void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
166 a44a2777 Richard Henderson
{
167 a44a2777 Richard Henderson
    cpu_alpha_store_fpcr(env, val);
168 a44a2777 Richard Henderson
}
169 a44a2777 Richard Henderson
170 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
171 a44a2777 Richard Henderson
int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong address,
172 a44a2777 Richard Henderson
                               int rw, int mmu_idx)
173 4c9649a9 j_mayer
{
174 07b6c13b Richard Henderson
    env->exception_index = EXCP_MMFAULT;
175 129d8aa5 Richard Henderson
    env->trap_arg0 = address;
176 4c9649a9 j_mayer
    return 1;
177 4c9649a9 j_mayer
}
178 4c9649a9 j_mayer
#else
179 4d5712f1 Andreas Färber
void swap_shadow_regs(CPUAlphaState *env)
180 21d2beaa Richard Henderson
{
181 21d2beaa Richard Henderson
    uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
182 21d2beaa Richard Henderson
183 21d2beaa Richard Henderson
    i0 = env->ir[8];
184 21d2beaa Richard Henderson
    i1 = env->ir[9];
185 21d2beaa Richard Henderson
    i2 = env->ir[10];
186 21d2beaa Richard Henderson
    i3 = env->ir[11];
187 21d2beaa Richard Henderson
    i4 = env->ir[12];
188 21d2beaa Richard Henderson
    i5 = env->ir[13];
189 21d2beaa Richard Henderson
    i6 = env->ir[14];
190 21d2beaa Richard Henderson
    i7 = env->ir[25];
191 21d2beaa Richard Henderson
192 21d2beaa Richard Henderson
    env->ir[8]  = env->shadow[0];
193 21d2beaa Richard Henderson
    env->ir[9]  = env->shadow[1];
194 21d2beaa Richard Henderson
    env->ir[10] = env->shadow[2];
195 21d2beaa Richard Henderson
    env->ir[11] = env->shadow[3];
196 21d2beaa Richard Henderson
    env->ir[12] = env->shadow[4];
197 21d2beaa Richard Henderson
    env->ir[13] = env->shadow[5];
198 21d2beaa Richard Henderson
    env->ir[14] = env->shadow[6];
199 21d2beaa Richard Henderson
    env->ir[25] = env->shadow[7];
200 21d2beaa Richard Henderson
201 21d2beaa Richard Henderson
    env->shadow[0] = i0;
202 21d2beaa Richard Henderson
    env->shadow[1] = i1;
203 21d2beaa Richard Henderson
    env->shadow[2] = i2;
204 21d2beaa Richard Henderson
    env->shadow[3] = i3;
205 21d2beaa Richard Henderson
    env->shadow[4] = i4;
206 21d2beaa Richard Henderson
    env->shadow[5] = i5;
207 21d2beaa Richard Henderson
    env->shadow[6] = i6;
208 21d2beaa Richard Henderson
    env->shadow[7] = i7;
209 21d2beaa Richard Henderson
}
210 21d2beaa Richard Henderson
211 a3b9af16 Richard Henderson
/* Returns the OSF/1 entMM failure indication, or -1 on success.  */
212 4d5712f1 Andreas Färber
static int get_physical_address(CPUAlphaState *env, target_ulong addr,
213 a3b9af16 Richard Henderson
                                int prot_need, int mmu_idx,
214 a3b9af16 Richard Henderson
                                target_ulong *pphys, int *pprot)
215 4c9649a9 j_mayer
{
216 a3b9af16 Richard Henderson
    target_long saddr = addr;
217 a3b9af16 Richard Henderson
    target_ulong phys = 0;
218 a3b9af16 Richard Henderson
    target_ulong L1pte, L2pte, L3pte;
219 a3b9af16 Richard Henderson
    target_ulong pt, index;
220 a3b9af16 Richard Henderson
    int prot = 0;
221 a3b9af16 Richard Henderson
    int ret = MM_K_ACV;
222 a3b9af16 Richard Henderson
223 a3b9af16 Richard Henderson
    /* Ensure that the virtual address is properly sign-extended from
224 a3b9af16 Richard Henderson
       the last implemented virtual address bit.  */
225 a3b9af16 Richard Henderson
    if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) {
226 a3b9af16 Richard Henderson
        goto exit;
227 a3b9af16 Richard Henderson
    }
228 a3b9af16 Richard Henderson
229 a3b9af16 Richard Henderson
    /* Translate the superpage.  */
230 a3b9af16 Richard Henderson
    /* ??? When we do more than emulate Unix PALcode, we'll need to
231 fa6e0a63 Richard Henderson
       determine which KSEG is actually active.  */
232 fa6e0a63 Richard Henderson
    if (saddr < 0 && ((saddr >> 41) & 3) == 2) {
233 fa6e0a63 Richard Henderson
        /* User-space cannot access KSEG addresses.  */
234 a3b9af16 Richard Henderson
        if (mmu_idx != MMU_KERNEL_IDX) {
235 a3b9af16 Richard Henderson
            goto exit;
236 a3b9af16 Richard Henderson
        }
237 a3b9af16 Richard Henderson
238 fa6e0a63 Richard Henderson
        /* For the benefit of the Typhoon chipset, move bit 40 to bit 43.
239 fa6e0a63 Richard Henderson
           We would not do this if the 48-bit KSEG is enabled.  */
240 a3b9af16 Richard Henderson
        phys = saddr & ((1ull << 40) - 1);
241 fa6e0a63 Richard Henderson
        phys |= (saddr & (1ull << 40)) << 3;
242 fa6e0a63 Richard Henderson
243 a3b9af16 Richard Henderson
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
244 a3b9af16 Richard Henderson
        ret = -1;
245 a3b9af16 Richard Henderson
        goto exit;
246 a3b9af16 Richard Henderson
    }
247 a3b9af16 Richard Henderson
248 a3b9af16 Richard Henderson
    /* Interpret the page table exactly like PALcode does.  */
249 a3b9af16 Richard Henderson
250 a3b9af16 Richard Henderson
    pt = env->ptbr;
251 a3b9af16 Richard Henderson
252 a3b9af16 Richard Henderson
    /* L1 page table read.  */
253 a3b9af16 Richard Henderson
    index = (addr >> (TARGET_PAGE_BITS + 20)) & 0x3ff;
254 a3b9af16 Richard Henderson
    L1pte = ldq_phys(pt + index*8);
255 a3b9af16 Richard Henderson
256 a3b9af16 Richard Henderson
    if (unlikely((L1pte & PTE_VALID) == 0)) {
257 a3b9af16 Richard Henderson
        ret = MM_K_TNV;
258 a3b9af16 Richard Henderson
        goto exit;
259 a3b9af16 Richard Henderson
    }
260 a3b9af16 Richard Henderson
    if (unlikely((L1pte & PTE_KRE) == 0)) {
261 a3b9af16 Richard Henderson
        goto exit;
262 a3b9af16 Richard Henderson
    }
263 a3b9af16 Richard Henderson
    pt = L1pte >> 32 << TARGET_PAGE_BITS;
264 a3b9af16 Richard Henderson
265 a3b9af16 Richard Henderson
    /* L2 page table read.  */
266 a3b9af16 Richard Henderson
    index = (addr >> (TARGET_PAGE_BITS + 10)) & 0x3ff;
267 a3b9af16 Richard Henderson
    L2pte = ldq_phys(pt + index*8);
268 a3b9af16 Richard Henderson
269 a3b9af16 Richard Henderson
    if (unlikely((L2pte & PTE_VALID) == 0)) {
270 a3b9af16 Richard Henderson
        ret = MM_K_TNV;
271 a3b9af16 Richard Henderson
        goto exit;
272 a3b9af16 Richard Henderson
    }
273 a3b9af16 Richard Henderson
    if (unlikely((L2pte & PTE_KRE) == 0)) {
274 a3b9af16 Richard Henderson
        goto exit;
275 a3b9af16 Richard Henderson
    }
276 a3b9af16 Richard Henderson
    pt = L2pte >> 32 << TARGET_PAGE_BITS;
277 a3b9af16 Richard Henderson
278 a3b9af16 Richard Henderson
    /* L3 page table read.  */
279 a3b9af16 Richard Henderson
    index = (addr >> TARGET_PAGE_BITS) & 0x3ff;
280 a3b9af16 Richard Henderson
    L3pte = ldq_phys(pt + index*8);
281 a3b9af16 Richard Henderson
282 a3b9af16 Richard Henderson
    phys = L3pte >> 32 << TARGET_PAGE_BITS;
283 a3b9af16 Richard Henderson
    if (unlikely((L3pte & PTE_VALID) == 0)) {
284 a3b9af16 Richard Henderson
        ret = MM_K_TNV;
285 a3b9af16 Richard Henderson
        goto exit;
286 a3b9af16 Richard Henderson
    }
287 a3b9af16 Richard Henderson
288 a3b9af16 Richard Henderson
#if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4
289 a3b9af16 Richard Henderson
# error page bits out of date
290 a3b9af16 Richard Henderson
#endif
291 a3b9af16 Richard Henderson
292 a3b9af16 Richard Henderson
    /* Check access violations.  */
293 a3b9af16 Richard Henderson
    if (L3pte & (PTE_KRE << mmu_idx)) {
294 a3b9af16 Richard Henderson
        prot |= PAGE_READ | PAGE_EXEC;
295 a3b9af16 Richard Henderson
    }
296 a3b9af16 Richard Henderson
    if (L3pte & (PTE_KWE << mmu_idx)) {
297 a3b9af16 Richard Henderson
        prot |= PAGE_WRITE;
298 a3b9af16 Richard Henderson
    }
299 a3b9af16 Richard Henderson
    if (unlikely((prot & prot_need) == 0 && prot_need)) {
300 a3b9af16 Richard Henderson
        goto exit;
301 a3b9af16 Richard Henderson
    }
302 a3b9af16 Richard Henderson
303 a3b9af16 Richard Henderson
    /* Check fault-on-operation violations.  */
304 a3b9af16 Richard Henderson
    prot &= ~(L3pte >> 1);
305 a3b9af16 Richard Henderson
    ret = -1;
306 a3b9af16 Richard Henderson
    if (unlikely((prot & prot_need) == 0)) {
307 a3b9af16 Richard Henderson
        ret = (prot_need & PAGE_EXEC ? MM_K_FOE :
308 a3b9af16 Richard Henderson
               prot_need & PAGE_WRITE ? MM_K_FOW :
309 a3b9af16 Richard Henderson
               prot_need & PAGE_READ ? MM_K_FOR : -1);
310 a3b9af16 Richard Henderson
    }
311 a3b9af16 Richard Henderson
312 a3b9af16 Richard Henderson
 exit:
313 a3b9af16 Richard Henderson
    *pphys = phys;
314 a3b9af16 Richard Henderson
    *pprot = prot;
315 a3b9af16 Richard Henderson
    return ret;
316 4c9649a9 j_mayer
}
317 4c9649a9 j_mayer
318 a8170e5e Avi Kivity
hwaddr cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr)
319 4c9649a9 j_mayer
{
320 a3b9af16 Richard Henderson
    target_ulong phys;
321 a3b9af16 Richard Henderson
    int prot, fail;
322 a3b9af16 Richard Henderson
323 a3b9af16 Richard Henderson
    fail = get_physical_address(env, addr, 0, 0, &phys, &prot);
324 a3b9af16 Richard Henderson
    return (fail >= 0 ? -1 : phys);
325 a3b9af16 Richard Henderson
}
326 a3b9af16 Richard Henderson
327 4d5712f1 Andreas Färber
int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw,
328 97b348e7 Blue Swirl
                               int mmu_idx)
329 a3b9af16 Richard Henderson
{
330 a3b9af16 Richard Henderson
    target_ulong phys;
331 a3b9af16 Richard Henderson
    int prot, fail;
332 a3b9af16 Richard Henderson
333 a3b9af16 Richard Henderson
    fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot);
334 a3b9af16 Richard Henderson
    if (unlikely(fail >= 0)) {
335 a3b9af16 Richard Henderson
        env->exception_index = EXCP_MMFAULT;
336 a3b9af16 Richard Henderson
        env->trap_arg0 = addr;
337 a3b9af16 Richard Henderson
        env->trap_arg1 = fail;
338 a3b9af16 Richard Henderson
        env->trap_arg2 = (rw == 2 ? -1 : rw);
339 a3b9af16 Richard Henderson
        return 1;
340 a3b9af16 Richard Henderson
    }
341 a3b9af16 Richard Henderson
342 a3b9af16 Richard Henderson
    tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
343 a3b9af16 Richard Henderson
                 prot, mmu_idx, TARGET_PAGE_SIZE);
344 129d8aa5 Richard Henderson
    return 0;
345 4c9649a9 j_mayer
}
346 3a6fa678 Richard Henderson
#endif /* USER_ONLY */
347 4c9649a9 j_mayer
348 4d5712f1 Andreas Färber
void do_interrupt (CPUAlphaState *env)
349 4c9649a9 j_mayer
{
350 3a6fa678 Richard Henderson
    int i = env->exception_index;
351 3a6fa678 Richard Henderson
352 3a6fa678 Richard Henderson
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
353 3a6fa678 Richard Henderson
        static int count;
354 3a6fa678 Richard Henderson
        const char *name = "<unknown>";
355 3a6fa678 Richard Henderson
356 3a6fa678 Richard Henderson
        switch (i) {
357 3a6fa678 Richard Henderson
        case EXCP_RESET:
358 3a6fa678 Richard Henderson
            name = "reset";
359 3a6fa678 Richard Henderson
            break;
360 3a6fa678 Richard Henderson
        case EXCP_MCHK:
361 3a6fa678 Richard Henderson
            name = "mchk";
362 3a6fa678 Richard Henderson
            break;
363 3a6fa678 Richard Henderson
        case EXCP_SMP_INTERRUPT:
364 3a6fa678 Richard Henderson
            name = "smp_interrupt";
365 3a6fa678 Richard Henderson
            break;
366 3a6fa678 Richard Henderson
        case EXCP_CLK_INTERRUPT:
367 3a6fa678 Richard Henderson
            name = "clk_interrupt";
368 3a6fa678 Richard Henderson
            break;
369 3a6fa678 Richard Henderson
        case EXCP_DEV_INTERRUPT:
370 3a6fa678 Richard Henderson
            name = "dev_interrupt";
371 3a6fa678 Richard Henderson
            break;
372 3a6fa678 Richard Henderson
        case EXCP_MMFAULT:
373 3a6fa678 Richard Henderson
            name = "mmfault";
374 3a6fa678 Richard Henderson
            break;
375 3a6fa678 Richard Henderson
        case EXCP_UNALIGN:
376 3a6fa678 Richard Henderson
            name = "unalign";
377 3a6fa678 Richard Henderson
            break;
378 3a6fa678 Richard Henderson
        case EXCP_OPCDEC:
379 3a6fa678 Richard Henderson
            name = "opcdec";
380 3a6fa678 Richard Henderson
            break;
381 3a6fa678 Richard Henderson
        case EXCP_ARITH:
382 3a6fa678 Richard Henderson
            name = "arith";
383 3a6fa678 Richard Henderson
            break;
384 3a6fa678 Richard Henderson
        case EXCP_FEN:
385 3a6fa678 Richard Henderson
            name = "fen";
386 3a6fa678 Richard Henderson
            break;
387 3a6fa678 Richard Henderson
        case EXCP_CALL_PAL:
388 3a6fa678 Richard Henderson
            name = "call_pal";
389 3a6fa678 Richard Henderson
            break;
390 3a6fa678 Richard Henderson
        case EXCP_STL_C:
391 3a6fa678 Richard Henderson
            name = "stl_c";
392 3a6fa678 Richard Henderson
            break;
393 3a6fa678 Richard Henderson
        case EXCP_STQ_C:
394 3a6fa678 Richard Henderson
            name = "stq_c";
395 3a6fa678 Richard Henderson
            break;
396 3a6fa678 Richard Henderson
        }
397 3a6fa678 Richard Henderson
        qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n",
398 3a6fa678 Richard Henderson
                 ++count, name, env->error_code, env->pc, env->ir[IR_SP]);
399 3a6fa678 Richard Henderson
    }
400 3a6fa678 Richard Henderson
401 3a6fa678 Richard Henderson
    env->exception_index = -1;
402 3a6fa678 Richard Henderson
403 3a6fa678 Richard Henderson
#if !defined(CONFIG_USER_ONLY)
404 3a6fa678 Richard Henderson
    switch (i) {
405 3a6fa678 Richard Henderson
    case EXCP_RESET:
406 3a6fa678 Richard Henderson
        i = 0x0000;
407 3a6fa678 Richard Henderson
        break;
408 3a6fa678 Richard Henderson
    case EXCP_MCHK:
409 3a6fa678 Richard Henderson
        i = 0x0080;
410 3a6fa678 Richard Henderson
        break;
411 3a6fa678 Richard Henderson
    case EXCP_SMP_INTERRUPT:
412 3a6fa678 Richard Henderson
        i = 0x0100;
413 3a6fa678 Richard Henderson
        break;
414 3a6fa678 Richard Henderson
    case EXCP_CLK_INTERRUPT:
415 3a6fa678 Richard Henderson
        i = 0x0180;
416 3a6fa678 Richard Henderson
        break;
417 3a6fa678 Richard Henderson
    case EXCP_DEV_INTERRUPT:
418 3a6fa678 Richard Henderson
        i = 0x0200;
419 3a6fa678 Richard Henderson
        break;
420 3a6fa678 Richard Henderson
    case EXCP_MMFAULT:
421 3a6fa678 Richard Henderson
        i = 0x0280;
422 3a6fa678 Richard Henderson
        break;
423 3a6fa678 Richard Henderson
    case EXCP_UNALIGN:
424 3a6fa678 Richard Henderson
        i = 0x0300;
425 3a6fa678 Richard Henderson
        break;
426 3a6fa678 Richard Henderson
    case EXCP_OPCDEC:
427 3a6fa678 Richard Henderson
        i = 0x0380;
428 3a6fa678 Richard Henderson
        break;
429 3a6fa678 Richard Henderson
    case EXCP_ARITH:
430 3a6fa678 Richard Henderson
        i = 0x0400;
431 3a6fa678 Richard Henderson
        break;
432 3a6fa678 Richard Henderson
    case EXCP_FEN:
433 3a6fa678 Richard Henderson
        i = 0x0480;
434 3a6fa678 Richard Henderson
        break;
435 3a6fa678 Richard Henderson
    case EXCP_CALL_PAL:
436 3a6fa678 Richard Henderson
        i = env->error_code;
437 3a6fa678 Richard Henderson
        /* There are 64 entry points for both privileged and unprivileged,
438 3a6fa678 Richard Henderson
           with bit 0x80 indicating unprivileged.  Each entry point gets
439 3a6fa678 Richard Henderson
           64 bytes to do its job.  */
440 3a6fa678 Richard Henderson
        if (i & 0x80) {
441 3a6fa678 Richard Henderson
            i = 0x2000 + (i - 0x80) * 64;
442 3a6fa678 Richard Henderson
        } else {
443 3a6fa678 Richard Henderson
            i = 0x1000 + i * 64;
444 3a6fa678 Richard Henderson
        }
445 3a6fa678 Richard Henderson
        break;
446 3a6fa678 Richard Henderson
    default:
447 3a6fa678 Richard Henderson
        cpu_abort(env, "Unhandled CPU exception");
448 3a6fa678 Richard Henderson
    }
449 3a6fa678 Richard Henderson
450 3a6fa678 Richard Henderson
    /* Remember where the exception happened.  Emulate real hardware in
451 3a6fa678 Richard Henderson
       that the low bit of the PC indicates PALmode.  */
452 3a6fa678 Richard Henderson
    env->exc_addr = env->pc | env->pal_mode;
453 3a6fa678 Richard Henderson
454 3a6fa678 Richard Henderson
    /* Continue execution at the PALcode entry point.  */
455 3a6fa678 Richard Henderson
    env->pc = env->palbr + i;
456 3a6fa678 Richard Henderson
457 3a6fa678 Richard Henderson
    /* Switch to PALmode.  */
458 21d2beaa Richard Henderson
    if (!env->pal_mode) {
459 21d2beaa Richard Henderson
        env->pal_mode = 1;
460 21d2beaa Richard Henderson
        swap_shadow_regs(env);
461 21d2beaa Richard Henderson
    }
462 3a6fa678 Richard Henderson
#endif /* !USER_ONLY */
463 4c9649a9 j_mayer
}
464 4c9649a9 j_mayer
465 4d5712f1 Andreas Färber
void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
466 4c9649a9 j_mayer
                     int flags)
467 4c9649a9 j_mayer
{
468 b55266b5 blueswir1
    static const char *linux_reg_names[] = {
469 4c9649a9 j_mayer
        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
470 4c9649a9 j_mayer
        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
471 4c9649a9 j_mayer
        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
472 4c9649a9 j_mayer
        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
473 4c9649a9 j_mayer
    };
474 4c9649a9 j_mayer
    int i;
475 4c9649a9 j_mayer
476 129d8aa5 Richard Henderson
    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  %02x\n",
477 4c9649a9 j_mayer
                env->pc, env->ps);
478 4c9649a9 j_mayer
    for (i = 0; i < 31; i++) {
479 4c9649a9 j_mayer
        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
480 4c9649a9 j_mayer
                    linux_reg_names[i], env->ir[i]);
481 4c9649a9 j_mayer
        if ((i % 3) == 2)
482 4c9649a9 j_mayer
            cpu_fprintf(f, "\n");
483 4c9649a9 j_mayer
    }
484 6910b8f6 Richard Henderson
485 6910b8f6 Richard Henderson
    cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
486 6910b8f6 Richard Henderson
                env->lock_addr, env->lock_value);
487 6910b8f6 Richard Henderson
488 4c9649a9 j_mayer
    for (i = 0; i < 31; i++) {
489 4c9649a9 j_mayer
        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
490 4c9649a9 j_mayer
                    *((uint64_t *)(&env->fir[i])));
491 4c9649a9 j_mayer
        if ((i % 3) == 2)
492 4c9649a9 j_mayer
            cpu_fprintf(f, "\n");
493 4c9649a9 j_mayer
    }
494 6910b8f6 Richard Henderson
    cpu_fprintf(f, "\n");
495 4c9649a9 j_mayer
}
496 b9f0923e Richard Henderson
497 20503968 Blue Swirl
void do_restore_state(CPUAlphaState *env, uintptr_t retaddr)
498 b9f0923e Richard Henderson
{
499 20503968 Blue Swirl
    if (retaddr) {
500 20503968 Blue Swirl
        TranslationBlock *tb = tb_find_pc(retaddr);
501 b9f0923e Richard Henderson
        if (tb) {
502 20503968 Blue Swirl
            cpu_restore_state(tb, env, retaddr);
503 b9f0923e Richard Henderson
        }
504 b9f0923e Richard Henderson
    }
505 b9f0923e Richard Henderson
}
506 b9f0923e Richard Henderson
507 b9f0923e Richard Henderson
/* This should only be called from translate, via gen_excp.
508 b9f0923e Richard Henderson
   We expect that ENV->PC has already been updated.  */
509 b9f0923e Richard Henderson
void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
510 b9f0923e Richard Henderson
{
511 b9f0923e Richard Henderson
    env->exception_index = excp;
512 b9f0923e Richard Henderson
    env->error_code = error;
513 b9f0923e Richard Henderson
    cpu_loop_exit(env);
514 b9f0923e Richard Henderson
}
515 b9f0923e Richard Henderson
516 b9f0923e Richard Henderson
/* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
517 20503968 Blue Swirl
void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr,
518 b9f0923e Richard Henderson
                                int excp, int error)
519 b9f0923e Richard Henderson
{
520 b9f0923e Richard Henderson
    env->exception_index = excp;
521 b9f0923e Richard Henderson
    env->error_code = error;
522 b9f0923e Richard Henderson
    do_restore_state(env, retaddr);
523 b9f0923e Richard Henderson
    cpu_loop_exit(env);
524 b9f0923e Richard Henderson
}
525 b9f0923e Richard Henderson
526 20503968 Blue Swirl
void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr,
527 b9f0923e Richard Henderson
                              int exc, uint64_t mask)
528 b9f0923e Richard Henderson
{
529 b9f0923e Richard Henderson
    env->trap_arg0 = exc;
530 b9f0923e Richard Henderson
    env->trap_arg1 = mask;
531 b9f0923e Richard Henderson
    dynamic_excp(env, retaddr, EXCP_ARITH, 0);
532 b9f0923e Richard Henderson
}