Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ ee5bbe38

History | View | Annotate | Download (19.2 kB)

1 e8af50a3 bellard
#include "exec.h"
2 e8af50a3 bellard
3 e80cfcfc bellard
//#define DEBUG_MMU
4 e80cfcfc bellard
5 9d893301 bellard
void raise_exception(int tt)
6 9d893301 bellard
{
7 9d893301 bellard
    env->exception_index = tt;
8 9d893301 bellard
    cpu_loop_exit();
9 9d893301 bellard
}   
10 9d893301 bellard
11 a0c4cb4a bellard
#ifdef USE_INT_TO_FLOAT_HELPERS
12 a0c4cb4a bellard
void do_fitos(void)
13 a0c4cb4a bellard
{
14 a0c4cb4a bellard
    FT0 = (float) *((int32_t *)&FT1);
15 a0c4cb4a bellard
}
16 a0c4cb4a bellard
17 a0c4cb4a bellard
void do_fitod(void)
18 a0c4cb4a bellard
{
19 a0c4cb4a bellard
    DT0 = (double) *((int32_t *)&FT1);
20 a0c4cb4a bellard
}
21 a0c4cb4a bellard
#endif
22 a0c4cb4a bellard
23 a0c4cb4a bellard
void do_fabss(void)
24 e8af50a3 bellard
{
25 7a0e1f41 bellard
    FT0 = float32_abs(FT1);
26 e8af50a3 bellard
}
27 e8af50a3 bellard
28 3475187d bellard
#ifdef TARGET_SPARC64
29 3475187d bellard
void do_fabsd(void)
30 3475187d bellard
{
31 3475187d bellard
    DT0 = float64_abs(DT1);
32 3475187d bellard
}
33 3475187d bellard
#endif
34 3475187d bellard
35 a0c4cb4a bellard
void do_fsqrts(void)
36 e8af50a3 bellard
{
37 7a0e1f41 bellard
    FT0 = float32_sqrt(FT1, &env->fp_status);
38 e8af50a3 bellard
}
39 e8af50a3 bellard
40 a0c4cb4a bellard
void do_fsqrtd(void)
41 e8af50a3 bellard
{
42 7a0e1f41 bellard
    DT0 = float64_sqrt(DT1, &env->fp_status);
43 e8af50a3 bellard
}
44 e8af50a3 bellard
45 3475187d bellard
#define FS 0
46 a0c4cb4a bellard
void do_fcmps (void)
47 e8af50a3 bellard
{
48 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
49 e8af50a3 bellard
    if (isnan(FT0) || isnan(FT1)) {
50 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
51 e80cfcfc bellard
        if (env->fsr & FSR_NVM) {
52 3475187d bellard
            env->fsr |= T0;
53 e80cfcfc bellard
            raise_exception(TT_FP_EXCP);
54 e80cfcfc bellard
        } else {
55 e80cfcfc bellard
            env->fsr |= FSR_NVA;
56 e80cfcfc bellard
        }
57 e8af50a3 bellard
    } else if (FT0 < FT1) {
58 3475187d bellard
        T0 = FSR_FCC0 << FS;
59 e8af50a3 bellard
    } else if (FT0 > FT1) {
60 3475187d bellard
        T0 = FSR_FCC1 << FS;
61 e8af50a3 bellard
    } else {
62 e8af50a3 bellard
        T0 = 0;
63 e8af50a3 bellard
    }
64 3475187d bellard
    env->fsr |= T0;
65 e8af50a3 bellard
}
66 e8af50a3 bellard
67 a0c4cb4a bellard
void do_fcmpd (void)
68 e8af50a3 bellard
{
69 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
70 3475187d bellard
    if (isnan(DT0) || isnan(DT1)) {
71 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
72 3475187d bellard
        if (env->fsr & FSR_NVM) {
73 3475187d bellard
            env->fsr |= T0;
74 3475187d bellard
            raise_exception(TT_FP_EXCP);
75 3475187d bellard
        } else {
76 3475187d bellard
            env->fsr |= FSR_NVA;
77 3475187d bellard
        }
78 3475187d bellard
    } else if (DT0 < DT1) {
79 3475187d bellard
        T0 = FSR_FCC0 << FS;
80 3475187d bellard
    } else if (DT0 > DT1) {
81 3475187d bellard
        T0 = FSR_FCC1 << FS;
82 3475187d bellard
    } else {
83 3475187d bellard
        T0 = 0;
84 3475187d bellard
    }
85 3475187d bellard
    env->fsr |= T0;
86 3475187d bellard
}
87 3475187d bellard
88 3475187d bellard
#ifdef TARGET_SPARC64
89 3475187d bellard
#undef FS
90 3475187d bellard
#define FS 22
91 3475187d bellard
void do_fcmps_fcc1 (void)
92 3475187d bellard
{
93 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
94 3475187d bellard
    if (isnan(FT0) || isnan(FT1)) {
95 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
96 3475187d bellard
        if (env->fsr & FSR_NVM) {
97 3475187d bellard
            env->fsr |= T0;
98 3475187d bellard
            raise_exception(TT_FP_EXCP);
99 3475187d bellard
        } else {
100 3475187d bellard
            env->fsr |= FSR_NVA;
101 3475187d bellard
        }
102 3475187d bellard
    } else if (FT0 < FT1) {
103 3475187d bellard
        T0 = FSR_FCC0 << FS;
104 3475187d bellard
    } else if (FT0 > FT1) {
105 3475187d bellard
        T0 = FSR_FCC1 << FS;
106 3475187d bellard
    } else {
107 3475187d bellard
        T0 = 0;
108 3475187d bellard
    }
109 3475187d bellard
    env->fsr |= T0;
110 3475187d bellard
}
111 3475187d bellard
112 3475187d bellard
void do_fcmpd_fcc1 (void)
113 3475187d bellard
{
114 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
115 3475187d bellard
    if (isnan(DT0) || isnan(DT1)) {
116 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
117 3475187d bellard
        if (env->fsr & FSR_NVM) {
118 3475187d bellard
            env->fsr |= T0;
119 3475187d bellard
            raise_exception(TT_FP_EXCP);
120 3475187d bellard
        } else {
121 3475187d bellard
            env->fsr |= FSR_NVA;
122 3475187d bellard
        }
123 3475187d bellard
    } else if (DT0 < DT1) {
124 3475187d bellard
        T0 = FSR_FCC0 << FS;
125 3475187d bellard
    } else if (DT0 > DT1) {
126 3475187d bellard
        T0 = FSR_FCC1 << FS;
127 3475187d bellard
    } else {
128 3475187d bellard
        T0 = 0;
129 3475187d bellard
    }
130 3475187d bellard
    env->fsr |= T0;
131 3475187d bellard
}
132 3475187d bellard
133 3475187d bellard
#undef FS
134 3475187d bellard
#define FS 24
135 3475187d bellard
void do_fcmps_fcc2 (void)
136 3475187d bellard
{
137 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
138 3475187d bellard
    if (isnan(FT0) || isnan(FT1)) {
139 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
140 3475187d bellard
        if (env->fsr & FSR_NVM) {
141 3475187d bellard
            env->fsr |= T0;
142 3475187d bellard
            raise_exception(TT_FP_EXCP);
143 3475187d bellard
        } else {
144 3475187d bellard
            env->fsr |= FSR_NVA;
145 3475187d bellard
        }
146 3475187d bellard
    } else if (FT0 < FT1) {
147 3475187d bellard
        T0 = FSR_FCC0 << FS;
148 3475187d bellard
    } else if (FT0 > FT1) {
149 3475187d bellard
        T0 = FSR_FCC1 << FS;
150 3475187d bellard
    } else {
151 3475187d bellard
        T0 = 0;
152 3475187d bellard
    }
153 3475187d bellard
    env->fsr |= T0;
154 3475187d bellard
}
155 3475187d bellard
156 3475187d bellard
void do_fcmpd_fcc2 (void)
157 3475187d bellard
{
158 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
159 e8af50a3 bellard
    if (isnan(DT0) || isnan(DT1)) {
160 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
161 e80cfcfc bellard
        if (env->fsr & FSR_NVM) {
162 3475187d bellard
            env->fsr |= T0;
163 e80cfcfc bellard
            raise_exception(TT_FP_EXCP);
164 e80cfcfc bellard
        } else {
165 e80cfcfc bellard
            env->fsr |= FSR_NVA;
166 e80cfcfc bellard
        }
167 e8af50a3 bellard
    } else if (DT0 < DT1) {
168 3475187d bellard
        T0 = FSR_FCC0 << FS;
169 e8af50a3 bellard
    } else if (DT0 > DT1) {
170 3475187d bellard
        T0 = FSR_FCC1 << FS;
171 3475187d bellard
    } else {
172 3475187d bellard
        T0 = 0;
173 3475187d bellard
    }
174 3475187d bellard
    env->fsr |= T0;
175 3475187d bellard
}
176 3475187d bellard
177 3475187d bellard
#undef FS
178 3475187d bellard
#define FS 26
179 3475187d bellard
void do_fcmps_fcc3 (void)
180 3475187d bellard
{
181 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
182 3475187d bellard
    if (isnan(FT0) || isnan(FT1)) {
183 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
184 3475187d bellard
        if (env->fsr & FSR_NVM) {
185 3475187d bellard
            env->fsr |= T0;
186 3475187d bellard
            raise_exception(TT_FP_EXCP);
187 3475187d bellard
        } else {
188 3475187d bellard
            env->fsr |= FSR_NVA;
189 3475187d bellard
        }
190 3475187d bellard
    } else if (FT0 < FT1) {
191 3475187d bellard
        T0 = FSR_FCC0 << FS;
192 3475187d bellard
    } else if (FT0 > FT1) {
193 3475187d bellard
        T0 = FSR_FCC1 << FS;
194 e8af50a3 bellard
    } else {
195 e8af50a3 bellard
        T0 = 0;
196 e8af50a3 bellard
    }
197 3475187d bellard
    env->fsr |= T0;
198 e8af50a3 bellard
}
199 e8af50a3 bellard
200 3475187d bellard
void do_fcmpd_fcc3 (void)
201 3475187d bellard
{
202 3475187d bellard
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
203 3475187d bellard
    if (isnan(DT0) || isnan(DT1)) {
204 3475187d bellard
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
205 3475187d bellard
        if (env->fsr & FSR_NVM) {
206 3475187d bellard
            env->fsr |= T0;
207 3475187d bellard
            raise_exception(TT_FP_EXCP);
208 3475187d bellard
        } else {
209 3475187d bellard
            env->fsr |= FSR_NVA;
210 3475187d bellard
        }
211 3475187d bellard
    } else if (DT0 < DT1) {
212 3475187d bellard
        T0 = FSR_FCC0 << FS;
213 3475187d bellard
    } else if (DT0 > DT1) {
214 3475187d bellard
        T0 = FSR_FCC1 << FS;
215 3475187d bellard
    } else {
216 3475187d bellard
        T0 = 0;
217 3475187d bellard
    }
218 3475187d bellard
    env->fsr |= T0;
219 3475187d bellard
}
220 3475187d bellard
#undef FS
221 3475187d bellard
#endif
222 3475187d bellard
223 3475187d bellard
#ifndef TARGET_SPARC64
224 a0c4cb4a bellard
void helper_ld_asi(int asi, int size, int sign)
225 e8af50a3 bellard
{
226 e80cfcfc bellard
    uint32_t ret;
227 e80cfcfc bellard
228 e80cfcfc bellard
    switch (asi) {
229 e8af50a3 bellard
    case 3: /* MMU probe */
230 e80cfcfc bellard
        {
231 e80cfcfc bellard
            int mmulev;
232 e80cfcfc bellard
233 e80cfcfc bellard
            mmulev = (T0 >> 8) & 15;
234 e80cfcfc bellard
            if (mmulev > 4)
235 e80cfcfc bellard
                ret = 0;
236 e80cfcfc bellard
            else {
237 ee5bbe38 bellard
                ret = mmu_probe(env, T0, mmulev);
238 e80cfcfc bellard
                //bswap32s(&ret);
239 e80cfcfc bellard
            }
240 e80cfcfc bellard
#ifdef DEBUG_MMU
241 e80cfcfc bellard
            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
242 e80cfcfc bellard
#endif
243 e80cfcfc bellard
        }
244 e80cfcfc bellard
        break;
245 e8af50a3 bellard
    case 4: /* read MMU regs */
246 e8af50a3 bellard
        {
247 e80cfcfc bellard
            int reg = (T0 >> 8) & 0xf;
248 e8af50a3 bellard
            
249 e80cfcfc bellard
            ret = env->mmuregs[reg];
250 55754d9e bellard
            if (reg == 3) /* Fault status cleared on read */
251 55754d9e bellard
                env->mmuregs[reg] = 0;
252 55754d9e bellard
#ifdef DEBUG_MMU
253 55754d9e bellard
            printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
254 55754d9e bellard
#endif
255 e8af50a3 bellard
        }
256 e80cfcfc bellard
        break;
257 e8af50a3 bellard
    case 0x20 ... 0x2f: /* MMU passthrough */
258 e80cfcfc bellard
        cpu_physical_memory_read(T0, (void *) &ret, size);
259 e80cfcfc bellard
        if (size == 4)
260 49be8030 bellard
            tswap32s(&ret);
261 49be8030 bellard
        else if (size == 2)
262 49be8030 bellard
            tswap16s((uint16_t *)&ret);
263 e80cfcfc bellard
        break;
264 e8af50a3 bellard
    default:
265 e80cfcfc bellard
        ret = 0;
266 e80cfcfc bellard
        break;
267 e8af50a3 bellard
    }
268 e80cfcfc bellard
    T1 = ret;
269 e8af50a3 bellard
}
270 e8af50a3 bellard
271 a0c4cb4a bellard
void helper_st_asi(int asi, int size, int sign)
272 e8af50a3 bellard
{
273 e8af50a3 bellard
    switch(asi) {
274 e8af50a3 bellard
    case 3: /* MMU flush */
275 e80cfcfc bellard
        {
276 e80cfcfc bellard
            int mmulev;
277 e80cfcfc bellard
278 e80cfcfc bellard
            mmulev = (T0 >> 8) & 15;
279 55754d9e bellard
#ifdef DEBUG_MMU
280 55754d9e bellard
            printf("mmu flush level %d\n", mmulev);
281 55754d9e bellard
#endif
282 e80cfcfc bellard
            switch (mmulev) {
283 e80cfcfc bellard
            case 0: // flush page
284 55754d9e bellard
                tlb_flush_page(env, T0 & 0xfffff000);
285 e80cfcfc bellard
                break;
286 e80cfcfc bellard
            case 1: // flush segment (256k)
287 e80cfcfc bellard
            case 2: // flush region (16M)
288 e80cfcfc bellard
            case 3: // flush context (4G)
289 e80cfcfc bellard
            case 4: // flush entire
290 55754d9e bellard
                tlb_flush(env, 1);
291 e80cfcfc bellard
                break;
292 e80cfcfc bellard
            default:
293 e80cfcfc bellard
                break;
294 e80cfcfc bellard
            }
295 55754d9e bellard
#ifdef DEBUG_MMU
296 ee5bbe38 bellard
            dump_mmu(env);
297 55754d9e bellard
#endif
298 e80cfcfc bellard
            return;
299 e80cfcfc bellard
        }
300 e8af50a3 bellard
    case 4: /* write MMU regs */
301 e8af50a3 bellard
        {
302 e80cfcfc bellard
            int reg = (T0 >> 8) & 0xf, oldreg;
303 e80cfcfc bellard
            
304 e80cfcfc bellard
            oldreg = env->mmuregs[reg];
305 55754d9e bellard
            switch(reg) {
306 55754d9e bellard
            case 0:
307 e8af50a3 bellard
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
308 e8af50a3 bellard
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
309 6f7e9aec bellard
                // Mappings generated during no-fault mode or MMU
310 6f7e9aec bellard
                // disabled mode are invalid in normal mode
311 6f7e9aec bellard
                if (oldreg != env->mmuregs[reg])
312 55754d9e bellard
                    tlb_flush(env, 1);
313 55754d9e bellard
                break;
314 55754d9e bellard
            case 2:
315 e8af50a3 bellard
                env->mmuregs[reg] = T1;
316 55754d9e bellard
                if (oldreg != env->mmuregs[reg]) {
317 55754d9e bellard
                    /* we flush when the MMU context changes because
318 55754d9e bellard
                       QEMU has no MMU context support */
319 55754d9e bellard
                    tlb_flush(env, 1);
320 55754d9e bellard
                }
321 55754d9e bellard
                break;
322 55754d9e bellard
            case 3:
323 55754d9e bellard
            case 4:
324 55754d9e bellard
                break;
325 55754d9e bellard
            default:
326 55754d9e bellard
                env->mmuregs[reg] = T1;
327 55754d9e bellard
                break;
328 55754d9e bellard
            }
329 55754d9e bellard
#ifdef DEBUG_MMU
330 55754d9e bellard
            if (oldreg != env->mmuregs[reg]) {
331 55754d9e bellard
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
332 55754d9e bellard
            }
333 ee5bbe38 bellard
            dump_mmu(env);
334 55754d9e bellard
#endif
335 e8af50a3 bellard
            return;
336 e8af50a3 bellard
        }
337 e80cfcfc bellard
    case 0x17: /* Block copy, sta access */
338 e80cfcfc bellard
        {
339 e80cfcfc bellard
            // value (T1) = src
340 e80cfcfc bellard
            // address (T0) = dst
341 e80cfcfc bellard
            // copy 32 bytes
342 e80cfcfc bellard
            int src = T1, dst = T0;
343 e80cfcfc bellard
            uint8_t temp[32];
344 e80cfcfc bellard
            
345 49be8030 bellard
            tswap32s(&src);
346 e80cfcfc bellard
347 e80cfcfc bellard
            cpu_physical_memory_read(src, (void *) &temp, 32);
348 e80cfcfc bellard
            cpu_physical_memory_write(dst, (void *) &temp, 32);
349 e80cfcfc bellard
        }
350 e80cfcfc bellard
        return;
351 e80cfcfc bellard
    case 0x1f: /* Block fill, stda access */
352 e80cfcfc bellard
        {
353 e80cfcfc bellard
            // value (T1, T2)
354 e80cfcfc bellard
            // address (T0) = dst
355 e80cfcfc bellard
            // fill 32 bytes
356 e80cfcfc bellard
            int i, dst = T0;
357 e80cfcfc bellard
            uint64_t val;
358 e80cfcfc bellard
            
359 e80cfcfc bellard
            val = (((uint64_t)T1) << 32) | T2;
360 49be8030 bellard
            tswap64s(&val);
361 e80cfcfc bellard
362 e80cfcfc bellard
            for (i = 0; i < 32; i += 8, dst += 8) {
363 e80cfcfc bellard
                cpu_physical_memory_write(dst, (void *) &val, 8);
364 e80cfcfc bellard
            }
365 e80cfcfc bellard
        }
366 e80cfcfc bellard
        return;
367 e8af50a3 bellard
    case 0x20 ... 0x2f: /* MMU passthrough */
368 e8af50a3 bellard
        {
369 e8af50a3 bellard
            int temp = T1;
370 e80cfcfc bellard
            if (size == 4)
371 49be8030 bellard
                tswap32s(&temp);
372 e80cfcfc bellard
            else if (size == 2)
373 49be8030 bellard
                tswap16s((uint16_t *)&temp);
374 e8af50a3 bellard
            cpu_physical_memory_write(T0, (void *) &temp, size);
375 e8af50a3 bellard
        }
376 e8af50a3 bellard
        return;
377 e8af50a3 bellard
    default:
378 e8af50a3 bellard
        return;
379 e8af50a3 bellard
    }
380 e8af50a3 bellard
}
381 e8af50a3 bellard
382 3475187d bellard
#else
383 3475187d bellard
384 3475187d bellard
void helper_ld_asi(int asi, int size, int sign)
385 3475187d bellard
{
386 3475187d bellard
    uint64_t ret;
387 3475187d bellard
388 3475187d bellard
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
389 3475187d bellard
        raise_exception(TT_PRIV_INSN);
390 3475187d bellard
391 3475187d bellard
    switch (asi) {
392 3475187d bellard
    case 0x14: // Bypass
393 3475187d bellard
    case 0x15: // Bypass, non-cacheable
394 3475187d bellard
        {
395 3475187d bellard
            cpu_physical_memory_read(T0, (void *) &ret, size);
396 3475187d bellard
            if (size == 8)
397 3475187d bellard
                tswap64s(&ret);
398 3475187d bellard
            if (size == 4)
399 3475187d bellard
                tswap32s((uint32_t *)&ret);
400 3475187d bellard
            else if (size == 2)
401 3475187d bellard
                tswap16s((uint16_t *)&ret);
402 3475187d bellard
            break;
403 3475187d bellard
        }
404 3475187d bellard
    case 0x1c: // Bypass LE
405 3475187d bellard
    case 0x1d: // Bypass, non-cacheable LE
406 3475187d bellard
        // XXX
407 3475187d bellard
        break;
408 3475187d bellard
    case 0x45: // LSU
409 3475187d bellard
        ret = env->lsu;
410 3475187d bellard
        break;
411 3475187d bellard
    case 0x50: // I-MMU regs
412 3475187d bellard
        {
413 3475187d bellard
            int reg = (T0 >> 3) & 0xf;
414 3475187d bellard
415 3475187d bellard
            ret = env->immuregs[reg];
416 3475187d bellard
            break;
417 3475187d bellard
        }
418 3475187d bellard
    case 0x51: // I-MMU 8k TSB pointer
419 3475187d bellard
    case 0x52: // I-MMU 64k TSB pointer
420 3475187d bellard
    case 0x55: // I-MMU data access
421 3475187d bellard
    case 0x56: // I-MMU tag read
422 3475187d bellard
        break;
423 3475187d bellard
    case 0x58: // D-MMU regs
424 3475187d bellard
        {
425 3475187d bellard
            int reg = (T0 >> 3) & 0xf;
426 3475187d bellard
427 3475187d bellard
            ret = env->dmmuregs[reg];
428 3475187d bellard
            break;
429 3475187d bellard
        }
430 3475187d bellard
    case 0x59: // D-MMU 8k TSB pointer
431 3475187d bellard
    case 0x5a: // D-MMU 64k TSB pointer
432 3475187d bellard
    case 0x5b: // D-MMU data pointer
433 3475187d bellard
    case 0x5d: // D-MMU data access
434 3475187d bellard
    case 0x5e: // D-MMU tag read
435 3475187d bellard
        break;
436 3475187d bellard
    case 0x54: // I-MMU data in, WO
437 3475187d bellard
    case 0x57: // I-MMU demap, WO
438 3475187d bellard
    case 0x5c: // D-MMU data in, WO
439 3475187d bellard
    case 0x5f: // D-MMU demap, WO
440 3475187d bellard
    default:
441 3475187d bellard
        ret = 0;
442 3475187d bellard
        break;
443 3475187d bellard
    }
444 3475187d bellard
    T1 = ret;
445 3475187d bellard
}
446 3475187d bellard
447 3475187d bellard
void helper_st_asi(int asi, int size, int sign)
448 3475187d bellard
{
449 3475187d bellard
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
450 3475187d bellard
        raise_exception(TT_PRIV_INSN);
451 3475187d bellard
452 3475187d bellard
    switch(asi) {
453 3475187d bellard
    case 0x14: // Bypass
454 3475187d bellard
    case 0x15: // Bypass, non-cacheable
455 3475187d bellard
        {
456 3475187d bellard
            target_ulong temp = T1;
457 3475187d bellard
            if (size == 8)
458 3475187d bellard
                tswap64s(&temp);
459 3475187d bellard
            else if (size == 4)
460 3475187d bellard
                tswap32s((uint32_t *)&temp);
461 3475187d bellard
            else if (size == 2)
462 3475187d bellard
                tswap16s((uint16_t *)&temp);
463 3475187d bellard
            cpu_physical_memory_write(T0, (void *) &temp, size);
464 3475187d bellard
        }
465 3475187d bellard
        return;
466 3475187d bellard
    case 0x1c: // Bypass LE
467 3475187d bellard
    case 0x1d: // Bypass, non-cacheable LE
468 3475187d bellard
        // XXX
469 3475187d bellard
        return;
470 3475187d bellard
    case 0x45: // LSU
471 3475187d bellard
        {
472 3475187d bellard
            uint64_t oldreg;
473 3475187d bellard
474 3475187d bellard
            oldreg = env->lsu;
475 3475187d bellard
            env->lsu = T1 & (DMMU_E | IMMU_E);
476 3475187d bellard
            // Mappings generated during D/I MMU disabled mode are
477 3475187d bellard
            // invalid in normal mode
478 3475187d bellard
            if (oldreg != env->lsu)
479 3475187d bellard
                tlb_flush(env, 1);
480 3475187d bellard
            return;
481 3475187d bellard
        }
482 3475187d bellard
    case 0x50: // I-MMU regs
483 3475187d bellard
        {
484 3475187d bellard
            int reg = (T0 >> 3) & 0xf;
485 3475187d bellard
            uint64_t oldreg;
486 3475187d bellard
            
487 3475187d bellard
            oldreg = env->immuregs[reg];
488 3475187d bellard
            switch(reg) {
489 3475187d bellard
            case 0: // RO
490 3475187d bellard
            case 4:
491 3475187d bellard
                return;
492 3475187d bellard
            case 1: // Not in I-MMU
493 3475187d bellard
            case 2:
494 3475187d bellard
            case 7:
495 3475187d bellard
            case 8:
496 3475187d bellard
                return;
497 3475187d bellard
            case 3: // SFSR
498 3475187d bellard
                if ((T1 & 1) == 0)
499 3475187d bellard
                    T1 = 0; // Clear SFSR
500 3475187d bellard
                break;
501 3475187d bellard
            case 5: // TSB access
502 3475187d bellard
            case 6: // Tag access
503 3475187d bellard
            default:
504 3475187d bellard
                break;
505 3475187d bellard
            }
506 3475187d bellard
            env->immuregs[reg] = T1;
507 3475187d bellard
#ifdef DEBUG_MMU
508 3475187d bellard
            if (oldreg != env->immuregs[reg]) {
509 3475187d bellard
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]);
510 3475187d bellard
            }
511 ee5bbe38 bellard
            dump_mmu(env);
512 3475187d bellard
#endif
513 3475187d bellard
            return;
514 3475187d bellard
        }
