]> git.proxmox.com Git - qemu.git/blame - target-sparc/op_helper.c
Add MXCC module reset register (Robert Reif)
[qemu.git] / target-sparc / op_helper.c
CommitLineData
e8af50a3 1#include "exec.h"
eed152bb 2#include "host-utils.h"
e8af50a3 3
83469015 4//#define DEBUG_PCALL
e80cfcfc 5//#define DEBUG_MMU
952a328f 6//#define DEBUG_MXCC
94554550 7//#define DEBUG_UNALIGNED
6c36d3fa 8//#define DEBUG_UNASSIGNED
e80cfcfc 9
952a328f
BS
10#ifdef DEBUG_MMU
11#define DPRINTF_MMU(fmt, args...) \
12do { printf("MMU: " fmt , ##args); } while (0)
13#else
14#define DPRINTF_MMU(fmt, args...)
15#endif
16
17#ifdef DEBUG_MXCC
18#define DPRINTF_MXCC(fmt, args...) \
19do { printf("MXCC: " fmt , ##args); } while (0)
20#else
21#define DPRINTF_MXCC(fmt, args...)
22#endif
23
9d893301
FB
24void raise_exception(int tt)
25{
26 env->exception_index = tt;
27 cpu_loop_exit();
3b46e624 28}
9d893301 29
417454b0
BS
30void check_ieee_exceptions()
31{
32 T0 = get_float_exception_flags(&env->fp_status);
33 if (T0)
34 {
0f8a249a
BS
35 /* Copy IEEE 754 flags into FSR */
36 if (T0 & float_flag_invalid)
37 env->fsr |= FSR_NVC;
38 if (T0 & float_flag_overflow)
39 env->fsr |= FSR_OFC;
40 if (T0 & float_flag_underflow)
41 env->fsr |= FSR_UFC;
42 if (T0 & float_flag_divbyzero)
43 env->fsr |= FSR_DZC;
44 if (T0 & float_flag_inexact)
45 env->fsr |= FSR_NXC;
46
47 if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
48 {
49 /* Unmasked exception, generate a trap */
50 env->fsr |= FSR_FTT_IEEE_EXCP;
51 raise_exception(TT_FP_EXCP);
52 }
53 else
54 {
55 /* Accumulate exceptions */
56 env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
57 }
417454b0
BS
58 }
59}
60
a0c4cb4a
FB
61#ifdef USE_INT_TO_FLOAT_HELPERS
62void do_fitos(void)
63{
417454b0 64 set_float_exception_flags(0, &env->fp_status);
ec230928 65 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
417454b0 66 check_ieee_exceptions();
a0c4cb4a
FB
67}
68
69void do_fitod(void)
70{
ec230928 71 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
a0c4cb4a 72}
1e64e78d
BS
73#ifdef TARGET_SPARC64
74void do_fxtos(void)
75{
76 set_float_exception_flags(0, &env->fp_status);
77 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
78 check_ieee_exceptions();
79}
80
81void do_fxtod(void)
82{
83 set_float_exception_flags(0, &env->fp_status);
84 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
85 check_ieee_exceptions();
86}
87#endif
a0c4cb4a
FB
88#endif
89
90void do_fabss(void)
e8af50a3 91{
7a0e1f41 92 FT0 = float32_abs(FT1);
e8af50a3
FB
93}
94
3475187d
FB
95#ifdef TARGET_SPARC64
96void do_fabsd(void)
97{
98 DT0 = float64_abs(DT1);
99}
100#endif
101
a0c4cb4a 102void do_fsqrts(void)
e8af50a3 103{
417454b0 104 set_float_exception_flags(0, &env->fp_status);
7a0e1f41 105 FT0 = float32_sqrt(FT1, &env->fp_status);
417454b0 106 check_ieee_exceptions();
e8af50a3
FB
107}
108
a0c4cb4a 109void do_fsqrtd(void)
e8af50a3 110{
417454b0 111 set_float_exception_flags(0, &env->fp_status);
7a0e1f41 112 DT0 = float64_sqrt(DT1, &env->fp_status);
417454b0 113 check_ieee_exceptions();
e8af50a3
FB
114}
115
417454b0 116#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
65ce8c2f
FB
117 void glue(do_, name) (void) \
118 { \
119 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
120 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
121 case float_relation_unordered: \
122 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
417454b0 123 if ((env->fsr & FSR_NVM) || TRAP) { \
65ce8c2f 124 env->fsr |= T0; \
417454b0
BS
125 env->fsr |= FSR_NVC; \
126 env->fsr |= FSR_FTT_IEEE_EXCP; \
65ce8c2f
FB
127 raise_exception(TT_FP_EXCP); \
128 } else { \
129 env->fsr |= FSR_NVA; \
130 } \
131 break; \
132 case float_relation_less: \
133 T0 = FSR_FCC0 << FS; \
134 break; \
135 case float_relation_greater: \
136 T0 = FSR_FCC1 << FS; \
137 break; \
138 default: \
139 T0 = 0; \
140 break; \
141 } \
142 env->fsr |= T0; \
e8af50a3 143 }
e8af50a3 144
417454b0
BS
145GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
146GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
147
148GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
149GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
3475187d
FB
150
151#ifdef TARGET_SPARC64
417454b0
BS
152GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
153GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
154
155GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
156GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
157
158GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
159GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
160
161GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
162GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
3475187d 163
417454b0
BS
164GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
165GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
3475187d 166
417454b0
BS
167GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
168GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
3475187d
FB
169#endif
170
171#ifndef TARGET_SPARC64
81ad8ba2 172#ifndef CONFIG_USER_ONLY
952a328f
BS
173
174#ifdef DEBUG_MXCC
175static void dump_mxcc(CPUState *env)
176{
177 printf("mxccdata: %016llx %016llx %016llx %016llx\n",
178 env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
179 printf("mxccregs: %016llx %016llx %016llx %016llx\n"
180 " %016llx %016llx %016llx %016llx\n",
181 env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
182 env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
183}
184#endif
185
a0c4cb4a 186void helper_ld_asi(int asi, int size, int sign)
e8af50a3 187{
83469015 188 uint32_t ret = 0;
e909ec2f 189 uint64_t tmp;
952a328f
BS
190#ifdef DEBUG_MXCC
191 uint32_t last_T0 = T0;
192#endif
e80cfcfc
FB
193
194 switch (asi) {
6c36d3fa 195 case 2: /* SuperSparc MXCC registers */
952a328f
BS
196 switch (T0) {
197 case 0x01c00a00: /* MXCC control register */
198 if (size == 8) {
199 ret = env->mxccregs[3];
200 T0 = env->mxccregs[3] >> 32;
201 } else
202 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
203 break;
204 case 0x01c00a04: /* MXCC control register */
205 if (size == 4)
206 ret = env->mxccregs[3];
207 else
208 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
209 break;
295db113
BS
210 case 0x01c00c00: /* Module reset register */
211 if (size == 8) {
212 ret = env->mxccregs[5] >> 32;
213 T0 = env->mxccregs[5];
214 // should we do something here?
215 } else
216 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
217 break;
952a328f
BS
218 case 0x01c00f00: /* MBus port address register */
219 if (size == 8) {
220 ret = env->mxccregs[7];
221 T0 = env->mxccregs[7] >> 32;
222 } else
223 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
224 break;
225 default:
226 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
227 break;
228 }
229 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
230 "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
231#ifdef DEBUG_MXCC
232 dump_mxcc(env);
233#endif
6c36d3fa 234 break;
e8af50a3 235 case 3: /* MMU probe */
0f8a249a
BS
236 {
237 int mmulev;
238
239 mmulev = (T0 >> 8) & 15;
240 if (mmulev > 4)
241 ret = 0;
242 else {
243 ret = mmu_probe(env, T0, mmulev);
244 //bswap32s(&ret);
245 }
952a328f 246 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
0f8a249a
BS
247 }
248 break;
e8af50a3 249 case 4: /* read MMU regs */
0f8a249a
BS
250 {
251 int reg = (T0 >> 8) & 0xf;
3b46e624 252
0f8a249a
BS
253 ret = env->mmuregs[reg];
254 if (reg == 3) /* Fault status cleared on read */
255 env->mmuregs[reg] = 0;
952a328f 256 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
0f8a249a
BS
257 }
258 break;
6c36d3fa
BS
259 case 9: /* Supervisor code access */
260 switch(size) {
261 case 1:
262 ret = ldub_code(T0);
263 break;
264 case 2:
265 ret = lduw_code(T0 & ~1);
266 break;
267 default:
268 case 4:
269 ret = ldl_code(T0 & ~3);
270 break;
271 case 8:
e909ec2f
BS
272 tmp = ldq_code(T0 & ~7);
273 ret = tmp >> 32;
274 T0 = tmp & 0xffffffff;
6c36d3fa
BS
275 break;
276 }
277 break;
81ad8ba2
BS
278 case 0xa: /* User data access */
279 switch(size) {
280 case 1:
281 ret = ldub_user(T0);
282 break;
283 case 2:
284 ret = lduw_user(T0 & ~1);
285 break;
286 default:
287 case 4:
288 ret = ldl_user(T0 & ~3);
289 break;
290 case 8:
e909ec2f
BS
291 tmp = ldq_user(T0 & ~7);
292 ret = tmp >> 32;
293 T0 = tmp & 0xffffffff;
81ad8ba2
BS
294 break;
295 }
296 break;
297 case 0xb: /* Supervisor data access */
298 switch(size) {
299 case 1:
300 ret = ldub_kernel(T0);
301 break;
302 case 2:
303 ret = lduw_kernel(T0 & ~1);
304 break;
305 default:
306 case 4:
307 ret = ldl_kernel(T0 & ~3);
308 break;
309 case 8:
e909ec2f
BS
310 tmp = ldq_kernel(T0 & ~7);
311 ret = tmp >> 32;
312 T0 = tmp & 0xffffffff;
81ad8ba2
BS
313 break;
314 }
315 break;
6c36d3fa
BS
316 case 0xc: /* I-cache tag */
317 case 0xd: /* I-cache data */
318 case 0xe: /* D-cache tag */
319 case 0xf: /* D-cache data */
320 break;
321 case 0x20: /* MMU passthrough */
02aab46a
FB
322 switch(size) {
323 case 1:
324 ret = ldub_phys(T0);
325 break;
326 case 2:
327 ret = lduw_phys(T0 & ~1);
328 break;
329 default:
330 case 4:
331 ret = ldl_phys(T0 & ~3);
332 break;
9e61bde5 333 case 8:
e909ec2f
BS
334 tmp = ldq_phys(T0 & ~7);
335 ret = tmp >> 32;
336 T0 = tmp & 0xffffffff;
0f8a249a 337 break;
02aab46a 338 }
0f8a249a 339 break;
5dcb6b91
BS
340 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
341 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
342 switch(size) {
343 case 1:
344 ret = ldub_phys((target_phys_addr_t)T0
345 | ((target_phys_addr_t)(asi & 0xf) << 32));
346 break;
347 case 2:
348 ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
349 | ((target_phys_addr_t)(asi & 0xf) << 32));
350 break;
351 default:
352 case 4:
353 ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
354 | ((target_phys_addr_t)(asi & 0xf) << 32));
355 break;
356 case 8:
e909ec2f 357 tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
5dcb6b91 358 | ((target_phys_addr_t)(asi & 0xf) << 32));
e909ec2f
BS
359 ret = tmp >> 32;
360 T0 = tmp & 0xffffffff;
0f8a249a 361 break;
5dcb6b91 362 }
0f8a249a 363 break;
5dcb6b91 364 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
e8af50a3 365 default:
6c36d3fa 366 do_unassigned_access(T0, 0, 0, 1);
0f8a249a
BS
367 ret = 0;
368 break;
e8af50a3 369 }
81ad8ba2
BS
370 if (sign) {
371 switch(size) {
372 case 1:
373 T1 = (int8_t) ret;
e32664fb 374 break;
81ad8ba2
BS
375 case 2:
376 T1 = (int16_t) ret;
e32664fb 377 break;
81ad8ba2
BS
378 default:
379 T1 = ret;
380 break;
381 }
382 }
383 else
384 T1 = ret;
e8af50a3
FB
385}
386
81ad8ba2 387void helper_st_asi(int asi, int size)
e8af50a3
FB
388{
389 switch(asi) {
6c36d3fa 390 case 2: /* SuperSparc MXCC registers */
952a328f
BS
391 switch (T0) {
392 case 0x01c00000: /* MXCC stream data register 0 */
393 if (size == 8)
394 env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
395 else
396 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
397 break;
398 case 0x01c00008: /* MXCC stream data register 1 */
399 if (size == 8)
400 env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
401 else
402 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
403 break;
404 case 0x01c00010: /* MXCC stream data register 2 */
405 if (size == 8)
406 env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
407 else
408 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
409 break;
410 case 0x01c00018: /* MXCC stream data register 3 */
411 if (size == 8)
412 env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
413 else
414 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
415 break;
416 case 0x01c00100: /* MXCC stream source */
417 if (size == 8)
418 env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
419 else
420 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
421 env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0);
422 env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8);
423 env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
424 env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
425 break;
426 case 0x01c00200: /* MXCC stream destination */
427 if (size == 8)
428 env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
429 else
430 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
431 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]);
432 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]);
433 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
434 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
435 break;
436 case 0x01c00a00: /* MXCC control register */
437 if (size == 8)
438 env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
439 else
440 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
441 break;
442 case 0x01c00a04: /* MXCC control register */
443 if (size == 4)
bd37ec21 444 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1;
952a328f
BS
445 else
446 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
447 break;
448 case 0x01c00e00: /* MXCC error register */
449 if (size == 8)
450 env->mxccregs[6] = ((uint64_t)T1 << 32) | T2;
451 else
452 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
453 if (env->mxccregs[6] == 0xffffffffffffffffULL) {
454 // this is probably a reset
455 }
456 break;
457 case 0x01c00f00: /* MBus port address register */
458 if (size == 8)
459 env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
460 else
461 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
462 break;
463 default:
464 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
465 break;
466 }
467 DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
468#ifdef DEBUG_MXCC
469 dump_mxcc(env);
470#endif
6c36d3fa 471 break;
e8af50a3 472 case 3: /* MMU flush */
0f8a249a
BS
473 {
474 int mmulev;
e80cfcfc 475
0f8a249a 476 mmulev = (T0 >> 8) & 15;
952a328f 477 DPRINTF_MMU("mmu flush level %d\n", mmulev);
0f8a249a
BS
478 switch (mmulev) {
479 case 0: // flush page
480 tlb_flush_page(env, T0 & 0xfffff000);
481 break;
482 case 1: // flush segment (256k)
483 case 2: // flush region (16M)
484 case 3: // flush context (4G)
485 case 4: // flush entire
486 tlb_flush(env, 1);
487 break;
488 default:
489 break;
490 }
55754d9e 491#ifdef DEBUG_MMU
0f8a249a 492 dump_mmu(env);
55754d9e 493#endif
0f8a249a
BS
494 return;
495 }
e8af50a3 496 case 4: /* write MMU regs */
0f8a249a
BS
497 {
498 int reg = (T0 >> 8) & 0xf;
499 uint32_t oldreg;
3b46e624 500
0f8a249a 501 oldreg = env->mmuregs[reg];
55754d9e
FB
502 switch(reg) {
503 case 0:
6d5f237a
BS
504 env->mmuregs[reg] &= ~(MMU_E | MMU_NF | env->mmu_bm);
505 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF | env->mmu_bm);
0f8a249a
BS
506 // Mappings generated during no-fault mode or MMU
507 // disabled mode are invalid in normal mode
6f7e9aec 508 if (oldreg != env->mmuregs[reg])
55754d9e
FB
509 tlb_flush(env, 1);
510 break;
511 case 2:
0f8a249a 512 env->mmuregs[reg] = T1;
55754d9e
FB
513 if (oldreg != env->mmuregs[reg]) {
514 /* we flush when the MMU context changes because
515 QEMU has no MMU context support */
516 tlb_flush(env, 1);
517 }
518 break;
519 case 3:
520 case 4:
521 break;
522 default:
0f8a249a 523 env->mmuregs[reg] = T1;
55754d9e
FB
524 break;
525 }
55754d9e 526 if (oldreg != env->mmuregs[reg]) {
952a328f 527 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
55754d9e 528 }
952a328f 529#ifdef DEBUG_MMU
0f8a249a 530 dump_mmu(env);
55754d9e 531#endif
0f8a249a
BS
532 return;
533 }
81ad8ba2
BS
534 case 0xa: /* User data access */
535 switch(size) {
536 case 1:
537 stb_user(T0, T1);
538 break;
539 case 2:
540 stw_user(T0 & ~1, T1);
541 break;
542 default:
543 case 4:
544 stl_user(T0 & ~3, T1);
545 break;
546 case 8:
e909ec2f 547 stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
81ad8ba2
BS
548 break;
549 }
550 break;
551 case 0xb: /* Supervisor data access */
552 switch(size) {
553 case 1:
554 stb_kernel(T0, T1);
555 break;
556 case 2:
557 stw_kernel(T0 & ~1, T1);
558 break;
559 default:
560 case 4:
561 stl_kernel(T0 & ~3, T1);
562 break;
563 case 8:
e909ec2f 564 stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
81ad8ba2
BS
565 break;
566 }
567 break;
6c36d3fa
BS
568 case 0xc: /* I-cache tag */
569 case 0xd: /* I-cache data */
570 case 0xe: /* D-cache tag */
571 case 0xf: /* D-cache data */
572 case 0x10: /* I/D-cache flush page */
573 case 0x11: /* I/D-cache flush segment */
574 case 0x12: /* I/D-cache flush region */
575 case 0x13: /* I/D-cache flush context */
576 case 0x14: /* I/D-cache flush user */
577 break;
e80cfcfc 578 case 0x17: /* Block copy, sta access */
0f8a249a
BS
579 {
580 // value (T1) = src
581 // address (T0) = dst
582 // copy 32 bytes
6c36d3fa
BS
583 unsigned int i;
584 uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
3b46e624 585
6c36d3fa
BS
586 for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
587 temp = ldl_kernel(src);
588 stl_kernel(dst, temp);
589 }
0f8a249a
BS
590 }
591 return;
e80cfcfc 592 case 0x1f: /* Block fill, stda access */
0f8a249a
BS
593 {
594 // value (T1, T2)
595 // address (T0) = dst
596 // fill 32 bytes
6c36d3fa
BS
597 unsigned int i;
598 uint32_t dst = T0 & 7;
599 uint64_t val;
e80cfcfc 600
6c36d3fa
BS
601 val = (((uint64_t)T1) << 32) | T2;
602
603 for (i = 0; i < 32; i += 8, dst += 8)
604 stq_kernel(dst, val);
0f8a249a
BS
605 }
606 return;
6c36d3fa 607 case 0x20: /* MMU passthrough */
0f8a249a 608 {
02aab46a
FB
609 switch(size) {
610 case 1:
611 stb_phys(T0, T1);
612 break;
613 case 2:
614 stw_phys(T0 & ~1, T1);
615 break;
616 case 4:
617 default:
618 stl_phys(T0 & ~3, T1);
619 break;
9e61bde5 620 case 8:
e909ec2f 621 stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
9e61bde5 622 break;
02aab46a 623 }
0f8a249a
BS
624 }
625 return;
5dcb6b91
BS
626 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
627 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
0f8a249a 628 {
5dcb6b91
BS
629 switch(size) {
630 case 1:
631 stb_phys((target_phys_addr_t)T0
632 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
633 break;
634 case 2:
635 stw_phys((target_phys_addr_t)(T0 & ~1)
636 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
637 break;
638 case 4:
639 default:
640 stl_phys((target_phys_addr_t)(T0 & ~3)
641 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
642 break;
643 case 8:
e909ec2f
BS
644 stq_phys((target_phys_addr_t)(T0 & ~7)
645 | ((target_phys_addr_t)(asi & 0xf) << 32),
646 ((uint64_t)T1 << 32) | T2);
5dcb6b91
BS
647 break;
648 }
0f8a249a
BS
649 }
650 return;
6c36d3fa
BS
651 case 0x31: /* Ross RT620 I-cache flush */
652 case 0x36: /* I-cache flash clear */
653 case 0x37: /* D-cache flash clear */
654 break;
655 case 9: /* Supervisor code access, XXX */
5dcb6b91 656 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
e8af50a3 657 default:
6c36d3fa 658 do_unassigned_access(T0, 1, 0, 1);
0f8a249a 659 return;
e8af50a3
FB
660 }
661}
662
81ad8ba2
BS
663#endif /* CONFIG_USER_ONLY */
664#else /* TARGET_SPARC64 */
665
666#ifdef CONFIG_USER_ONLY
667void helper_ld_asi(int asi, int size, int sign)
668{
669 uint64_t ret = 0;
670
671 if (asi < 0x80)
672 raise_exception(TT_PRIV_ACT);
673
674 switch (asi) {
675 case 0x80: // Primary
676 case 0x82: // Primary no-fault
677 case 0x88: // Primary LE
678 case 0x8a: // Primary no-fault LE
679 {
680 switch(size) {
681 case 1:
682 ret = ldub_raw(T0);
683 break;
684 case 2:
685 ret = lduw_raw(T0 & ~1);
686 break;
687 case 4:
688 ret = ldl_raw(T0 & ~3);
689 break;
690 default:
691 case 8:
692 ret = ldq_raw(T0 & ~7);
693 break;
694 }
695 }
696 break;
697 case 0x81: // Secondary
698 case 0x83: // Secondary no-fault
699 case 0x89: // Secondary LE
700 case 0x8b: // Secondary no-fault LE
701 // XXX
702 break;
703 default:
704 break;
705 }
706
707 /* Convert from little endian */
708 switch (asi) {
709 case 0x88: // Primary LE
710 case 0x89: // Secondary LE
711 case 0x8a: // Primary no-fault LE
712 case 0x8b: // Secondary no-fault LE
713 switch(size) {
714 case 2:
715 ret = bswap16(ret);
e32664fb 716 break;
81ad8ba2
BS
717 case 4:
718 ret = bswap32(ret);
e32664fb 719 break;
81ad8ba2
BS
720 case 8:
721 ret = bswap64(ret);
e32664fb 722 break;
81ad8ba2
BS
723 default:
724 break;
725 }
726 default:
727 break;
728 }
729
730 /* Convert to signed number */
731 if (sign) {
732 switch(size) {
733 case 1:
734 ret = (int8_t) ret;
e32664fb 735 break;
81ad8ba2
BS
736 case 2:
737 ret = (int16_t) ret;
e32664fb 738 break;
81ad8ba2
BS
739 case 4:
740 ret = (int32_t) ret;
e32664fb 741 break;
81ad8ba2
BS
742 default:
743 break;
744 }
745 }
746 T1 = ret;
747}
748
749void helper_st_asi(int asi, int size)
750{
751 if (asi < 0x80)
752 raise_exception(TT_PRIV_ACT);
753
754 /* Convert to little endian */
755 switch (asi) {
756 case 0x88: // Primary LE
757 case 0x89: // Secondary LE
758 switch(size) {
759 case 2:
760 T0 = bswap16(T0);
e32664fb 761 break;
81ad8ba2
BS
762 case 4:
763 T0 = bswap32(T0);
e32664fb 764 break;
81ad8ba2
BS
765 case 8:
766 T0 = bswap64(T0);
e32664fb 767 break;
81ad8ba2
BS
768 default:
769 break;
770 }
771 default:
772 break;
773 }
774
775 switch(asi) {
776 case 0x80: // Primary
777 case 0x88: // Primary LE
778 {
779 switch(size) {
780 case 1:
781 stb_raw(T0, T1);
782 break;
783 case 2:
784 stw_raw(T0 & ~1, T1);
785 break;
786 case 4:
787 stl_raw(T0 & ~3, T1);
788 break;
789 case 8:
790 default:
791 stq_raw(T0 & ~7, T1);
792 break;
793 }
794 }
795 break;
796 case 0x81: // Secondary
797 case 0x89: // Secondary LE
798 // XXX
799 return;
800
801 case 0x82: // Primary no-fault, RO
802 case 0x83: // Secondary no-fault, RO
803 case 0x8a: // Primary no-fault LE, RO
804 case 0x8b: // Secondary no-fault LE, RO
805 default:
806 do_unassigned_access(T0, 1, 0, 1);
807 return;
808 }
809}
810
811#else /* CONFIG_USER_ONLY */
3475187d
FB
812
813void helper_ld_asi(int asi, int size, int sign)
814{
83469015 815 uint64_t ret = 0;
3475187d 816
6f27aba6 817 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
20b749f6 818 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
0f8a249a 819 raise_exception(TT_PRIV_ACT);
3475187d
FB
820
821 switch (asi) {
81ad8ba2
BS
822 case 0x10: // As if user primary
823 case 0x18: // As if user primary LE
824 case 0x80: // Primary
825 case 0x82: // Primary no-fault
826 case 0x88: // Primary LE
827 case 0x8a: // Primary no-fault LE
828 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
6f27aba6
BS
829 if (env->hpstate & HS_PRIV) {
830 switch(size) {
831 case 1:
832 ret = ldub_hypv(T0);
833 break;
834 case 2:
835 ret = lduw_hypv(T0 & ~1);
836 break;
837 case 4:
838 ret = ldl_hypv(T0 & ~3);
839 break;
840 default:
841 case 8:
842 ret = ldq_hypv(T0 & ~7);
843 break;
844 }
845 } else {
846 switch(size) {
847 case 1:
848 ret = ldub_kernel(T0);
849 break;
850 case 2:
851 ret = lduw_kernel(T0 & ~1);
852 break;
853 case 4:
854 ret = ldl_kernel(T0 & ~3);
855 break;
856 default:
857 case 8:
858 ret = ldq_kernel(T0 & ~7);
859 break;
860 }
81ad8ba2
BS
861 }
862 } else {
863 switch(size) {
864 case 1:
865 ret = ldub_user(T0);
866 break;
867 case 2:
868 ret = lduw_user(T0 & ~1);
869 break;
870 case 4:
871 ret = ldl_user(T0 & ~3);
872 break;
873 default:
874 case 8:
875 ret = ldq_user(T0 & ~7);
876 break;
877 }
878 }
879 break;
3475187d
FB
880 case 0x14: // Bypass
881 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
882 case 0x1c: // Bypass LE
883 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 884 {
02aab46a
FB
885 switch(size) {
886 case 1:
887 ret = ldub_phys(T0);
888 break;
889 case 2:
890 ret = lduw_phys(T0 & ~1);
891 break;
892 case 4:
893 ret = ldl_phys(T0 & ~3);
894 break;
895 default:
896 case 8:
897 ret = ldq_phys(T0 & ~7);
898 break;
899 }
0f8a249a
BS
900 break;
901 }
83469015
FB
902 case 0x04: // Nucleus
903 case 0x0c: // Nucleus Little Endian (LE)
83469015 904 case 0x11: // As if user secondary
83469015 905 case 0x19: // As if user secondary LE
83469015
FB
906 case 0x24: // Nucleus quad LDD 128 bit atomic
907 case 0x2c: // Nucleus quad LDD 128 bit atomic
908 case 0x4a: // UPA config
81ad8ba2 909 case 0x81: // Secondary
83469015 910 case 0x83: // Secondary no-fault
83469015 911 case 0x89: // Secondary LE
83469015 912 case 0x8b: // Secondary no-fault LE
0f8a249a
BS
913 // XXX
914 break;
3475187d 915 case 0x45: // LSU
0f8a249a
BS
916 ret = env->lsu;
917 break;
3475187d 918 case 0x50: // I-MMU regs
0f8a249a
BS
919 {
920 int reg = (T0 >> 3) & 0xf;
3475187d 921
0f8a249a
BS
922 ret = env->immuregs[reg];
923 break;
924 }
3475187d
FB
925 case 0x51: // I-MMU 8k TSB pointer
926 case 0x52: // I-MMU 64k TSB pointer
927 case 0x55: // I-MMU data access
0f8a249a
BS
928 // XXX
929 break;
83469015 930 case 0x56: // I-MMU tag read
0f8a249a
BS
931 {
932 unsigned int i;
933
934 for (i = 0; i < 64; i++) {
935 // Valid, ctx match, vaddr match
936 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
937 env->itlb_tag[i] == T0) {
938 ret = env->itlb_tag[i];
939 break;
940 }
941 }
942 break;
943 }
3475187d 944 case 0x58: // D-MMU regs
0f8a249a
BS
945 {
946 int reg = (T0 >> 3) & 0xf;
3475187d 947
0f8a249a
BS
948 ret = env->dmmuregs[reg];
949 break;
950 }
83469015 951 case 0x5e: // D-MMU tag read
0f8a249a
BS
952 {
953 unsigned int i;
954
955 for (i = 0; i < 64; i++) {
956 // Valid, ctx match, vaddr match
957 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
958 env->dtlb_tag[i] == T0) {
959 ret = env->dtlb_tag[i];
960 break;
961 }
962 }
963 break;
964 }
3475187d
FB
965 case 0x59: // D-MMU 8k TSB pointer
966 case 0x5a: // D-MMU 64k TSB pointer
967 case 0x5b: // D-MMU data pointer
968 case 0x5d: // D-MMU data access
83469015
FB
969 case 0x48: // Interrupt dispatch, RO
970 case 0x49: // Interrupt data receive
971 case 0x7f: // Incoming interrupt vector, RO
0f8a249a
BS
972 // XXX
973 break;
3475187d
FB
974 case 0x54: // I-MMU data in, WO
975 case 0x57: // I-MMU demap, WO
976 case 0x5c: // D-MMU data in, WO
977 case 0x5f: // D-MMU demap, WO
83469015 978 case 0x77: // Interrupt vector, WO
3475187d 979 default:
6c36d3fa 980 do_unassigned_access(T0, 0, 0, 1);
0f8a249a
BS
981 ret = 0;
982 break;
3475187d 983 }
81ad8ba2
BS
984
985 /* Convert from little endian */
986 switch (asi) {
987 case 0x0c: // Nucleus Little Endian (LE)
988 case 0x18: // As if user primary LE
989 case 0x19: // As if user secondary LE
990 case 0x1c: // Bypass LE
991 case 0x1d: // Bypass, non-cacheable LE
992 case 0x88: // Primary LE
993 case 0x89: // Secondary LE
994 case 0x8a: // Primary no-fault LE
995 case 0x8b: // Secondary no-fault LE
996 switch(size) {
997 case 2:
998 ret = bswap16(ret);
e32664fb 999 break;
81ad8ba2
BS
1000 case 4:
1001 ret = bswap32(ret);
e32664fb 1002 break;
81ad8ba2
BS
1003 case 8:
1004 ret = bswap64(ret);
e32664fb 1005 break;
81ad8ba2
BS
1006 default:
1007 break;
1008 }
1009 default:
1010 break;
1011 }
1012
1013 /* Convert to signed number */
1014 if (sign) {
1015 switch(size) {
1016 case 1:
1017 ret = (int8_t) ret;
e32664fb 1018 break;
81ad8ba2
BS
1019 case 2:
1020 ret = (int16_t) ret;
e32664fb 1021 break;
81ad8ba2
BS
1022 case 4:
1023 ret = (int32_t) ret;
e32664fb 1024 break;
81ad8ba2
BS
1025 default:
1026 break;
1027 }
1028 }
3475187d
FB
1029 T1 = ret;
1030}
1031
81ad8ba2 1032void helper_st_asi(int asi, int size)
3475187d 1033{
6f27aba6 1034 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
20b749f6 1035 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
0f8a249a 1036 raise_exception(TT_PRIV_ACT);
3475187d 1037
81ad8ba2
BS
1038 /* Convert to little endian */
1039 switch (asi) {
1040 case 0x0c: // Nucleus Little Endian (LE)
1041 case 0x18: // As if user primary LE
1042 case 0x19: // As if user secondary LE
1043 case 0x1c: // Bypass LE
1044 case 0x1d: // Bypass, non-cacheable LE
81ad8ba2
BS
1045 case 0x88: // Primary LE
1046 case 0x89: // Secondary LE
1047 switch(size) {
1048 case 2:
1049 T0 = bswap16(T0);
e32664fb 1050 break;
81ad8ba2
BS
1051 case 4:
1052 T0 = bswap32(T0);
e32664fb 1053 break;
81ad8ba2
BS
1054 case 8:
1055 T0 = bswap64(T0);
e32664fb 1056 break;
81ad8ba2
BS
1057 default:
1058 break;
1059 }
1060 default:
1061 break;
1062 }
1063
3475187d 1064 switch(asi) {
81ad8ba2
BS
1065 case 0x10: // As if user primary
1066 case 0x18: // As if user primary LE
1067 case 0x80: // Primary
1068 case 0x88: // Primary LE
1069 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
6f27aba6
BS
1070 if (env->hpstate & HS_PRIV) {
1071 switch(size) {
1072 case 1:
1073 stb_hypv(T0, T1);
1074 break;
1075 case 2:
1076 stw_hypv(T0 & ~1, T1);
1077 break;
1078 case 4:
1079 stl_hypv(T0 & ~3, T1);
1080 break;
1081 case 8:
1082 default:
1083 stq_hypv(T0 & ~7, T1);
1084 break;
1085 }
1086 } else {
1087 switch(size) {
1088 case 1:
1089 stb_kernel(T0, T1);
1090 break;
1091 case 2:
1092 stw_kernel(T0 & ~1, T1);
1093 break;
1094 case 4:
1095 stl_kernel(T0 & ~3, T1);
1096 break;
1097 case 8:
1098 default:
1099 stq_kernel(T0 & ~7, T1);
1100 break;
1101 }
81ad8ba2
BS
1102 }
1103 } else {
1104 switch(size) {
1105 case 1:
1106 stb_user(T0, T1);
1107 break;
1108 case 2:
1109 stw_user(T0 & ~1, T1);
1110 break;
1111 case 4:
1112 stl_user(T0 & ~3, T1);
1113 break;
1114 case 8:
1115 default:
1116 stq_user(T0 & ~7, T1);
1117 break;
1118 }
1119 }
1120 break;
3475187d
FB
1121 case 0x14: // Bypass
1122 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
1123 case 0x1c: // Bypass LE
1124 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 1125 {
02aab46a
FB
1126 switch(size) {
1127 case 1:
1128 stb_phys(T0, T1);
1129 break;
1130 case 2:
1131 stw_phys(T0 & ~1, T1);
1132 break;
1133 case 4:
1134 stl_phys(T0 & ~3, T1);
1135 break;
1136 case 8:
1137 default:
1138 stq_phys(T0 & ~7, T1);
1139 break;
1140 }
0f8a249a
BS
1141 }
1142 return;
83469015
FB
1143 case 0x04: // Nucleus
1144 case 0x0c: // Nucleus Little Endian (LE)
83469015 1145 case 0x11: // As if user secondary
83469015 1146 case 0x19: // As if user secondary LE
83469015
FB
1147 case 0x24: // Nucleus quad LDD 128 bit atomic
1148 case 0x2c: // Nucleus quad LDD 128 bit atomic
1149 case 0x4a: // UPA config
51996525 1150 case 0x81: // Secondary
83469015 1151 case 0x89: // Secondary LE
0f8a249a
BS
1152 // XXX
1153 return;
3475187d 1154 case 0x45: // LSU
0f8a249a
BS
1155 {
1156 uint64_t oldreg;
1157
1158 oldreg = env->lsu;
1159 env->lsu = T1 & (DMMU_E | IMMU_E);
1160 // Mappings generated during D/I MMU disabled mode are
1161 // invalid in normal mode
1162 if (oldreg != env->lsu) {
952a328f 1163 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
83469015 1164#ifdef DEBUG_MMU
0f8a249a 1165 dump_mmu(env);
83469015 1166#endif
0f8a249a
BS
1167 tlb_flush(env, 1);
1168 }
1169 return;
1170 }
3475187d 1171 case 0x50: // I-MMU regs
0f8a249a
BS
1172 {
1173 int reg = (T0 >> 3) & 0xf;
1174 uint64_t oldreg;
3b46e624 1175
0f8a249a 1176 oldreg = env->immuregs[reg];
3475187d
FB
1177 switch(reg) {
1178 case 0: // RO
1179 case 4:
1180 return;
1181 case 1: // Not in I-MMU
1182 case 2:
1183 case 7:
1184 case 8:
1185 return;
1186 case 3: // SFSR
0f8a249a
BS
1187 if ((T1 & 1) == 0)
1188 T1 = 0; // Clear SFSR
3475187d
FB
1189 break;
1190 case 5: // TSB access
1191 case 6: // Tag access
1192 default:
1193 break;
1194 }
0f8a249a 1195 env->immuregs[reg] = T1;
3475187d 1196 if (oldreg != env->immuregs[reg]) {
952a328f 1197 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
3475187d 1198 }
952a328f 1199#ifdef DEBUG_MMU
0f8a249a 1200 dump_mmu(env);
3475187d 1201#endif
0f8a249a
BS
1202 return;
1203 }
3475187d 1204 case 0x54: // I-MMU data in
0f8a249a
BS
1205 {
1206 unsigned int i;
1207
1208 // Try finding an invalid entry
1209 for (i = 0; i < 64; i++) {
1210 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1211 env->itlb_tag[i] = env->immuregs[6];
1212 env->itlb_tte[i] = T1;
1213 return;
1214 }
1215 }
1216 // Try finding an unlocked entry
1217 for (i = 0; i < 64; i++) {
1218 if ((env->itlb_tte[i] & 0x40) == 0) {
1219 env->itlb_tag[i] = env->immuregs[6];
1220 env->itlb_tte[i] = T1;
1221 return;
1222 }
1223 }
1224 // error state?
1225 return;
1226 }
3475187d 1227 case 0x55: // I-MMU data access
0f8a249a
BS
1228 {
1229 unsigned int i = (T0 >> 3) & 0x3f;
3475187d 1230
0f8a249a
BS
1231 env->itlb_tag[i] = env->immuregs[6];
1232 env->itlb_tte[i] = T1;
1233 return;
1234 }
3475187d 1235 case 0x57: // I-MMU demap
0f8a249a
BS
1236 // XXX
1237 return;
3475187d 1238 case 0x58: // D-MMU regs
0f8a249a
BS
1239 {
1240 int reg = (T0 >> 3) & 0xf;
1241 uint64_t oldreg;
3b46e624 1242
0f8a249a 1243 oldreg = env->dmmuregs[reg];
3475187d
FB
1244 switch(reg) {
1245 case 0: // RO
1246 case 4:
1247 return;
1248 case 3: // SFSR
0f8a249a
BS
1249 if ((T1 & 1) == 0) {
1250 T1 = 0; // Clear SFSR, Fault address
1251 env->dmmuregs[4] = 0;
1252 }
1253 env->dmmuregs[reg] = T1;
3475187d
FB
1254 break;
1255 case 1: // Primary context
1256 case 2: // Secondary context
1257 case 5: // TSB access
1258 case 6: // Tag access
1259 case 7: // Virtual Watchpoint
1260 case 8: // Physical Watchpoint
1261 default:
1262 break;
1263 }
0f8a249a 1264 env->dmmuregs[reg] = T1;
3475187d 1265 if (oldreg != env->dmmuregs[reg]) {
952a328f 1266 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
3475187d 1267 }
952a328f 1268#ifdef DEBUG_MMU
0f8a249a 1269 dump_mmu(env);
3475187d 1270#endif
0f8a249a
BS
1271 return;
1272 }
3475187d 1273 case 0x5c: // D-MMU data in
0f8a249a
BS
1274 {
1275 unsigned int i;
1276
1277 // Try finding an invalid entry
1278 for (i = 0; i < 64; i++) {
1279 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1280 env->dtlb_tag[i] = env->dmmuregs[6];
1281 env->dtlb_tte[i] = T1;
1282 return;
1283 }
1284 }
1285 // Try finding an unlocked entry
1286 for (i = 0; i < 64; i++) {
1287 if ((env->dtlb_tte[i] & 0x40) == 0) {
1288 env->dtlb_tag[i] = env->dmmuregs[6];
1289 env->dtlb_tte[i] = T1;
1290 return;
1291 }
1292 }
1293 // error state?
1294 return;
1295 }
3475187d 1296 case 0x5d: // D-MMU data access
0f8a249a
BS
1297 {
1298 unsigned int i = (T0 >> 3) & 0x3f;
3475187d 1299
0f8a249a
BS
1300 env->dtlb_tag[i] = env->dmmuregs[6];
1301 env->dtlb_tte[i] = T1;
1302 return;
1303 }
3475187d 1304 case 0x5f: // D-MMU demap
83469015 1305 case 0x49: // Interrupt data receive
0f8a249a
BS
1306 // XXX
1307 return;
3475187d
FB
1308 case 0x51: // I-MMU 8k TSB pointer, RO
1309 case 0x52: // I-MMU 64k TSB pointer, RO
1310 case 0x56: // I-MMU tag read, RO
1311 case 0x59: // D-MMU 8k TSB pointer, RO
1312 case 0x5a: // D-MMU 64k TSB pointer, RO
1313 case 0x5b: // D-MMU data pointer, RO
1314 case 0x5e: // D-MMU tag read, RO
83469015
FB
1315 case 0x48: // Interrupt dispatch, RO
1316 case 0x7f: // Incoming interrupt vector, RO
1317 case 0x82: // Primary no-fault, RO
1318 case 0x83: // Secondary no-fault, RO
1319 case 0x8a: // Primary no-fault LE, RO
1320 case 0x8b: // Secondary no-fault LE, RO
3475187d 1321 default:
6c36d3fa 1322 do_unassigned_access(T0, 1, 0, 1);
0f8a249a 1323 return;
3475187d
FB
1324 }
1325}
81ad8ba2 1326#endif /* CONFIG_USER_ONLY */
3391c818
BS
1327
1328void helper_ldf_asi(int asi, int size, int rd)
1329{
1330 target_ulong tmp_T0 = T0, tmp_T1 = T1;
1331 unsigned int i;
1332
1333 switch (asi) {
1334 case 0xf0: // Block load primary
1335 case 0xf1: // Block load secondary
1336 case 0xf8: // Block load primary LE
1337 case 0xf9: // Block load secondary LE
51996525
BS
1338 if (rd & 7) {
1339 raise_exception(TT_ILL_INSN);
1340 return;
1341 }
1342 if (T0 & 0x3f) {
1343 raise_exception(TT_UNALIGNED);
1344 return;
1345 }
1346 for (i = 0; i < 16; i++) {
1347 helper_ld_asi(asi & 0x8f, 4, 0);
1348 *(uint32_t *)&env->fpr[rd++] = T1;
1349 T0 += 4;
3391c818
BS
1350 }
1351 T0 = tmp_T0;
1352 T1 = tmp_T1;
1353
1354 return;
1355 default:
1356 break;
1357 }
1358
1359 helper_ld_asi(asi, size, 0);
1360 switch(size) {
1361 default:
1362 case 4:
1363 *((uint32_t *)&FT0) = T1;
1364 break;
1365 case 8:
1366 *((int64_t *)&DT0) = T1;
1367 break;
1368 }
1369 T1 = tmp_T1;
1370}
1371
1372void helper_stf_asi(int asi, int size, int rd)
1373{
1374 target_ulong tmp_T0 = T0, tmp_T1 = T1;
1375 unsigned int i;
1376
1377 switch (asi) {
1378 case 0xf0: // Block store primary
1379 case 0xf1: // Block store secondary
1380 case 0xf8: // Block store primary LE
1381 case 0xf9: // Block store secondary LE
51996525
BS
1382 if (rd & 7) {
1383 raise_exception(TT_ILL_INSN);
1384 return;
1385 }
1386 if (T0 & 0x3f) {
1387 raise_exception(TT_UNALIGNED);
1388 return;
1389 }
1390 for (i = 0; i < 16; i++) {
1391 T1 = *(uint32_t *)&env->fpr[rd++];
1392 helper_st_asi(asi & 0x8f, 4);
1393 T0 += 4;
3391c818
BS
1394 }
1395 T0 = tmp_T0;
1396 T1 = tmp_T1;
1397
1398 return;
1399 default:
1400 break;
1401 }
1402
1403 switch(size) {
1404 default:
1405 case 4:
1406 T1 = *((uint32_t *)&FT0);
1407 break;
1408 case 8:
1409 T1 = *((int64_t *)&DT0);
1410 break;
1411 }
1412 helper_st_asi(asi, size);
1413 T1 = tmp_T1;
1414}
1415
81ad8ba2 1416#endif /* TARGET_SPARC64 */
3475187d
FB
1417
1418#ifndef TARGET_SPARC64
a0c4cb4a 1419void helper_rett()
e8af50a3 1420{
af7bf89b
FB
1421 unsigned int cwp;
1422
d4218d99
BS
1423 if (env->psret == 1)
1424 raise_exception(TT_ILL_INSN);
1425
e8af50a3 1426 env->psret = 1;
5fafdf24 1427 cwp = (env->cwp + 1) & (NWINDOWS - 1);
e8af50a3
FB
1428 if (env->wim & (1 << cwp)) {
1429 raise_exception(TT_WIN_UNF);
1430 }
1431 set_cwp(cwp);
1432 env->psrs = env->psrps;
1433}
3475187d 1434#endif
e8af50a3 1435
8d5f07fa 1436void helper_ldfsr(void)
e8af50a3 1437{
7a0e1f41 1438 int rnd_mode;
e8af50a3
FB
1439 switch (env->fsr & FSR_RD_MASK) {
1440 case FSR_RD_NEAREST:
7a0e1f41 1441 rnd_mode = float_round_nearest_even;
0f8a249a 1442 break;
ed910241 1443 default:
e8af50a3 1444 case FSR_RD_ZERO:
7a0e1f41 1445 rnd_mode = float_round_to_zero;
0f8a249a 1446 break;
e8af50a3 1447 case FSR_RD_POS:
7a0e1f41 1448 rnd_mode = float_round_up;
0f8a249a 1449 break;
e8af50a3 1450 case FSR_RD_NEG:
7a0e1f41 1451 rnd_mode = float_round_down;
0f8a249a 1452 break;
e8af50a3 1453 }
7a0e1f41 1454 set_float_rounding_mode(rnd_mode, &env->fp_status);
e8af50a3 1455}
e80cfcfc 1456
e80cfcfc
FB
1457void helper_debug()
1458{
1459 env->exception_index = EXCP_DEBUG;
1460 cpu_loop_exit();
1461}
af7bf89b 1462
3475187d 1463#ifndef TARGET_SPARC64
af7bf89b
FB
1464void do_wrpsr()
1465{
d4218d99
BS
1466 if ((T0 & PSR_CWP) >= NWINDOWS)
1467 raise_exception(TT_ILL_INSN);
1468 else
1469 PUT_PSR(env, T0);
af7bf89b
FB
1470}
1471
1472void do_rdpsr()
1473{
1474 T0 = GET_PSR(env);
1475}
3475187d
FB
1476
1477#else
1478
1479void do_popc()
1480{
eed152bb 1481 T0 = ctpop64(T1);
3475187d 1482}
83469015
FB
1483
1484static inline uint64_t *get_gregset(uint64_t pstate)
1485{
1486 switch (pstate) {
1487 default:
1488 case 0:
0f8a249a 1489 return env->bgregs;
83469015 1490 case PS_AG:
0f8a249a 1491 return env->agregs;
83469015 1492 case PS_MG:
0f8a249a 1493 return env->mgregs;
83469015 1494 case PS_IG:
0f8a249a 1495 return env->igregs;
83469015
FB
1496 }
1497}
1498
8f1f22f6 1499static inline void change_pstate(uint64_t new_pstate)
83469015 1500{
8f1f22f6 1501 uint64_t pstate_regs, new_pstate_regs;
83469015
FB
1502 uint64_t *src, *dst;
1503
83469015
FB
1504 pstate_regs = env->pstate & 0xc01;
1505 new_pstate_regs = new_pstate & 0xc01;
1506 if (new_pstate_regs != pstate_regs) {
0f8a249a
BS
1507 // Switch global register bank
1508 src = get_gregset(new_pstate_regs);
1509 dst = get_gregset(pstate_regs);
1510 memcpy32(dst, env->gregs);
1511 memcpy32(env->gregs, src);
83469015
FB
1512 }
1513 env->pstate = new_pstate;
1514}
1515
8f1f22f6
BS
1516void do_wrpstate(void)
1517{
1518 change_pstate(T0 & 0xf3f);
1519}
1520
83469015
FB
1521void do_done(void)
1522{
1523 env->tl--;
1524 env->pc = env->tnpc[env->tl];
1525 env->npc = env->tnpc[env->tl] + 4;
1526 PUT_CCR(env, env->tstate[env->tl] >> 32);
1527 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
8f1f22f6 1528 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
17d996e1 1529 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
83469015
FB
1530}
1531
1532void do_retry(void)
1533{
1534 env->tl--;
1535 env->pc = env->tpc[env->tl];
1536 env->npc = env->tnpc[env->tl];
1537 PUT_CCR(env, env->tstate[env->tl] >> 32);
1538 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
8f1f22f6 1539 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
17d996e1 1540 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
83469015 1541}
3475187d 1542#endif
ee5bbe38
FB
1543
1544void set_cwp(int new_cwp)
1545{
1546 /* put the modified wrap registers at their proper location */
1547 if (env->cwp == (NWINDOWS - 1))
1548 memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1549 env->cwp = new_cwp;
1550 /* put the wrap registers at their temporary location */
1551 if (new_cwp == (NWINDOWS - 1))
1552 memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1553 env->regwptr = env->regbase + (new_cwp * 16);
1554 REGWPTR = env->regwptr;
1555}
1556
1557void cpu_set_cwp(CPUState *env1, int new_cwp)
1558{
1559 CPUState *saved_env;
1560#ifdef reg_REGWPTR
1561 target_ulong *saved_regwptr;
1562#endif
1563
1564 saved_env = env;
1565#ifdef reg_REGWPTR
1566 saved_regwptr = REGWPTR;
1567#endif
1568 env = env1;
1569 set_cwp(new_cwp);
1570 env = saved_env;
1571#ifdef reg_REGWPTR
1572 REGWPTR = saved_regwptr;
1573#endif
1574}
1575
1576#ifdef TARGET_SPARC64
1577void do_interrupt(int intno)
1578{
1579#ifdef DEBUG_PCALL
1580 if (loglevel & CPU_LOG_INT) {
0f8a249a
BS
1581 static int count;
1582 fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
ee5bbe38
FB
1583 count, intno,
1584 env->pc,
1585 env->npc, env->regwptr[6]);
0f8a249a 1586 cpu_dump_state(env, logfile, fprintf, 0);
ee5bbe38 1587#if 0
0f8a249a
BS
1588 {
1589 int i;
1590 uint8_t *ptr;
1591
1592 fprintf(logfile, " code=");
1593 ptr = (uint8_t *)env->pc;
1594 for(i = 0; i < 16; i++) {
1595 fprintf(logfile, " %02x", ldub(ptr + i));
1596 }
1597 fprintf(logfile, "\n");
1598 }
ee5bbe38 1599#endif
0f8a249a 1600 count++;
ee5bbe38
FB
1601 }
1602#endif
5fafdf24 1603#if !defined(CONFIG_USER_ONLY)
83469015 1604 if (env->tl == MAXTL) {
c68ea704 1605 cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
0f8a249a 1606 return;
ee5bbe38
FB
1607 }
1608#endif
1609 env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
0f8a249a 1610 ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
ee5bbe38
FB
1611 env->tpc[env->tl] = env->pc;
1612 env->tnpc[env->tl] = env->npc;
1613 env->tt[env->tl] = intno;
8f1f22f6
BS
1614 change_pstate(PS_PEF | PS_PRIV | PS_AG);
1615
1616 if (intno == TT_CLRWIN)
1617 set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1618 else if ((intno & 0x1c0) == TT_SPILL)
1619 set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1620 else if ((intno & 0x1c0) == TT_FILL)
1621 set_cwp((env->cwp + 1) & (NWINDOWS - 1));
83469015
FB
1622 env->tbr &= ~0x7fffULL;
1623 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1624 if (env->tl < MAXTL - 1) {
0f8a249a 1625 env->tl++;
83469015 1626 } else {
0f8a249a
BS
1627 env->pstate |= PS_RED;
1628 if (env->tl != MAXTL)
1629 env->tl++;
83469015 1630 }
ee5bbe38
FB
1631 env->pc = env->tbr;
1632 env->npc = env->pc + 4;
1633 env->exception_index = 0;
1634}
1635#else
1636void do_interrupt(int intno)
1637{
1638 int cwp;
1639
1640#ifdef DEBUG_PCALL
1641 if (loglevel & CPU_LOG_INT) {
0f8a249a
BS
1642 static int count;
1643 fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
ee5bbe38
FB
1644 count, intno,
1645 env->pc,
1646 env->npc, env->regwptr[6]);
0f8a249a 1647 cpu_dump_state(env, logfile, fprintf, 0);
ee5bbe38 1648#if 0
0f8a249a
BS
1649 {
1650 int i;
1651 uint8_t *ptr;
1652
1653 fprintf(logfile, " code=");
1654 ptr = (uint8_t *)env->pc;
1655 for(i = 0; i < 16; i++) {
1656 fprintf(logfile, " %02x", ldub(ptr + i));
1657 }
1658 fprintf(logfile, "\n");
1659 }
ee5bbe38 1660#endif
0f8a249a 1661 count++;
ee5bbe38
FB
1662 }
1663#endif
5fafdf24 1664#if !defined(CONFIG_USER_ONLY)
ee5bbe38 1665 if (env->psret == 0) {
c68ea704 1666 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
0f8a249a 1667 return;
ee5bbe38
FB
1668 }
1669#endif
1670 env->psret = 0;
5fafdf24 1671 cwp = (env->cwp - 1) & (NWINDOWS - 1);
ee5bbe38
FB
1672 set_cwp(cwp);
1673 env->regwptr[9] = env->pc;
1674 env->regwptr[10] = env->npc;
1675 env->psrps = env->psrs;
1676 env->psrs = 1;
1677 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1678 env->pc = env->tbr;
1679 env->npc = env->pc + 4;
1680 env->exception_index = 0;
1681}
1682#endif
1683
5fafdf24 1684#if !defined(CONFIG_USER_ONLY)
ee5bbe38 1685
d2889a3e
BS
1686static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1687 void *retaddr);
1688
ee5bbe38 1689#define MMUSUFFIX _mmu
d2889a3e 1690#define ALIGNED_ONLY
273af660
TS
1691#ifdef __s390__
1692# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1693#else
1694# define GETPC() (__builtin_return_address(0))
1695#endif
ee5bbe38
FB
1696
1697#define SHIFT 0
1698#include "softmmu_template.h"
1699
1700#define SHIFT 1
1701#include "softmmu_template.h"
1702
1703#define SHIFT 2
1704#include "softmmu_template.h"
1705
1706#define SHIFT 3
1707#include "softmmu_template.h"
1708
d2889a3e
BS
1709static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1710 void *retaddr)
1711{
94554550
BS
1712#ifdef DEBUG_UNALIGNED
1713 printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1714#endif
1715 raise_exception(TT_UNALIGNED);
d2889a3e 1716}
ee5bbe38
FB
1717
1718/* try to fill the TLB and return an exception if error. If retaddr is
1719 NULL, it means that the function was called in C code (i.e. not
1720 from generated code or from helper.c) */
1721/* XXX: fix it to restore all registers */
6ebbf390 1722void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
ee5bbe38
FB
1723{
1724 TranslationBlock *tb;
1725 int ret;
1726 unsigned long pc;
1727 CPUState *saved_env;
1728
1729 /* XXX: hack to restore env in all cases, even if not called from
1730 generated code */
1731 saved_env = env;
1732 env = cpu_single_env;
1733
6ebbf390 1734 ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
ee5bbe38
FB
1735 if (ret) {
1736 if (retaddr) {
1737 /* now we have a real cpu fault */
1738 pc = (unsigned long)retaddr;
1739 tb = tb_find_pc(pc);
1740 if (tb) {
1741 /* the PC is inside the translated code. It means that we have
1742 a virtual CPU fault */
1743 cpu_restore_state(tb, env, pc, (void *)T2);
1744 }
1745 }
1746 cpu_loop_exit();
1747 }
1748 env = saved_env;
1749}
1750
1751#endif
6c36d3fa
BS
1752
1753#ifndef TARGET_SPARC64
5dcb6b91 1754void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
6c36d3fa
BS
1755 int is_asi)
1756{
1757 CPUState *saved_env;
1758
1759 /* XXX: hack to restore env in all cases, even if not called from
1760 generated code */
1761 saved_env = env;
1762 env = cpu_single_env;
1763 if (env->mmuregs[3]) /* Fault status register */
0f8a249a 1764 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
6c36d3fa
BS
1765 if (is_asi)
1766 env->mmuregs[3] |= 1 << 16;
1767 if (env->psrs)
1768 env->mmuregs[3] |= 1 << 5;
1769 if (is_exec)
1770 env->mmuregs[3] |= 1 << 6;
1771 if (is_write)
1772 env->mmuregs[3] |= 1 << 7;
1773 env->mmuregs[3] |= (5 << 2) | 2;
1774 env->mmuregs[4] = addr; /* Fault address register */
1775 if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1776#ifdef DEBUG_UNASSIGNED
5dcb6b91 1777 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
6c36d3fa
BS
1778 "\n", addr, env->pc);
1779#endif
1b2e93c1
BS
1780 if (is_exec)
1781 raise_exception(TT_CODE_ACCESS);
1782 else
1783 raise_exception(TT_DATA_ACCESS);
6c36d3fa
BS
1784 }
1785 env = saved_env;
1786}
1787#else
5dcb6b91 1788void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
6c36d3fa
BS
1789 int is_asi)
1790{
1791#ifdef DEBUG_UNASSIGNED
1792 CPUState *saved_env;
1793
1794 /* XXX: hack to restore env in all cases, even if not called from
1795 generated code */
1796 saved_env = env;
1797 env = cpu_single_env;
5dcb6b91 1798 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
6c36d3fa
BS
1799 addr, env->pc);
1800 env = saved_env;
1801#endif
1b2e93c1
BS
1802 if (is_exec)
1803 raise_exception(TT_CODE_ACCESS);
1804 else
1805 raise_exception(TT_DATA_ACCESS);
6c36d3fa
BS
1806}
1807#endif
20c9f095
BS
1808
1809#ifdef TARGET_SPARC64
1810void do_tick_set_count(void *opaque, uint64_t count)
1811{
d8bdf5fa 1812#if !defined(CONFIG_USER_ONLY)
20c9f095 1813 ptimer_set_count(opaque, -count);
d8bdf5fa 1814#endif
20c9f095
BS
1815}
1816
1817uint64_t do_tick_get_count(void *opaque)
1818{
d8bdf5fa 1819#if !defined(CONFIG_USER_ONLY)
20c9f095 1820 return -ptimer_get_count(opaque);
d8bdf5fa
BS
1821#else
1822 return 0;
1823#endif
20c9f095
BS
1824}
1825
1826void do_tick_set_limit(void *opaque, uint64_t limit)
1827{
d8bdf5fa 1828#if !defined(CONFIG_USER_ONLY)
20c9f095 1829 ptimer_set_limit(opaque, -limit, 0);
d8bdf5fa 1830#endif
20c9f095
BS
1831}
1832#endif