515 3475187d bellard
    case 0x54: // I-MMU data in
516 3475187d bellard
        {
517 3475187d bellard
            unsigned int i;
518 3475187d bellard
519 3475187d bellard
            // Try finding an invalid entry
520 3475187d bellard
            for (i = 0; i < 64; i++) {
521 3475187d bellard
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
522 3475187d bellard
                    env->itlb_tag[i] = env->immuregs[6];
523 3475187d bellard
                    env->itlb_tte[i] = T1;
524 3475187d bellard
                    return;
525 3475187d bellard
                }
526 3475187d bellard
            }
527 3475187d bellard
            // Try finding an unlocked entry
528 3475187d bellard
            for (i = 0; i < 64; i++) {
529 3475187d bellard
                if ((env->itlb_tte[i] & 0x40) == 0) {
530 3475187d bellard
                    env->itlb_tag[i] = env->immuregs[6];
531 3475187d bellard
                    env->itlb_tte[i] = T1;
532 3475187d bellard
                    return;
533 3475187d bellard
                }
534 3475187d bellard
            }
535 3475187d bellard
            // error state?
536 3475187d bellard
            return;
537 3475187d bellard
        }
538 3475187d bellard
    case 0x55: // I-MMU data access
539 3475187d bellard
        {
540 3475187d bellard
            unsigned int i = (T0 >> 3) & 0x3f;
541 3475187d bellard
542 3475187d bellard
            env->itlb_tag[i] = env->immuregs[6];
543 3475187d bellard
            env->itlb_tte[i] = T1;
544 3475187d bellard
            return;
545 3475187d bellard
        }
546 3475187d bellard
    case 0x57: // I-MMU demap
547 3475187d bellard
        return;
548 3475187d bellard
    case 0x58: // D-MMU regs
549 3475187d bellard
        {
550 3475187d bellard
            int reg = (T0 >> 3) & 0xf;
551 3475187d bellard
            uint64_t oldreg;
552 3475187d bellard
            
553 3475187d bellard
            oldreg = env->dmmuregs[reg];
554 3475187d bellard
            switch(reg) {
555 3475187d bellard
            case 0: // RO
556 3475187d bellard
            case 4:
557 3475187d bellard
                return;
558 3475187d bellard
            case 3: // SFSR
559 3475187d bellard
                if ((T1 & 1) == 0) {
560 3475187d bellard
                    T1 = 0; // Clear SFSR, Fault address
561 3475187d bellard
                    env->dmmuregs[4] = 0;
562 3475187d bellard
                }
563 3475187d bellard
                env->dmmuregs[reg] = T1;
564 3475187d bellard
                break;
565 3475187d bellard
            case 1: // Primary context
566 3475187d bellard
            case 2: // Secondary context
567 3475187d bellard
            case 5: // TSB access
568 3475187d bellard
            case 6: // Tag access
569 3475187d bellard
            case 7: // Virtual Watchpoint
570 3475187d bellard
            case 8: // Physical Watchpoint
571 3475187d bellard
            default:
572 3475187d bellard
                break;
573 3475187d bellard
            }
574 3475187d bellard
            env->dmmuregs[reg] = T1;
575 3475187d bellard
#ifdef DEBUG_MMU
576 3475187d bellard
            if (oldreg != env->dmmuregs[reg]) {
577 3475187d bellard
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]);
578 3475187d bellard
            }
579 ee5bbe38 bellard
            dump_mmu(env);
580 3475187d bellard
#endif
581 3475187d bellard
            return;
582 3475187d bellard
        }
583 3475187d bellard
    case 0x5c: // D-MMU data in
584 3475187d bellard
        {
585 3475187d bellard
            unsigned int i;
586 3475187d bellard
587 3475187d bellard
            // Try finding an invalid entry
588 3475187d bellard
            for (i = 0; i < 64; i++) {
589 3475187d bellard
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
590 3475187d bellard
                    env->dtlb_tag[i] = env->dmmuregs[6];
591 3475187d bellard
                    env->dtlb_tte[i] = T1;
592 3475187d bellard
                    return;
593 3475187d bellard
                }
594 3475187d bellard
            }
595 3475187d bellard
            // Try finding an unlocked entry
596 3475187d bellard
            for (i = 0; i < 64; i++) {
597 3475187d bellard
                if ((env->dtlb_tte[i] & 0x40) == 0) {
598 3475187d bellard
                    env->dtlb_tag[i] = env->dmmuregs[6];
599 3475187d bellard
                    env->dtlb_tte[i] = T1;
600 3475187d bellard
                    return;
601 3475187d bellard
                }
602 3475187d bellard
            }
603 3475187d bellard
            // error state?
604 3475187d bellard
            return;
605 3475187d bellard
        }
606 3475187d bellard
    case 0x5d: // D-MMU data access
607 3475187d bellard
        {
608 3475187d bellard
            unsigned int i = (T0 >> 3) & 0x3f;
609 3475187d bellard
610 3475187d bellard
            env->dtlb_tag[i] = env->dmmuregs[6];
611 3475187d bellard
            env->dtlb_tte[i] = T1;
612 3475187d bellard
            return;
613 3475187d bellard
        }
614 3475187d bellard
    case 0x5f: // D-MMU demap
615 3475187d bellard
        return;
616 3475187d bellard
    case 0x51: // I-MMU 8k TSB pointer, RO
617 3475187d bellard
    case 0x52: // I-MMU 64k TSB pointer, RO
618 3475187d bellard
    case 0x56: // I-MMU tag read, RO
619 3475187d bellard
    case 0x59: // D-MMU 8k TSB pointer, RO
620 3475187d bellard
    case 0x5a: // D-MMU 64k TSB pointer, RO
621 3475187d bellard
    case 0x5b: // D-MMU data pointer, RO
622 3475187d bellard
    case 0x5e: // D-MMU tag read, RO
623 3475187d bellard
    default:
624 3475187d bellard
        return;
625 3475187d bellard
    }
626 3475187d bellard
}
627 3475187d bellard
628 3475187d bellard
#endif
629 3475187d bellard
630 3475187d bellard
#ifndef TARGET_SPARC64
631 a0c4cb4a bellard
void helper_rett()
632 e8af50a3 bellard
{
633 af7bf89b bellard
    unsigned int cwp;
634 af7bf89b bellard
635 e8af50a3 bellard
    env->psret = 1;
636 e8af50a3 bellard
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
637 e8af50a3 bellard
    if (env->wim & (1 << cwp)) {
638 e8af50a3 bellard
        raise_exception(TT_WIN_UNF);
639 e8af50a3 bellard
    }
640 e8af50a3 bellard
    set_cwp(cwp);
641 e8af50a3 bellard
    env->psrs = env->psrps;
642 e8af50a3 bellard
}
643 3475187d bellard
#endif
644 e8af50a3 bellard
645 8d5f07fa bellard
void helper_ldfsr(void)
646 e8af50a3 bellard
{
647 7a0e1f41 bellard
    int rnd_mode;
648 e8af50a3 bellard
    switch (env->fsr & FSR_RD_MASK) {
649 e8af50a3 bellard
    case FSR_RD_NEAREST:
650 7a0e1f41 bellard
        rnd_mode = float_round_nearest_even;
651 e8af50a3 bellard
        break;
652 ed910241 bellard
    default:
653 e8af50a3 bellard
    case FSR_RD_ZERO:
654 7a0e1f41 bellard
        rnd_mode = float_round_to_zero;
655 e8af50a3 bellard
        break;
656 e8af50a3 bellard
    case FSR_RD_POS:
657 7a0e1f41 bellard
        rnd_mode = float_round_up;
658 e8af50a3 bellard
        break;
659 e8af50a3 bellard
    case FSR_RD_NEG:
660 7a0e1f41 bellard
        rnd_mode = float_round_down;
661 e8af50a3 bellard
        break;
662 e8af50a3 bellard
    }
663 7a0e1f41 bellard
    set_float_rounding_mode(rnd_mode, &env->fp_status);
664 e8af50a3 bellard
}
665 e80cfcfc bellard
666 e80cfcfc bellard
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
667 e80cfcfc bellard
{
668 e80cfcfc bellard
    int exptemp;
669 e80cfcfc bellard
670 e80cfcfc bellard
    *pmant = ldexp(frexp(f, &exptemp), 53);
671 e80cfcfc bellard
    *pexp = exptemp;
672 e80cfcfc bellard
}
673 e80cfcfc bellard
674 e80cfcfc bellard
double cpu_put_fp64(uint64_t mant, uint16_t exp)
675 e80cfcfc bellard
{
676 e80cfcfc bellard
    return ldexp((double) mant, exp - 53);
677 e80cfcfc bellard
}
678 e80cfcfc bellard
679 e80cfcfc bellard
void helper_debug()
680 e80cfcfc bellard
{
681 e80cfcfc bellard
    env->exception_index = EXCP_DEBUG;
682 e80cfcfc bellard
    cpu_loop_exit();
683 e80cfcfc bellard
}
684 af7bf89b bellard
685 3475187d bellard
#ifndef TARGET_SPARC64
686 af7bf89b bellard
void do_wrpsr()
687 af7bf89b bellard
{
688 af7bf89b bellard
    PUT_PSR(env, T0);
689 af7bf89b bellard
}
690 af7bf89b bellard
691 af7bf89b bellard
void do_rdpsr()
692 af7bf89b bellard
{
693 af7bf89b bellard
    T0 = GET_PSR(env);
694 af7bf89b bellard
}
695 3475187d bellard
696 3475187d bellard
#else
697 3475187d bellard
698 3475187d bellard
void do_popc()
699 3475187d bellard
{
700 3475187d bellard
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
701 3475187d bellard
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
702 3475187d bellard
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
703 3475187d bellard
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
704 3475187d bellard
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
705 3475187d bellard
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
706 3475187d bellard
}
707 3475187d bellard
#endif
708 ee5bbe38 bellard
709 ee5bbe38 bellard
void set_cwp(int new_cwp)
710 ee5bbe38 bellard
{
711 ee5bbe38 bellard
    /* put the modified wrap registers at their proper location */
712 ee5bbe38 bellard
    if (env->cwp == (NWINDOWS - 1))
713 ee5bbe38 bellard
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
714 ee5bbe38 bellard
    env->cwp = new_cwp;
715 ee5bbe38 bellard
    /* put the wrap registers at their temporary location */
716 ee5bbe38 bellard
    if (new_cwp == (NWINDOWS - 1))
717 ee5bbe38 bellard
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
718 ee5bbe38 bellard
    env->regwptr = env->regbase + (new_cwp * 16);
719 ee5bbe38 bellard
    REGWPTR = env->regwptr;
720 ee5bbe38 bellard
}
721 ee5bbe38 bellard
722 ee5bbe38 bellard
void cpu_set_cwp(CPUState *env1, int new_cwp)
723 ee5bbe38 bellard
{
724 ee5bbe38 bellard
    CPUState *saved_env;
725 ee5bbe38 bellard
#ifdef reg_REGWPTR
726 ee5bbe38 bellard
    target_ulong *saved_regwptr;
727 ee5bbe38 bellard
#endif
728 ee5bbe38 bellard
729 ee5bbe38 bellard
    saved_env = env;
730 ee5bbe38 bellard
#ifdef reg_REGWPTR
731 ee5bbe38 bellard
    saved_regwptr = REGWPTR;
732 ee5bbe38 bellard
#endif
733 ee5bbe38 bellard
    env = env1;
734 ee5bbe38 bellard
    set_cwp(new_cwp);
735 ee5bbe38 bellard
    env = saved_env;
736 ee5bbe38 bellard
#ifdef reg_REGWPTR
737 ee5bbe38 bellard
    REGWPTR = saved_regwptr;
738 ee5bbe38 bellard
#endif
739 ee5bbe38 bellard
}
740 ee5bbe38 bellard
741 ee5bbe38 bellard
#ifdef TARGET_SPARC64
742 ee5bbe38 bellard
void do_interrupt(int intno)
743 ee5bbe38 bellard
{
744 ee5bbe38 bellard
#ifdef DEBUG_PCALL
745 ee5bbe38 bellard
    if (loglevel & CPU_LOG_INT) {
746 ee5bbe38 bellard
        static int count;
747 ee5bbe38 bellard
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
748 ee5bbe38 bellard
                count, intno,
749 ee5bbe38 bellard
                env->pc,
750 ee5bbe38 bellard
                env->npc, env->regwptr[6]);
751 ee5bbe38 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
752 ee5bbe38 bellard
#if 0
753 ee5bbe38 bellard
        {
754 ee5bbe38 bellard
            int i;
755 ee5bbe38 bellard
            uint8_t *ptr;
756 ee5bbe38 bellard

757 ee5bbe38 bellard
            fprintf(logfile, "       code=");
758 ee5bbe38 bellard
            ptr = (uint8_t *)env->pc;
759 ee5bbe38 bellard
            for(i = 0; i < 16; i++) {
760 ee5bbe38 bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
761 ee5bbe38 bellard
            }
762 ee5bbe38 bellard
            fprintf(logfile, "\n");
763 ee5bbe38 bellard
        }
764 ee5bbe38 bellard
#endif
765 ee5bbe38 bellard
        count++;
766 ee5bbe38 bellard
    }
767 ee5bbe38 bellard
#endif
768 ee5bbe38 bellard
#if !defined(CONFIG_USER_ONLY) 
769 ee5bbe38 bellard
    if (env->pstate & PS_IE) {
770 ee5bbe38 bellard
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
771 ee5bbe38 bellard
        return;
772 ee5bbe38 bellard
    }
773 ee5bbe38 bellard
#endif
774 ee5bbe38 bellard
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
775 ee5bbe38 bellard
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
776 ee5bbe38 bellard
    env->tpc[env->tl] = env->pc;
777 ee5bbe38 bellard
    env->tnpc[env->tl] = env->npc;
778 ee5bbe38 bellard
    env->tt[env->tl] = intno;
779 ee5bbe38 bellard
    env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4);
780 ee5bbe38 bellard
    env->tl++;
781 ee5bbe38 bellard
    env->pc = env->tbr;
782 ee5bbe38 bellard
    env->npc = env->pc + 4;
783 ee5bbe38 bellard
    env->exception_index = 0;
784 ee5bbe38 bellard
}
785 ee5bbe38 bellard
#else
786 ee5bbe38 bellard
void do_interrupt(int intno)
787 ee5bbe38 bellard
{
788 ee5bbe38 bellard
    int cwp;
789 ee5bbe38 bellard
790 ee5bbe38 bellard
#ifdef DEBUG_PCALL
791 ee5bbe38 bellard
    if (loglevel & CPU_LOG_INT) {
792 ee5bbe38 bellard
        static int count;
793 ee5bbe38 bellard
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
794 ee5bbe38 bellard
                count, intno,
795 ee5bbe38 bellard
                env->pc,
796 ee5bbe38 bellard
                env->npc, env->regwptr[6]);
797 ee5bbe38 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
798 ee5bbe38 bellard
#if 0
799 ee5bbe38 bellard
        {
800 ee5bbe38 bellard
            int i;
801 ee5bbe38 bellard
            uint8_t *ptr;
802 ee5bbe38 bellard

803 ee5bbe38 bellard
            fprintf(logfile, "       code=");
804 ee5bbe38 bellard
            ptr = (uint8_t *)env->pc;
805 ee5bbe38 bellard
            for(i = 0; i < 16; i++) {
806 ee5bbe38 bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
807 ee5bbe38 bellard
            }
808 ee5bbe38 bellard
            fprintf(logfile, "\n");
809 ee5bbe38 bellard
        }
810 ee5bbe38 bellard
#endif
811 ee5bbe38 bellard
        count++;
812 ee5bbe38 bellard
    }
813 ee5bbe38 bellard
#endif
814 ee5bbe38 bellard
#if !defined(CONFIG_USER_ONLY) 
815 ee5bbe38 bellard
    if (env->psret == 0) {
816 ee5bbe38 bellard
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
817 ee5bbe38 bellard
        return;
818 ee5bbe38 bellard
    }
819 ee5bbe38 bellard
#endif
820 ee5bbe38 bellard
    env->psret = 0;
821 ee5bbe38 bellard
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
822 ee5bbe38 bellard
    set_cwp(cwp);
823 ee5bbe38 bellard
    env->regwptr[9] = env->pc;
824 ee5bbe38 bellard
    env->regwptr[10] = env->npc;
825 ee5bbe38 bellard
    env->psrps = env->psrs;
826 ee5bbe38 bellard
    env->psrs = 1;
827 ee5bbe38 bellard
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
828 ee5bbe38 bellard
    env->pc = env->tbr;
829 ee5bbe38 bellard
    env->npc = env->pc + 4;
830 ee5bbe38 bellard
    env->exception_index = 0;
831 ee5bbe38 bellard
}
832 ee5bbe38 bellard
#endif
833 ee5bbe38 bellard
834 ee5bbe38 bellard
#if !defined(CONFIG_USER_ONLY) 
835 ee5bbe38 bellard
836 ee5bbe38 bellard
#define MMUSUFFIX _mmu
837 ee5bbe38 bellard
#define GETPC() (__builtin_return_address(0))
838 ee5bbe38 bellard
839 ee5bbe38 bellard
#define SHIFT 0
840 ee5bbe38 bellard
#include "softmmu_template.h"
841 ee5bbe38 bellard
842 ee5bbe38 bellard
#define SHIFT 1
843 ee5bbe38 bellard
#include "softmmu_template.h"
844 ee5bbe38 bellard
845 ee5bbe38 bellard
#define SHIFT 2
846 ee5bbe38 bellard
#include "softmmu_template.h"
847 ee5bbe38 bellard
848 ee5bbe38 bellard
#define SHIFT 3
849 ee5bbe38 bellard
#include "softmmu_template.h"
850 ee5bbe38 bellard
851 ee5bbe38 bellard
852 ee5bbe38 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
853 ee5bbe38 bellard
   NULL, it means that the function was called in C code (i.e. not
854 ee5bbe38 bellard
   from generated code or from helper.c) */
855 ee5bbe38 bellard
/* XXX: fix it to restore all registers */
856 ee5bbe38 bellard
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
857 ee5bbe38 bellard
{
858 ee5bbe38 bellard
    TranslationBlock *tb;
859 ee5bbe38 bellard
    int ret;
860 ee5bbe38 bellard
    unsigned long pc;
861 ee5bbe38 bellard
    CPUState *saved_env;
862 ee5bbe38 bellard
863 ee5bbe38 bellard
    /* XXX: hack to restore env in all cases, even if not called from
864 ee5bbe38 bellard
       generated code */
865 ee5bbe38 bellard
    saved_env = env;
866 ee5bbe38 bellard
    env = cpu_single_env;
867 ee5bbe38 bellard
868 ee5bbe38 bellard
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
869 ee5bbe38 bellard
    if (ret) {
870 ee5bbe38 bellard
        if (retaddr) {
871 ee5bbe38 bellard
            /* now we have a real cpu fault */
872 ee5bbe38 bellard
            pc = (unsigned long)retaddr;
873 ee5bbe38 bellard
            tb = tb_find_pc(pc);
874 ee5bbe38 bellard
            if (tb) {
875 ee5bbe38 bellard
                /* the PC is inside the translated code. It means that we have
876 ee5bbe38 bellard
                   a virtual CPU fault */
877 ee5bbe38 bellard
                cpu_restore_state(tb, env, pc, (void *)T2);
878 ee5bbe38 bellard
            }
879 ee5bbe38 bellard
        }
880 ee5bbe38 bellard
        cpu_loop_exit();
881 ee5bbe38 bellard
    }
882 ee5bbe38 bellard
    env = saved_env;
883 ee5bbe38 bellard
}
884 ee5bbe38 bellard
885 ee5bbe38 bellard
#endif