|
|
1.1 root 1: /*
2: * Helpers for loads and stores
3: *
4: * Copyright (c) 2003-2005 Fabrice Bellard
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18: */
19:
20: #include "cpu.h"
21: #include "dyngen-exec.h"
22: #include "helper.h"
23:
24: #if !defined(CONFIG_USER_ONLY)
25: #include "softmmu_exec.h"
26: #endif
27:
28: //#define DEBUG_MMU
29: //#define DEBUG_MXCC
30: //#define DEBUG_UNALIGNED
31: //#define DEBUG_UNASSIGNED
32: //#define DEBUG_ASI
33: //#define DEBUG_CACHE_CONTROL
34:
35: #ifdef DEBUG_MMU
36: #define DPRINTF_MMU(fmt, ...) \
37: do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
38: #else
39: #define DPRINTF_MMU(fmt, ...) do {} while (0)
40: #endif
41:
42: #ifdef DEBUG_MXCC
43: #define DPRINTF_MXCC(fmt, ...) \
44: do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
45: #else
46: #define DPRINTF_MXCC(fmt, ...) do {} while (0)
47: #endif
48:
49: #ifdef DEBUG_ASI
50: #define DPRINTF_ASI(fmt, ...) \
51: do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
52: #endif
53:
54: #ifdef DEBUG_CACHE_CONTROL
55: #define DPRINTF_CACHE_CONTROL(fmt, ...) \
56: do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0)
57: #else
58: #define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0)
59: #endif
60:
61: #ifdef TARGET_SPARC64
62: #ifndef TARGET_ABI32
63: #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
64: #else
65: #define AM_CHECK(env1) (1)
66: #endif
67: #endif
68:
69: #define QT0 (env->qt0)
70: #define QT1 (env->qt1)
71:
72: #if !defined(CONFIG_USER_ONLY)
73: static void do_unassigned_access(target_phys_addr_t addr, int is_write,
74: int is_exec, int is_asi, int size);
75: #else
76: #ifdef TARGET_SPARC64
77: static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
78: int is_asi, int size);
79: #endif
80: #endif
81:
82: #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
83: /* Calculates TSB pointer value for fault page size 8k or 64k */
84: static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
85: uint64_t tag_access_register,
86: int page_size)
87: {
88: uint64_t tsb_base = tsb_register & ~0x1fffULL;
89: int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
90: int tsb_size = tsb_register & 0xf;
91:
92: /* discard lower 13 bits which hold tag access context */
93: uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
94:
95: /* now reorder bits */
96: uint64_t tsb_base_mask = ~0x1fffULL;
97: uint64_t va = tag_access_va;
98:
99: /* move va bits to correct position */
100: if (page_size == 8*1024) {
101: va >>= 9;
102: } else if (page_size == 64*1024) {
103: va >>= 12;
104: }
105:
106: if (tsb_size) {
107: tsb_base_mask <<= tsb_size;
108: }
109:
110: /* calculate tsb_base mask and adjust va if split is in use */
111: if (tsb_split) {
112: if (page_size == 8*1024) {
113: va &= ~(1ULL << (13 + tsb_size));
114: } else if (page_size == 64*1024) {
115: va |= (1ULL << (13 + tsb_size));
116: }
117: tsb_base_mask <<= 1;
118: }
119:
120: return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
121: }
122:
123: /* Calculates tag target register value by reordering bits
124: in tag access register */
125: static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
126: {
127: return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
128: }
129:
130: static void replace_tlb_entry(SparcTLBEntry *tlb,
131: uint64_t tlb_tag, uint64_t tlb_tte,
132: CPUState *env1)
133: {
134: target_ulong mask, size, va, offset;
135:
136: /* flush page range if translation is valid */
137: if (TTE_IS_VALID(tlb->tte)) {
138:
139: mask = 0xffffffffffffe000ULL;
140: mask <<= 3 * ((tlb->tte >> 61) & 3);
141: size = ~mask + 1;
142:
143: va = tlb->tag & mask;
144:
145: for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
146: tlb_flush_page(env1, va + offset);
147: }
148: }
149:
150: tlb->tag = tlb_tag;
151: tlb->tte = tlb_tte;
152: }
153:
154: static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
155: const char *strmmu, CPUState *env1)
156: {
157: unsigned int i;
158: target_ulong mask;
159: uint64_t context;
160:
161: int is_demap_context = (demap_addr >> 6) & 1;
162:
163: /* demap context */
164: switch ((demap_addr >> 4) & 3) {
165: case 0: /* primary */
166: context = env1->dmmu.mmu_primary_context;
167: break;
168: case 1: /* secondary */
169: context = env1->dmmu.mmu_secondary_context;
170: break;
171: case 2: /* nucleus */
172: context = 0;
173: break;
174: case 3: /* reserved */
175: default:
176: return;
177: }
178:
179: for (i = 0; i < 64; i++) {
180: if (TTE_IS_VALID(tlb[i].tte)) {
181:
182: if (is_demap_context) {
183: /* will remove non-global entries matching context value */
184: if (TTE_IS_GLOBAL(tlb[i].tte) ||
185: !tlb_compare_context(&tlb[i], context)) {
186: continue;
187: }
188: } else {
189: /* demap page
190: will remove any entry matching VA */
191: mask = 0xffffffffffffe000ULL;
192: mask <<= 3 * ((tlb[i].tte >> 61) & 3);
193:
194: if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
195: continue;
196: }
197:
198: /* entry should be global or matching context value */
199: if (!TTE_IS_GLOBAL(tlb[i].tte) &&
200: !tlb_compare_context(&tlb[i], context)) {
201: continue;
202: }
203: }
204:
205: replace_tlb_entry(&tlb[i], 0, 0, env1);
206: #ifdef DEBUG_MMU
207: DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
208: dump_mmu(stdout, fprintf, env1);
209: #endif
210: }
211: }
212: }
213:
214: static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
215: uint64_t tlb_tag, uint64_t tlb_tte,
216: const char *strmmu, CPUState *env1)
217: {
218: unsigned int i, replace_used;
219:
220: /* Try replacing invalid entry */
221: for (i = 0; i < 64; i++) {
222: if (!TTE_IS_VALID(tlb[i].tte)) {
223: replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
224: #ifdef DEBUG_MMU
225: DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
226: dump_mmu(stdout, fprintf, env1);
227: #endif
228: return;
229: }
230: }
231:
232: /* All entries are valid, try replacing unlocked entry */
233:
234: for (replace_used = 0; replace_used < 2; ++replace_used) {
235:
236: /* Used entries are not replaced on first pass */
237:
238: for (i = 0; i < 64; i++) {
239: if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
240:
241: replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
242: #ifdef DEBUG_MMU
243: DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
244: strmmu, (replace_used ? "used" : "unused"), i);
245: dump_mmu(stdout, fprintf, env1);
246: #endif
247: return;
248: }
249: }
250:
251: /* Now reset used bit and search for unused entries again */
252:
253: for (i = 0; i < 64; i++) {
254: TTE_SET_UNUSED(tlb[i].tte);
255: }
256: }
257:
258: #ifdef DEBUG_MMU
259: DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
260: #endif
261: /* error state? */
262: }
263:
264: #endif
265:
266: static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
267: {
268: #ifdef TARGET_SPARC64
269: if (AM_CHECK(env1)) {
270: addr &= 0xffffffffULL;
271: }
272: #endif
273: return addr;
274: }
275:
276: /* returns true if access using this ASI is to have address translated by MMU
277: otherwise access is to raw physical address */
278: static inline int is_translating_asi(int asi)
279: {
280: #ifdef TARGET_SPARC64
281: /* Ultrasparc IIi translating asi
282: - note this list is defined by cpu implementation
283: */
284: switch (asi) {
285: case 0x04 ... 0x11:
286: case 0x16 ... 0x19:
287: case 0x1E ... 0x1F:
288: case 0x24 ... 0x2C:
289: case 0x70 ... 0x73:
290: case 0x78 ... 0x79:
291: case 0x80 ... 0xFF:
292: return 1;
293:
294: default:
295: return 0;
296: }
297: #else
298: /* TODO: check sparc32 bits */
299: return 0;
300: #endif
301: }
302:
303: static inline target_ulong asi_address_mask(CPUState *env1,
304: int asi, target_ulong addr)
305: {
306: if (is_translating_asi(asi)) {
307: return address_mask(env, addr);
308: } else {
309: return addr;
310: }
311: }
312:
313: void helper_check_align(target_ulong addr, uint32_t align)
314: {
315: if (addr & align) {
316: #ifdef DEBUG_UNALIGNED
317: printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
318: "\n", addr, env->pc);
319: #endif
320: helper_raise_exception(env, TT_UNALIGNED);
321: }
322: }
323:
324: #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
325: defined(DEBUG_MXCC)
326: static void dump_mxcc(CPUState *env)
327: {
328: printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
329: "\n",
330: env->mxccdata[0], env->mxccdata[1],
331: env->mxccdata[2], env->mxccdata[3]);
332: printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
333: "\n"
334: " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
335: "\n",
336: env->mxccregs[0], env->mxccregs[1],
337: env->mxccregs[2], env->mxccregs[3],
338: env->mxccregs[4], env->mxccregs[5],
339: env->mxccregs[6], env->mxccregs[7]);
340: }
341: #endif
342:
343: #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
344: && defined(DEBUG_ASI)
345: static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
346: uint64_t r1)
347: {
348: switch (size) {
349: case 1:
350: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
351: addr, asi, r1 & 0xff);
352: break;
353: case 2:
354: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
355: addr, asi, r1 & 0xffff);
356: break;
357: case 4:
358: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
359: addr, asi, r1 & 0xffffffff);
360: break;
361: case 8:
362: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
363: addr, asi, r1);
364: break;
365: }
366: }
367: #endif
368:
369: #ifndef TARGET_SPARC64
370: #ifndef CONFIG_USER_ONLY
371:
372:
373: /* Leon3 cache control */
374:
375: static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
376: {
377: DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
378: addr, val, size);
379:
380: if (size != 4) {
381: DPRINTF_CACHE_CONTROL("32bits only\n");
382: return;
383: }
384:
385: switch (addr) {
386: case 0x00: /* Cache control */
387:
388: /* These values must always be read as zeros */
389: val &= ~CACHE_CTRL_FD;
390: val &= ~CACHE_CTRL_FI;
391: val &= ~CACHE_CTRL_IB;
392: val &= ~CACHE_CTRL_IP;
393: val &= ~CACHE_CTRL_DP;
394:
395: env->cache_control = val;
396: break;
397: case 0x04: /* Instruction cache configuration */
398: case 0x08: /* Data cache configuration */
399: /* Read Only */
400: break;
401: default:
402: DPRINTF_CACHE_CONTROL("write unknown register %08x\n", addr);
403: break;
404: };
405: }
406:
407: static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
408: {
409: uint64_t ret = 0;
410:
411: if (size != 4) {
412: DPRINTF_CACHE_CONTROL("32bits only\n");
413: return 0;
414: }
415:
416: switch (addr) {
417: case 0x00: /* Cache control */
418: ret = env->cache_control;
419: break;
420:
421: /* Configuration registers are read and only always keep those
422: predefined values */
423:
424: case 0x04: /* Instruction cache configuration */
425: ret = 0x10220000;
426: break;
427: case 0x08: /* Data cache configuration */
428: ret = 0x18220000;
429: break;
430: default:
431: DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr);
432: break;
433: };
434: DPRINTF_CACHE_CONTROL("ld addr:%08x, ret:0x%" PRIx64 ", size:%d\n",
435: addr, ret, size);
436: return ret;
437: }
438:
439: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
440: {
441: uint64_t ret = 0;
442: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
443: uint32_t last_addr = addr;
444: #endif
445:
446: helper_check_align(addr, size - 1);
447: switch (asi) {
448: case 2: /* SuperSparc MXCC registers and Leon3 cache control */
449: switch (addr) {
450: case 0x00: /* Leon3 Cache Control */
451: case 0x08: /* Leon3 Instruction Cache config */
452: case 0x0C: /* Leon3 Date Cache config */
453: if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
454: ret = leon3_cache_control_ld(addr, size);
455: }
456: break;
457: case 0x01c00a00: /* MXCC control register */
458: if (size == 8) {
459: ret = env->mxccregs[3];
460: } else {
461: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
462: size);
463: }
464: break;
465: case 0x01c00a04: /* MXCC control register */
466: if (size == 4) {
467: ret = env->mxccregs[3];
468: } else {
469: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
470: size);
471: }
472: break;
473: case 0x01c00c00: /* Module reset register */
474: if (size == 8) {
475: ret = env->mxccregs[5];
476: /* should we do something here? */
477: } else {
478: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
479: size);
480: }
481: break;
482: case 0x01c00f00: /* MBus port address register */
483: if (size == 8) {
484: ret = env->mxccregs[7];
485: } else {
486: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
487: size);
488: }
489: break;
490: default:
491: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
492: size);
493: break;
494: }
495: DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
496: "addr = %08x -> ret = %" PRIx64 ","
497: "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
498: #ifdef DEBUG_MXCC
499: dump_mxcc(env);
500: #endif
501: break;
502: case 3: /* MMU probe */
503: {
504: int mmulev;
505:
506: mmulev = (addr >> 8) & 15;
507: if (mmulev > 4) {
508: ret = 0;
509: } else {
510: ret = mmu_probe(env, addr, mmulev);
511: }
512: DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
513: addr, mmulev, ret);
514: }
515: break;
516: case 4: /* read MMU regs */
517: {
518: int reg = (addr >> 8) & 0x1f;
519:
520: ret = env->mmuregs[reg];
521: if (reg == 3) { /* Fault status cleared on read */
522: env->mmuregs[3] = 0;
523: } else if (reg == 0x13) { /* Fault status read */
524: ret = env->mmuregs[3];
525: } else if (reg == 0x14) { /* Fault address read */
526: ret = env->mmuregs[4];
527: }
528: DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
529: }
530: break;
531: case 5: /* Turbosparc ITLB Diagnostic */
532: case 6: /* Turbosparc DTLB Diagnostic */
533: case 7: /* Turbosparc IOTLB Diagnostic */
534: break;
535: case 9: /* Supervisor code access */
536: switch (size) {
537: case 1:
538: ret = ldub_code(addr);
539: break;
540: case 2:
541: ret = lduw_code(addr);
542: break;
543: default:
544: case 4:
545: ret = ldl_code(addr);
546: break;
547: case 8:
548: ret = ldq_code(addr);
549: break;
550: }
551: break;
552: case 0xa: /* User data access */
553: switch (size) {
554: case 1:
555: ret = ldub_user(addr);
556: break;
557: case 2:
558: ret = lduw_user(addr);
559: break;
560: default:
561: case 4:
562: ret = ldl_user(addr);
563: break;
564: case 8:
565: ret = ldq_user(addr);
566: break;
567: }
568: break;
569: case 0xb: /* Supervisor data access */
570: switch (size) {
571: case 1:
572: ret = ldub_kernel(addr);
573: break;
574: case 2:
575: ret = lduw_kernel(addr);
576: break;
577: default:
578: case 4:
579: ret = ldl_kernel(addr);
580: break;
581: case 8:
582: ret = ldq_kernel(addr);
583: break;
584: }
585: break;
586: case 0xc: /* I-cache tag */
587: case 0xd: /* I-cache data */
588: case 0xe: /* D-cache tag */
589: case 0xf: /* D-cache data */
590: break;
591: case 0x20: /* MMU passthrough */
592: switch (size) {
593: case 1:
594: ret = ldub_phys(addr);
595: break;
596: case 2:
597: ret = lduw_phys(addr);
598: break;
599: default:
600: case 4:
601: ret = ldl_phys(addr);
602: break;
603: case 8:
604: ret = ldq_phys(addr);
605: break;
606: }
607: break;
608: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
609: switch (size) {
610: case 1:
611: ret = ldub_phys((target_phys_addr_t)addr
612: | ((target_phys_addr_t)(asi & 0xf) << 32));
613: break;
614: case 2:
615: ret = lduw_phys((target_phys_addr_t)addr
616: | ((target_phys_addr_t)(asi & 0xf) << 32));
617: break;
618: default:
619: case 4:
620: ret = ldl_phys((target_phys_addr_t)addr
621: | ((target_phys_addr_t)(asi & 0xf) << 32));
622: break;
623: case 8:
624: ret = ldq_phys((target_phys_addr_t)addr
625: | ((target_phys_addr_t)(asi & 0xf) << 32));
626: break;
627: }
628: break;
629: case 0x30: /* Turbosparc secondary cache diagnostic */
630: case 0x31: /* Turbosparc RAM snoop */
631: case 0x32: /* Turbosparc page table descriptor diagnostic */
632: case 0x39: /* data cache diagnostic register */
633: ret = 0;
634: break;
635: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
636: {
637: int reg = (addr >> 8) & 3;
638:
639: switch (reg) {
640: case 0: /* Breakpoint Value (Addr) */
641: ret = env->mmubpregs[reg];
642: break;
643: case 1: /* Breakpoint Mask */
644: ret = env->mmubpregs[reg];
645: break;
646: case 2: /* Breakpoint Control */
647: ret = env->mmubpregs[reg];
648: break;
649: case 3: /* Breakpoint Status */
650: ret = env->mmubpregs[reg];
651: env->mmubpregs[reg] = 0ULL;
652: break;
653: }
654: DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
655: ret);
656: }
657: break;
658: case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
659: ret = env->mmubpctrv;
660: break;
661: case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
662: ret = env->mmubpctrc;
663: break;
664: case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
665: ret = env->mmubpctrs;
666: break;
667: case 0x4c: /* SuperSPARC MMU Breakpoint Action */
668: ret = env->mmubpaction;
669: break;
670: case 8: /* User code access, XXX */
671: default:
672: do_unassigned_access(addr, 0, 0, asi, size);
673: ret = 0;
674: break;
675: }
676: if (sign) {
677: switch (size) {
678: case 1:
679: ret = (int8_t) ret;
680: break;
681: case 2:
682: ret = (int16_t) ret;
683: break;
684: case 4:
685: ret = (int32_t) ret;
686: break;
687: default:
688: break;
689: }
690: }
691: #ifdef DEBUG_ASI
692: dump_asi("read ", last_addr, asi, size, ret);
693: #endif
694: return ret;
695: }
696:
697: void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
698: {
699: helper_check_align(addr, size - 1);
700: switch (asi) {
701: case 2: /* SuperSparc MXCC registers and Leon3 cache control */
702: switch (addr) {
703: case 0x00: /* Leon3 Cache Control */
704: case 0x08: /* Leon3 Instruction Cache config */
705: case 0x0C: /* Leon3 Date Cache config */
706: if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
707: leon3_cache_control_st(addr, val, size);
708: }
709: break;
710:
711: case 0x01c00000: /* MXCC stream data register 0 */
712: if (size == 8) {
713: env->mxccdata[0] = val;
714: } else {
715: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
716: size);
717: }
718: break;
719: case 0x01c00008: /* MXCC stream data register 1 */
720: if (size == 8) {
721: env->mxccdata[1] = val;
722: } else {
723: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
724: size);
725: }
726: break;
727: case 0x01c00010: /* MXCC stream data register 2 */
728: if (size == 8) {
729: env->mxccdata[2] = val;
730: } else {
731: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
732: size);
733: }
734: break;
735: case 0x01c00018: /* MXCC stream data register 3 */
736: if (size == 8) {
737: env->mxccdata[3] = val;
738: } else {
739: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
740: size);
741: }
742: break;
743: case 0x01c00100: /* MXCC stream source */
744: if (size == 8) {
745: env->mxccregs[0] = val;
746: } else {
747: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
748: size);
749: }
750: env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
751: 0);
752: env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
753: 8);
754: env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
755: 16);
756: env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
757: 24);
758: break;
759: case 0x01c00200: /* MXCC stream destination */
760: if (size == 8) {
761: env->mxccregs[1] = val;
762: } else {
763: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
764: size);
765: }
766: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
767: env->mxccdata[0]);
768: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
769: env->mxccdata[1]);
770: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
771: env->mxccdata[2]);
772: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
773: env->mxccdata[3]);
774: break;
775: case 0x01c00a00: /* MXCC control register */
776: if (size == 8) {
777: env->mxccregs[3] = val;
778: } else {
779: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
780: size);
781: }
782: break;
783: case 0x01c00a04: /* MXCC control register */
784: if (size == 4) {
785: env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
786: | val;
787: } else {
788: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
789: size);
790: }
791: break;
792: case 0x01c00e00: /* MXCC error register */
793: /* writing a 1 bit clears the error */
794: if (size == 8) {
795: env->mxccregs[6] &= ~val;
796: } else {
797: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
798: size);
799: }
800: break;
801: case 0x01c00f00: /* MBus port address register */
802: if (size == 8) {
803: env->mxccregs[7] = val;
804: } else {
805: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
806: size);
807: }
808: break;
809: default:
810: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
811: size);
812: break;
813: }
814: DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
815: asi, size, addr, val);
816: #ifdef DEBUG_MXCC
817: dump_mxcc(env);
818: #endif
819: break;
820: case 3: /* MMU flush */
821: {
822: int mmulev;
823:
824: mmulev = (addr >> 8) & 15;
825: DPRINTF_MMU("mmu flush level %d\n", mmulev);
826: switch (mmulev) {
827: case 0: /* flush page */
828: tlb_flush_page(env, addr & 0xfffff000);
829: break;
830: case 1: /* flush segment (256k) */
831: case 2: /* flush region (16M) */
832: case 3: /* flush context (4G) */
833: case 4: /* flush entire */
834: tlb_flush(env, 1);
835: break;
836: default:
837: break;
838: }
839: #ifdef DEBUG_MMU
840: dump_mmu(stdout, fprintf, env);
841: #endif
842: }
843: break;
844: case 4: /* write MMU regs */
845: {
846: int reg = (addr >> 8) & 0x1f;
847: uint32_t oldreg;
848:
849: oldreg = env->mmuregs[reg];
850: switch (reg) {
851: case 0: /* Control Register */
852: env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
853: (val & 0x00ffffff);
854: /* Mappings generated during no-fault mode or MMU
855: disabled mode are invalid in normal mode */
856: if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
857: (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
858: tlb_flush(env, 1);
859: }
860: break;
861: case 1: /* Context Table Pointer Register */
862: env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
863: break;
864: case 2: /* Context Register */
865: env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
866: if (oldreg != env->mmuregs[reg]) {
867: /* we flush when the MMU context changes because
868: QEMU has no MMU context support */
869: tlb_flush(env, 1);
870: }
871: break;
872: case 3: /* Synchronous Fault Status Register with Clear */
873: case 4: /* Synchronous Fault Address Register */
874: break;
875: case 0x10: /* TLB Replacement Control Register */
876: env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
877: break;
878: case 0x13: /* Synchronous Fault Status Register with Read
879: and Clear */
880: env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
881: break;
882: case 0x14: /* Synchronous Fault Address Register */
883: env->mmuregs[4] = val;
884: break;
885: default:
886: env->mmuregs[reg] = val;
887: break;
888: }
889: if (oldreg != env->mmuregs[reg]) {
890: DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
891: reg, oldreg, env->mmuregs[reg]);
892: }
893: #ifdef DEBUG_MMU
894: dump_mmu(stdout, fprintf, env);
895: #endif
896: }
897: break;
898: case 5: /* Turbosparc ITLB Diagnostic */
899: case 6: /* Turbosparc DTLB Diagnostic */
900: case 7: /* Turbosparc IOTLB Diagnostic */
901: break;
902: case 0xa: /* User data access */
903: switch (size) {
904: case 1:
905: stb_user(addr, val);
906: break;
907: case 2:
908: stw_user(addr, val);
909: break;
910: default:
911: case 4:
912: stl_user(addr, val);
913: break;
914: case 8:
915: stq_user(addr, val);
916: break;
917: }
918: break;
919: case 0xb: /* Supervisor data access */
920: switch (size) {
921: case 1:
922: stb_kernel(addr, val);
923: break;
924: case 2:
925: stw_kernel(addr, val);
926: break;
927: default:
928: case 4:
929: stl_kernel(addr, val);
930: break;
931: case 8:
932: stq_kernel(addr, val);
933: break;
934: }
935: break;
936: case 0xc: /* I-cache tag */
937: case 0xd: /* I-cache data */
938: case 0xe: /* D-cache tag */
939: case 0xf: /* D-cache data */
940: case 0x10: /* I/D-cache flush page */
941: case 0x11: /* I/D-cache flush segment */
942: case 0x12: /* I/D-cache flush region */
943: case 0x13: /* I/D-cache flush context */
944: case 0x14: /* I/D-cache flush user */
945: break;
946: case 0x17: /* Block copy, sta access */
947: {
948: /* val = src
949: addr = dst
950: copy 32 bytes */
951: unsigned int i;
952: uint32_t src = val & ~3, dst = addr & ~3, temp;
953:
954: for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
955: temp = ldl_kernel(src);
956: stl_kernel(dst, temp);
957: }
958: }
959: break;
960: case 0x1f: /* Block fill, stda access */
961: {
962: /* addr = dst
963: fill 32 bytes with val */
964: unsigned int i;
965: uint32_t dst = addr & 7;
966:
967: for (i = 0; i < 32; i += 8, dst += 8) {
968: stq_kernel(dst, val);
969: }
970: }
971: break;
972: case 0x20: /* MMU passthrough */
973: {
974: switch (size) {
975: case 1:
976: stb_phys(addr, val);
977: break;
978: case 2:
979: stw_phys(addr, val);
980: break;
981: case 4:
982: default:
983: stl_phys(addr, val);
984: break;
985: case 8:
986: stq_phys(addr, val);
987: break;
988: }
989: }
990: break;
991: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
992: {
993: switch (size) {
994: case 1:
995: stb_phys((target_phys_addr_t)addr
996: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
997: break;
998: case 2:
999: stw_phys((target_phys_addr_t)addr
1000: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1001: break;
1002: case 4:
1003: default:
1004: stl_phys((target_phys_addr_t)addr
1005: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1006: break;
1007: case 8:
1008: stq_phys((target_phys_addr_t)addr
1009: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1010: break;
1011: }
1012: }
1013: break;
1014: case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */
1015: case 0x31: /* store buffer data, Ross RT620 I-cache flush or
1016: Turbosparc snoop RAM */
1017: case 0x32: /* store buffer control or Turbosparc page table
1018: descriptor diagnostic */
1019: case 0x36: /* I-cache flash clear */
1020: case 0x37: /* D-cache flash clear */
1021: break;
1022: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1023: {
1024: int reg = (addr >> 8) & 3;
1025:
1026: switch (reg) {
1027: case 0: /* Breakpoint Value (Addr) */
1028: env->mmubpregs[reg] = (val & 0xfffffffffULL);
1029: break;
1030: case 1: /* Breakpoint Mask */
1031: env->mmubpregs[reg] = (val & 0xfffffffffULL);
1032: break;
1033: case 2: /* Breakpoint Control */
1034: env->mmubpregs[reg] = (val & 0x7fULL);
1035: break;
1036: case 3: /* Breakpoint Status */
1037: env->mmubpregs[reg] = (val & 0xfULL);
1038: break;
1039: }
1040: DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
1041: env->mmuregs[reg]);
1042: }
1043: break;
1044: case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
1045: env->mmubpctrv = val & 0xffffffff;
1046: break;
1047: case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
1048: env->mmubpctrc = val & 0x3;
1049: break;
1050: case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
1051: env->mmubpctrs = val & 0x3;
1052: break;
1053: case 0x4c: /* SuperSPARC MMU Breakpoint Action */
1054: env->mmubpaction = val & 0x1fff;
1055: break;
1056: case 8: /* User code access, XXX */
1057: case 9: /* Supervisor code access, XXX */
1058: default:
1059: do_unassigned_access(addr, 1, 0, asi, size);
1060: break;
1061: }
1062: #ifdef DEBUG_ASI
1063: dump_asi("write", addr, asi, size, val);
1064: #endif
1065: }
1066:
1067: #endif /* CONFIG_USER_ONLY */
1068: #else /* TARGET_SPARC64 */
1069:
1070: #ifdef CONFIG_USER_ONLY
1071: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1072: {
1073: uint64_t ret = 0;
1074: #if defined(DEBUG_ASI)
1075: target_ulong last_addr = addr;
1076: #endif
1077:
1078: if (asi < 0x80) {
1079: helper_raise_exception(env, TT_PRIV_ACT);
1080: }
1081:
1082: helper_check_align(addr, size - 1);
1083: addr = asi_address_mask(env, asi, addr);
1084:
1085: switch (asi) {
1086: case 0x82: /* Primary no-fault */
1087: case 0x8a: /* Primary no-fault LE */
1088: if (page_check_range(addr, size, PAGE_READ) == -1) {
1089: #ifdef DEBUG_ASI
1090: dump_asi("read ", last_addr, asi, size, ret);
1091: #endif
1092: return 0;
1093: }
1094: /* Fall through */
1095: case 0x80: /* Primary */
1096: case 0x88: /* Primary LE */
1097: {
1098: switch (size) {
1099: case 1:
1100: ret = ldub_raw(addr);
1101: break;
1102: case 2:
1103: ret = lduw_raw(addr);
1104: break;
1105: case 4:
1106: ret = ldl_raw(addr);
1107: break;
1108: default:
1109: case 8:
1110: ret = ldq_raw(addr);
1111: break;
1112: }
1113: }
1114: break;
1115: case 0x83: /* Secondary no-fault */
1116: case 0x8b: /* Secondary no-fault LE */
1117: if (page_check_range(addr, size, PAGE_READ) == -1) {
1118: #ifdef DEBUG_ASI
1119: dump_asi("read ", last_addr, asi, size, ret);
1120: #endif
1121: return 0;
1122: }
1123: /* Fall through */
1124: case 0x81: /* Secondary */
1125: case 0x89: /* Secondary LE */
1126: /* XXX */
1127: break;
1128: default:
1129: break;
1130: }
1131:
1132: /* Convert from little endian */
1133: switch (asi) {
1134: case 0x88: /* Primary LE */
1135: case 0x89: /* Secondary LE */
1136: case 0x8a: /* Primary no-fault LE */
1137: case 0x8b: /* Secondary no-fault LE */
1138: switch (size) {
1139: case 2:
1140: ret = bswap16(ret);
1141: break;
1142: case 4:
1143: ret = bswap32(ret);
1144: break;
1145: case 8:
1146: ret = bswap64(ret);
1147: break;
1148: default:
1149: break;
1150: }
1151: default:
1152: break;
1153: }
1154:
1155: /* Convert to signed number */
1156: if (sign) {
1157: switch (size) {
1158: case 1:
1159: ret = (int8_t) ret;
1160: break;
1161: case 2:
1162: ret = (int16_t) ret;
1163: break;
1164: case 4:
1165: ret = (int32_t) ret;
1166: break;
1167: default:
1168: break;
1169: }
1170: }
1171: #ifdef DEBUG_ASI
1172: dump_asi("read ", last_addr, asi, size, ret);
1173: #endif
1174: return ret;
1175: }
1176:
1177: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1178: {
1179: #ifdef DEBUG_ASI
1180: dump_asi("write", addr, asi, size, val);
1181: #endif
1182: if (asi < 0x80) {
1183: helper_raise_exception(env, TT_PRIV_ACT);
1184: }
1185:
1186: helper_check_align(addr, size - 1);
1187: addr = asi_address_mask(env, asi, addr);
1188:
1189: /* Convert to little endian */
1190: switch (asi) {
1191: case 0x88: /* Primary LE */
1192: case 0x89: /* Secondary LE */
1193: switch (size) {
1194: case 2:
1195: val = bswap16(val);
1196: break;
1197: case 4:
1198: val = bswap32(val);
1199: break;
1200: case 8:
1201: val = bswap64(val);
1202: break;
1203: default:
1204: break;
1205: }
1206: default:
1207: break;
1208: }
1209:
1210: switch (asi) {
1211: case 0x80: /* Primary */
1212: case 0x88: /* Primary LE */
1213: {
1214: switch (size) {
1215: case 1:
1216: stb_raw(addr, val);
1217: break;
1218: case 2:
1219: stw_raw(addr, val);
1220: break;
1221: case 4:
1222: stl_raw(addr, val);
1223: break;
1224: case 8:
1225: default:
1226: stq_raw(addr, val);
1227: break;
1228: }
1229: }
1230: break;
1231: case 0x81: /* Secondary */
1232: case 0x89: /* Secondary LE */
1233: /* XXX */
1234: return;
1235:
1236: case 0x82: /* Primary no-fault, RO */
1237: case 0x83: /* Secondary no-fault, RO */
1238: case 0x8a: /* Primary no-fault LE, RO */
1239: case 0x8b: /* Secondary no-fault LE, RO */
1240: default:
1241: do_unassigned_access(addr, 1, 0, 1, size);
1242: return;
1243: }
1244: }
1245:
1246: #else /* CONFIG_USER_ONLY */
1247:
1248: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1249: {
1250: uint64_t ret = 0;
1251: #if defined(DEBUG_ASI)
1252: target_ulong last_addr = addr;
1253: #endif
1254:
1255: asi &= 0xff;
1256:
1257: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1258: || (cpu_has_hypervisor(env)
1259: && asi >= 0x30 && asi < 0x80
1260: && !(env->hpstate & HS_PRIV))) {
1261: helper_raise_exception(env, TT_PRIV_ACT);
1262: }
1263:
1264: helper_check_align(addr, size - 1);
1265: addr = asi_address_mask(env, asi, addr);
1266:
1267: /* process nonfaulting loads first */
1268: if ((asi & 0xf6) == 0x82) {
1269: int mmu_idx;
1270:
1271: /* secondary space access has lowest asi bit equal to 1 */
1272: if (env->pstate & PS_PRIV) {
1273: mmu_idx = (asi & 1) ? MMU_KERNEL_SECONDARY_IDX : MMU_KERNEL_IDX;
1274: } else {
1275: mmu_idx = (asi & 1) ? MMU_USER_SECONDARY_IDX : MMU_USER_IDX;
1276: }
1277:
1278: if (cpu_get_phys_page_nofault(env, addr, mmu_idx) == -1ULL) {
1279: #ifdef DEBUG_ASI
1280: dump_asi("read ", last_addr, asi, size, ret);
1281: #endif
1282: /* env->exception_index is set in get_physical_address_data(). */
1283: helper_raise_exception(env, env->exception_index);
1284: }
1285:
1286: /* convert nonfaulting load ASIs to normal load ASIs */
1287: asi &= ~0x02;
1288: }
1289:
1290: switch (asi) {
1291: case 0x10: /* As if user primary */
1292: case 0x11: /* As if user secondary */
1293: case 0x18: /* As if user primary LE */
1294: case 0x19: /* As if user secondary LE */
1295: case 0x80: /* Primary */
1296: case 0x81: /* Secondary */
1297: case 0x88: /* Primary LE */
1298: case 0x89: /* Secondary LE */
1299: case 0xe2: /* UA2007 Primary block init */
1300: case 0xe3: /* UA2007 Secondary block init */
1301: if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1302: if (cpu_hypervisor_mode(env)) {
1303: switch (size) {
1304: case 1:
1305: ret = ldub_hypv(addr);
1306: break;
1307: case 2:
1308: ret = lduw_hypv(addr);
1309: break;
1310: case 4:
1311: ret = ldl_hypv(addr);
1312: break;
1313: default:
1314: case 8:
1315: ret = ldq_hypv(addr);
1316: break;
1317: }
1318: } else {
1319: /* secondary space access has lowest asi bit equal to 1 */
1320: if (asi & 1) {
1321: switch (size) {
1322: case 1:
1323: ret = ldub_kernel_secondary(addr);
1324: break;
1325: case 2:
1326: ret = lduw_kernel_secondary(addr);
1327: break;
1328: case 4:
1329: ret = ldl_kernel_secondary(addr);
1330: break;
1331: default:
1332: case 8:
1333: ret = ldq_kernel_secondary(addr);
1334: break;
1335: }
1336: } else {
1337: switch (size) {
1338: case 1:
1339: ret = ldub_kernel(addr);
1340: break;
1341: case 2:
1342: ret = lduw_kernel(addr);
1343: break;
1344: case 4:
1345: ret = ldl_kernel(addr);
1346: break;
1347: default:
1348: case 8:
1349: ret = ldq_kernel(addr);
1350: break;
1351: }
1352: }
1353: }
1354: } else {
1355: /* secondary space access has lowest asi bit equal to 1 */
1356: if (asi & 1) {
1357: switch (size) {
1358: case 1:
1359: ret = ldub_user_secondary(addr);
1360: break;
1361: case 2:
1362: ret = lduw_user_secondary(addr);
1363: break;
1364: case 4:
1365: ret = ldl_user_secondary(addr);
1366: break;
1367: default:
1368: case 8:
1369: ret = ldq_user_secondary(addr);
1370: break;
1371: }
1372: } else {
1373: switch (size) {
1374: case 1:
1375: ret = ldub_user(addr);
1376: break;
1377: case 2:
1378: ret = lduw_user(addr);
1379: break;
1380: case 4:
1381: ret = ldl_user(addr);
1382: break;
1383: default:
1384: case 8:
1385: ret = ldq_user(addr);
1386: break;
1387: }
1388: }
1389: }
1390: break;
1391: case 0x14: /* Bypass */
1392: case 0x15: /* Bypass, non-cacheable */
1393: case 0x1c: /* Bypass LE */
1394: case 0x1d: /* Bypass, non-cacheable LE */
1395: {
1396: switch (size) {
1397: case 1:
1398: ret = ldub_phys(addr);
1399: break;
1400: case 2:
1401: ret = lduw_phys(addr);
1402: break;
1403: case 4:
1404: ret = ldl_phys(addr);
1405: break;
1406: default:
1407: case 8:
1408: ret = ldq_phys(addr);
1409: break;
1410: }
1411: break;
1412: }
1413: case 0x24: /* Nucleus quad LDD 128 bit atomic */
1414: case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
1415: Only ldda allowed */
1416: helper_raise_exception(env, TT_ILL_INSN);
1417: return 0;
1418: case 0x04: /* Nucleus */
1419: case 0x0c: /* Nucleus Little Endian (LE) */
1420: {
1421: switch (size) {
1422: case 1:
1423: ret = ldub_nucleus(addr);
1424: break;
1425: case 2:
1426: ret = lduw_nucleus(addr);
1427: break;
1428: case 4:
1429: ret = ldl_nucleus(addr);
1430: break;
1431: default:
1432: case 8:
1433: ret = ldq_nucleus(addr);
1434: break;
1435: }
1436: break;
1437: }
1438: case 0x4a: /* UPA config */
1439: /* XXX */
1440: break;
1441: case 0x45: /* LSU */
1442: ret = env->lsu;
1443: break;
1444: case 0x50: /* I-MMU regs */
1445: {
1446: int reg = (addr >> 3) & 0xf;
1447:
1448: if (reg == 0) {
1449: /* I-TSB Tag Target register */
1450: ret = ultrasparc_tag_target(env->immu.tag_access);
1451: } else {
1452: ret = env->immuregs[reg];
1453: }
1454:
1455: break;
1456: }
1457: case 0x51: /* I-MMU 8k TSB pointer */
1458: {
1459: /* env->immuregs[5] holds I-MMU TSB register value
1460: env->immuregs[6] holds I-MMU Tag Access register value */
1461: ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
1462: 8*1024);
1463: break;
1464: }
1465: case 0x52: /* I-MMU 64k TSB pointer */
1466: {
1467: /* env->immuregs[5] holds I-MMU TSB register value
1468: env->immuregs[6] holds I-MMU Tag Access register value */
1469: ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
1470: 64*1024);
1471: break;
1472: }
1473: case 0x55: /* I-MMU data access */
1474: {
1475: int reg = (addr >> 3) & 0x3f;
1476:
1477: ret = env->itlb[reg].tte;
1478: break;
1479: }
1480: case 0x56: /* I-MMU tag read */
1481: {
1482: int reg = (addr >> 3) & 0x3f;
1483:
1484: ret = env->itlb[reg].tag;
1485: break;
1486: }
1487: case 0x58: /* D-MMU regs */
1488: {
1489: int reg = (addr >> 3) & 0xf;
1490:
1491: if (reg == 0) {
1492: /* D-TSB Tag Target register */
1493: ret = ultrasparc_tag_target(env->dmmu.tag_access);
1494: } else {
1495: ret = env->dmmuregs[reg];
1496: }
1497: break;
1498: }
1499: case 0x59: /* D-MMU 8k TSB pointer */
1500: {
1501: /* env->dmmuregs[5] holds D-MMU TSB register value
1502: env->dmmuregs[6] holds D-MMU Tag Access register value */
1503: ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
1504: 8*1024);
1505: break;
1506: }
1507: case 0x5a: /* D-MMU 64k TSB pointer */
1508: {
1509: /* env->dmmuregs[5] holds D-MMU TSB register value
1510: env->dmmuregs[6] holds D-MMU Tag Access register value */
1511: ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
1512: 64*1024);
1513: break;
1514: }
1515: case 0x5d: /* D-MMU data access */
1516: {
1517: int reg = (addr >> 3) & 0x3f;
1518:
1519: ret = env->dtlb[reg].tte;
1520: break;
1521: }
1522: case 0x5e: /* D-MMU tag read */
1523: {
1524: int reg = (addr >> 3) & 0x3f;
1525:
1526: ret = env->dtlb[reg].tag;
1527: break;
1528: }
1529: case 0x46: /* D-cache data */
1530: case 0x47: /* D-cache tag access */
1531: case 0x4b: /* E-cache error enable */
1532: case 0x4c: /* E-cache asynchronous fault status */
1533: case 0x4d: /* E-cache asynchronous fault address */
1534: case 0x4e: /* E-cache tag data */
1535: case 0x66: /* I-cache instruction access */
1536: case 0x67: /* I-cache tag access */
1537: case 0x6e: /* I-cache predecode */
1538: case 0x6f: /* I-cache LRU etc. */
1539: case 0x76: /* E-cache tag */
1540: case 0x7e: /* E-cache tag */
1541: break;
1542: case 0x5b: /* D-MMU data pointer */
1543: case 0x48: /* Interrupt dispatch, RO */
1544: case 0x49: /* Interrupt data receive */
1545: case 0x7f: /* Incoming interrupt vector, RO */
1546: /* XXX */
1547: break;
1548: case 0x54: /* I-MMU data in, WO */
1549: case 0x57: /* I-MMU demap, WO */
1550: case 0x5c: /* D-MMU data in, WO */
1551: case 0x5f: /* D-MMU demap, WO */
1552: case 0x77: /* Interrupt vector, WO */
1553: default:
1554: do_unassigned_access(addr, 0, 0, 1, size);
1555: ret = 0;
1556: break;
1557: }
1558:
1559: /* Convert from little endian */
1560: switch (asi) {
1561: case 0x0c: /* Nucleus Little Endian (LE) */
1562: case 0x18: /* As if user primary LE */
1563: case 0x19: /* As if user secondary LE */
1564: case 0x1c: /* Bypass LE */
1565: case 0x1d: /* Bypass, non-cacheable LE */
1566: case 0x88: /* Primary LE */
1567: case 0x89: /* Secondary LE */
1568: switch(size) {
1569: case 2:
1570: ret = bswap16(ret);
1571: break;
1572: case 4:
1573: ret = bswap32(ret);
1574: break;
1575: case 8:
1576: ret = bswap64(ret);
1577: break;
1578: default:
1579: break;
1580: }
1581: default:
1582: break;
1583: }
1584:
1585: /* Convert to signed number */
1586: if (sign) {
1587: switch (size) {
1588: case 1:
1589: ret = (int8_t) ret;
1590: break;
1591: case 2:
1592: ret = (int16_t) ret;
1593: break;
1594: case 4:
1595: ret = (int32_t) ret;
1596: break;
1597: default:
1598: break;
1599: }
1600: }
1601: #ifdef DEBUG_ASI
1602: dump_asi("read ", last_addr, asi, size, ret);
1603: #endif
1604: return ret;
1605: }
1606:
1607: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1608: {
1609: #ifdef DEBUG_ASI
1610: dump_asi("write", addr, asi, size, val);
1611: #endif
1612:
1613: asi &= 0xff;
1614:
1615: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1616: || (cpu_has_hypervisor(env)
1617: && asi >= 0x30 && asi < 0x80
1618: && !(env->hpstate & HS_PRIV))) {
1619: helper_raise_exception(env, TT_PRIV_ACT);
1620: }
1621:
1622: helper_check_align(addr, size - 1);
1623: addr = asi_address_mask(env, asi, addr);
1624:
1625: /* Convert to little endian */
1626: switch (asi) {
1627: case 0x0c: /* Nucleus Little Endian (LE) */
1628: case 0x18: /* As if user primary LE */
1629: case 0x19: /* As if user secondary LE */
1630: case 0x1c: /* Bypass LE */
1631: case 0x1d: /* Bypass, non-cacheable LE */
1632: case 0x88: /* Primary LE */
1633: case 0x89: /* Secondary LE */
1634: switch (size) {
1635: case 2:
1636: val = bswap16(val);
1637: break;
1638: case 4:
1639: val = bswap32(val);
1640: break;
1641: case 8:
1642: val = bswap64(val);
1643: break;
1644: default:
1645: break;
1646: }
1647: default:
1648: break;
1649: }
1650:
1651: switch (asi) {
1652: case 0x10: /* As if user primary */
1653: case 0x11: /* As if user secondary */
1654: case 0x18: /* As if user primary LE */
1655: case 0x19: /* As if user secondary LE */
1656: case 0x80: /* Primary */
1657: case 0x81: /* Secondary */
1658: case 0x88: /* Primary LE */
1659: case 0x89: /* Secondary LE */
1660: case 0xe2: /* UA2007 Primary block init */
1661: case 0xe3: /* UA2007 Secondary block init */
1662: if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1663: if (cpu_hypervisor_mode(env)) {
1664: switch (size) {
1665: case 1:
1666: stb_hypv(addr, val);
1667: break;
1668: case 2:
1669: stw_hypv(addr, val);
1670: break;
1671: case 4:
1672: stl_hypv(addr, val);
1673: break;
1674: case 8:
1675: default:
1676: stq_hypv(addr, val);
1677: break;
1678: }
1679: } else {
1680: /* secondary space access has lowest asi bit equal to 1 */
1681: if (asi & 1) {
1682: switch (size) {
1683: case 1:
1684: stb_kernel_secondary(addr, val);
1685: break;
1686: case 2:
1687: stw_kernel_secondary(addr, val);
1688: break;
1689: case 4:
1690: stl_kernel_secondary(addr, val);
1691: break;
1692: case 8:
1693: default:
1694: stq_kernel_secondary(addr, val);
1695: break;
1696: }
1697: } else {
1698: switch (size) {
1699: case 1:
1700: stb_kernel(addr, val);
1701: break;
1702: case 2:
1703: stw_kernel(addr, val);
1704: break;
1705: case 4:
1706: stl_kernel(addr, val);
1707: break;
1708: case 8:
1709: default:
1710: stq_kernel(addr, val);
1711: break;
1712: }
1713: }
1714: }
1715: } else {
1716: /* secondary space access has lowest asi bit equal to 1 */
1717: if (asi & 1) {
1718: switch (size) {
1719: case 1:
1720: stb_user_secondary(addr, val);
1721: break;
1722: case 2:
1723: stw_user_secondary(addr, val);
1724: break;
1725: case 4:
1726: stl_user_secondary(addr, val);
1727: break;
1728: case 8:
1729: default:
1730: stq_user_secondary(addr, val);
1731: break;
1732: }
1733: } else {
1734: switch (size) {
1735: case 1:
1736: stb_user(addr, val);
1737: break;
1738: case 2:
1739: stw_user(addr, val);
1740: break;
1741: case 4:
1742: stl_user(addr, val);
1743: break;
1744: case 8:
1745: default:
1746: stq_user(addr, val);
1747: break;
1748: }
1749: }
1750: }
1751: break;
1752: case 0x14: /* Bypass */
1753: case 0x15: /* Bypass, non-cacheable */
1754: case 0x1c: /* Bypass LE */
1755: case 0x1d: /* Bypass, non-cacheable LE */
1756: {
1757: switch (size) {
1758: case 1:
1759: stb_phys(addr, val);
1760: break;
1761: case 2:
1762: stw_phys(addr, val);
1763: break;
1764: case 4:
1765: stl_phys(addr, val);
1766: break;
1767: case 8:
1768: default:
1769: stq_phys(addr, val);
1770: break;
1771: }
1772: }
1773: return;
1774: case 0x24: /* Nucleus quad LDD 128 bit atomic */
1775: case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
1776: Only ldda allowed */
1777: helper_raise_exception(env, TT_ILL_INSN);
1778: return;
1779: case 0x04: /* Nucleus */
1780: case 0x0c: /* Nucleus Little Endian (LE) */
1781: {
1782: switch (size) {
1783: case 1:
1784: stb_nucleus(addr, val);
1785: break;
1786: case 2:
1787: stw_nucleus(addr, val);
1788: break;
1789: case 4:
1790: stl_nucleus(addr, val);
1791: break;
1792: default:
1793: case 8:
1794: stq_nucleus(addr, val);
1795: break;
1796: }
1797: break;
1798: }
1799:
1800: case 0x4a: /* UPA config */
1801: /* XXX */
1802: return;
1803: case 0x45: /* LSU */
1804: {
1805: uint64_t oldreg;
1806:
1807: oldreg = env->lsu;
1808: env->lsu = val & (DMMU_E | IMMU_E);
1809: /* Mappings generated during D/I MMU disabled mode are
1810: invalid in normal mode */
1811: if (oldreg != env->lsu) {
1812: DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
1813: oldreg, env->lsu);
1814: #ifdef DEBUG_MMU
1815: dump_mmu(stdout, fprintf, env1);
1816: #endif
1817: tlb_flush(env, 1);
1818: }
1819: return;
1820: }
1821: case 0x50: /* I-MMU regs */
1822: {
1823: int reg = (addr >> 3) & 0xf;
1824: uint64_t oldreg;
1825:
1826: oldreg = env->immuregs[reg];
1827: switch (reg) {
1828: case 0: /* RO */
1829: return;
1830: case 1: /* Not in I-MMU */
1831: case 2:
1832: return;
1833: case 3: /* SFSR */
1834: if ((val & 1) == 0) {
1835: val = 0; /* Clear SFSR */
1836: }
1837: env->immu.sfsr = val;
1838: break;
1839: case 4: /* RO */
1840: return;
1841: case 5: /* TSB access */
1842: DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
1843: PRIx64 "\n", env->immu.tsb, val);
1844: env->immu.tsb = val;
1845: break;
1846: case 6: /* Tag access */
1847: env->immu.tag_access = val;
1848: break;
1849: case 7:
1850: case 8:
1851: return;
1852: default:
1853: break;
1854: }
1855:
1856: if (oldreg != env->immuregs[reg]) {
1857: DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
1858: PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1859: }
1860: #ifdef DEBUG_MMU
1861: dump_mmu(stdout, fprintf, env);
1862: #endif
1863: return;
1864: }
1865: case 0x54: /* I-MMU data in */
1866: replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
1867: return;
1868: case 0x55: /* I-MMU data access */
1869: {
1870: /* TODO: auto demap */
1871:
1872: unsigned int i = (addr >> 3) & 0x3f;
1873:
1874: replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
1875:
1876: #ifdef DEBUG_MMU
1877: DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
1878: dump_mmu(stdout, fprintf, env);
1879: #endif
1880: return;
1881: }
1882: case 0x57: /* I-MMU demap */
1883: demap_tlb(env->itlb, addr, "immu", env);
1884: return;
1885: case 0x58: /* D-MMU regs */
1886: {
1887: int reg = (addr >> 3) & 0xf;
1888: uint64_t oldreg;
1889:
1890: oldreg = env->dmmuregs[reg];
1891: switch (reg) {
1892: case 0: /* RO */
1893: case 4:
1894: return;
1895: case 3: /* SFSR */
1896: if ((val & 1) == 0) {
1897: val = 0; /* Clear SFSR, Fault address */
1898: env->dmmu.sfar = 0;
1899: }
1900: env->dmmu.sfsr = val;
1901: break;
1902: case 1: /* Primary context */
1903: env->dmmu.mmu_primary_context = val;
1904: /* can be optimized to only flush MMU_USER_IDX
1905: and MMU_KERNEL_IDX entries */
1906: tlb_flush(env, 1);
1907: break;
1908: case 2: /* Secondary context */
1909: env->dmmu.mmu_secondary_context = val;
1910: /* can be optimized to only flush MMU_USER_SECONDARY_IDX
1911: and MMU_KERNEL_SECONDARY_IDX entries */
1912: tlb_flush(env, 1);
1913: break;
1914: case 5: /* TSB access */
1915: DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
1916: PRIx64 "\n", env->dmmu.tsb, val);
1917: env->dmmu.tsb = val;
1918: break;
1919: case 6: /* Tag access */
1920: env->dmmu.tag_access = val;
1921: break;
1922: case 7: /* Virtual Watchpoint */
1923: case 8: /* Physical Watchpoint */
1924: default:
1925: env->dmmuregs[reg] = val;
1926: break;
1927: }
1928:
1929: if (oldreg != env->dmmuregs[reg]) {
1930: DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
1931: PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1932: }
1933: #ifdef DEBUG_MMU
1934: dump_mmu(stdout, fprintf, env);
1935: #endif
1936: return;
1937: }
1938: case 0x5c: /* D-MMU data in */
1939: replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
1940: return;
1941: case 0x5d: /* D-MMU data access */
1942: {
1943: unsigned int i = (addr >> 3) & 0x3f;
1944:
1945: replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
1946:
1947: #ifdef DEBUG_MMU
1948: DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
1949: dump_mmu(stdout, fprintf, env);
1950: #endif
1951: return;
1952: }
1953: case 0x5f: /* D-MMU demap */
1954: demap_tlb(env->dtlb, addr, "dmmu", env);
1955: return;
1956: case 0x49: /* Interrupt data receive */
1957: /* XXX */
1958: return;
1959: case 0x46: /* D-cache data */
1960: case 0x47: /* D-cache tag access */
1961: case 0x4b: /* E-cache error enable */
1962: case 0x4c: /* E-cache asynchronous fault status */
1963: case 0x4d: /* E-cache asynchronous fault address */
1964: case 0x4e: /* E-cache tag data */
1965: case 0x66: /* I-cache instruction access */
1966: case 0x67: /* I-cache tag access */
1967: case 0x6e: /* I-cache predecode */
1968: case 0x6f: /* I-cache LRU etc. */
1969: case 0x76: /* E-cache tag */
1970: case 0x7e: /* E-cache tag */
1971: return;
1972: case 0x51: /* I-MMU 8k TSB pointer, RO */
1973: case 0x52: /* I-MMU 64k TSB pointer, RO */
1974: case 0x56: /* I-MMU tag read, RO */
1975: case 0x59: /* D-MMU 8k TSB pointer, RO */
1976: case 0x5a: /* D-MMU 64k TSB pointer, RO */
1977: case 0x5b: /* D-MMU data pointer, RO */
1978: case 0x5e: /* D-MMU tag read, RO */
1979: case 0x48: /* Interrupt dispatch, RO */
1980: case 0x7f: /* Incoming interrupt vector, RO */
1981: case 0x82: /* Primary no-fault, RO */
1982: case 0x83: /* Secondary no-fault, RO */
1983: case 0x8a: /* Primary no-fault LE, RO */
1984: case 0x8b: /* Secondary no-fault LE, RO */
1985: default:
1986: do_unassigned_access(addr, 1, 0, 1, size);
1987: return;
1988: }
1989: }
1990: #endif /* CONFIG_USER_ONLY */
1991:
1992: void helper_ldda_asi(target_ulong addr, int asi, int rd)
1993: {
1994: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1995: || (cpu_has_hypervisor(env)
1996: && asi >= 0x30 && asi < 0x80
1997: && !(env->hpstate & HS_PRIV))) {
1998: helper_raise_exception(env, TT_PRIV_ACT);
1999: }
2000:
2001: addr = asi_address_mask(env, asi, addr);
2002:
2003: switch (asi) {
2004: #if !defined(CONFIG_USER_ONLY)
2005: case 0x24: /* Nucleus quad LDD 128 bit atomic */
2006: case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
2007: helper_check_align(addr, 0xf);
2008: if (rd == 0) {
2009: env->gregs[1] = ldq_nucleus(addr + 8);
2010: if (asi == 0x2c) {
2011: bswap64s(&env->gregs[1]);
2012: }
2013: } else if (rd < 8) {
2014: env->gregs[rd] = ldq_nucleus(addr);
2015: env->gregs[rd + 1] = ldq_nucleus(addr + 8);
2016: if (asi == 0x2c) {
2017: bswap64s(&env->gregs[rd]);
2018: bswap64s(&env->gregs[rd + 1]);
2019: }
2020: } else {
2021: env->regwptr[rd] = ldq_nucleus(addr);
2022: env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
2023: if (asi == 0x2c) {
2024: bswap64s(&env->regwptr[rd]);
2025: bswap64s(&env->regwptr[rd + 1]);
2026: }
2027: }
2028: break;
2029: #endif
2030: default:
2031: helper_check_align(addr, 0x3);
2032: if (rd == 0) {
2033: env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2034: } else if (rd < 8) {
2035: env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2036: env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2037: } else {
2038: env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2039: env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2040: }
2041: break;
2042: }
2043: }
2044:
2045: void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2046: {
2047: unsigned int i;
2048: target_ulong val;
2049:
2050: helper_check_align(addr, 3);
2051: addr = asi_address_mask(env, asi, addr);
2052:
2053: switch (asi) {
2054: case 0xf0: /* UA2007/JPS1 Block load primary */
2055: case 0xf1: /* UA2007/JPS1 Block load secondary */
2056: case 0xf8: /* UA2007/JPS1 Block load primary LE */
2057: case 0xf9: /* UA2007/JPS1 Block load secondary LE */
2058: if (rd & 7) {
2059: helper_raise_exception(env, TT_ILL_INSN);
2060: return;
2061: }
2062: helper_check_align(addr, 0x3f);
2063: for (i = 0; i < 8; i++, rd += 2, addr += 8) {
2064: env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x8f, 8, 0);
2065: }
2066: return;
2067:
2068: case 0x16: /* UA2007 Block load primary, user privilege */
2069: case 0x17: /* UA2007 Block load secondary, user privilege */
2070: case 0x1e: /* UA2007 Block load primary LE, user privilege */
2071: case 0x1f: /* UA2007 Block load secondary LE, user privilege */
2072: case 0x70: /* JPS1 Block load primary, user privilege */
2073: case 0x71: /* JPS1 Block load secondary, user privilege */
2074: case 0x78: /* JPS1 Block load primary LE, user privilege */
2075: case 0x79: /* JPS1 Block load secondary LE, user privilege */
2076: if (rd & 7) {
2077: helper_raise_exception(env, TT_ILL_INSN);
2078: return;
2079: }
2080: helper_check_align(addr, 0x3f);
2081: for (i = 0; i < 8; i++, rd += 2, addr += 4) {
2082: env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x19, 8, 0);
2083: }
2084: return;
2085:
2086: default:
2087: break;
2088: }
2089:
2090: switch (size) {
2091: default:
2092: case 4:
2093: val = helper_ld_asi(addr, asi, size, 0);
2094: if (rd & 1) {
2095: env->fpr[rd/2].l.lower = val;
2096: } else {
2097: env->fpr[rd/2].l.upper = val;
2098: }
2099: break;
2100: case 8:
2101: env->fpr[rd/2].ll = helper_ld_asi(addr, asi, size, 0);
2102: break;
2103: case 16:
2104: env->fpr[rd/2].ll = helper_ld_asi(addr, asi, 8, 0);
2105: env->fpr[rd/2 + 1].ll = helper_ld_asi(addr + 8, asi, 8, 0);
2106: break;
2107: }
2108: }
2109:
2110: void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2111: {
2112: unsigned int i;
2113: target_ulong val;
2114:
2115: helper_check_align(addr, 3);
2116: addr = asi_address_mask(env, asi, addr);
2117:
2118: switch (asi) {
2119: case 0xe0: /* UA2007/JPS1 Block commit store primary (cache flush) */
2120: case 0xe1: /* UA2007/JPS1 Block commit store secondary (cache flush) */
2121: case 0xf0: /* UA2007/JPS1 Block store primary */
2122: case 0xf1: /* UA2007/JPS1 Block store secondary */
2123: case 0xf8: /* UA2007/JPS1 Block store primary LE */
2124: case 0xf9: /* UA2007/JPS1 Block store secondary LE */
2125: if (rd & 7) {
2126: helper_raise_exception(env, TT_ILL_INSN);
2127: return;
2128: }
2129: helper_check_align(addr, 0x3f);
2130: for (i = 0; i < 8; i++, rd += 2, addr += 8) {
2131: helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
2132: }
2133:
2134: return;
2135: case 0x16: /* UA2007 Block load primary, user privilege */
2136: case 0x17: /* UA2007 Block load secondary, user privilege */
2137: case 0x1e: /* UA2007 Block load primary LE, user privilege */
2138: case 0x1f: /* UA2007 Block load secondary LE, user privilege */
2139: case 0x70: /* JPS1 Block store primary, user privilege */
2140: case 0x71: /* JPS1 Block store secondary, user privilege */
2141: case 0x78: /* JPS1 Block load primary LE, user privilege */
2142: case 0x79: /* JPS1 Block load secondary LE, user privilege */
2143: if (rd & 7) {
2144: helper_raise_exception(env, TT_ILL_INSN);
2145: return;
2146: }
2147: helper_check_align(addr, 0x3f);
2148: for (i = 0; i < 8; i++, rd += 2, addr += 8) {
2149: helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x19, 8);
2150: }
2151:
2152: return;
2153: default:
2154: break;
2155: }
2156:
2157: switch (size) {
2158: default:
2159: case 4:
2160: if (rd & 1) {
2161: val = env->fpr[rd/2].l.lower;
2162: } else {
2163: val = env->fpr[rd/2].l.upper;
2164: }
2165: helper_st_asi(addr, val, asi, size);
2166: break;
2167: case 8:
2168: helper_st_asi(addr, env->fpr[rd/2].ll, asi, size);
2169: break;
2170: case 16:
2171: helper_st_asi(addr, env->fpr[rd/2].ll, asi, 8);
2172: helper_st_asi(addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
2173: break;
2174: }
2175: }
2176:
2177: target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2178: target_ulong val2, uint32_t asi)
2179: {
2180: target_ulong ret;
2181:
2182: val2 &= 0xffffffffUL;
2183: ret = helper_ld_asi(addr, asi, 4, 0);
2184: ret &= 0xffffffffUL;
2185: if (val2 == ret) {
2186: helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2187: }
2188: return ret;
2189: }
2190:
2191: target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2192: target_ulong val2, uint32_t asi)
2193: {
2194: target_ulong ret;
2195:
2196: ret = helper_ld_asi(addr, asi, 8, 0);
2197: if (val2 == ret) {
2198: helper_st_asi(addr, val1, asi, 8);
2199: }
2200: return ret;
2201: }
2202: #endif /* TARGET_SPARC64 */
2203:
2204: void helper_ldqf(target_ulong addr, int mem_idx)
2205: {
2206: /* XXX add 128 bit load */
2207: CPU_QuadU u;
2208:
2209: helper_check_align(addr, 7);
2210: #if !defined(CONFIG_USER_ONLY)
2211: switch (mem_idx) {
2212: case MMU_USER_IDX:
2213: u.ll.upper = ldq_user(addr);
2214: u.ll.lower = ldq_user(addr + 8);
2215: QT0 = u.q;
2216: break;
2217: case MMU_KERNEL_IDX:
2218: u.ll.upper = ldq_kernel(addr);
2219: u.ll.lower = ldq_kernel(addr + 8);
2220: QT0 = u.q;
2221: break;
2222: #ifdef TARGET_SPARC64
2223: case MMU_HYPV_IDX:
2224: u.ll.upper = ldq_hypv(addr);
2225: u.ll.lower = ldq_hypv(addr + 8);
2226: QT0 = u.q;
2227: break;
2228: #endif
2229: default:
2230: DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx);
2231: break;
2232: }
2233: #else
2234: u.ll.upper = ldq_raw(address_mask(env, addr));
2235: u.ll.lower = ldq_raw(address_mask(env, addr + 8));
2236: QT0 = u.q;
2237: #endif
2238: }
2239:
2240: void helper_stqf(target_ulong addr, int mem_idx)
2241: {
2242: /* XXX add 128 bit store */
2243: CPU_QuadU u;
2244:
2245: helper_check_align(addr, 7);
2246: #if !defined(CONFIG_USER_ONLY)
2247: switch (mem_idx) {
2248: case MMU_USER_IDX:
2249: u.q = QT0;
2250: stq_user(addr, u.ll.upper);
2251: stq_user(addr + 8, u.ll.lower);
2252: break;
2253: case MMU_KERNEL_IDX:
2254: u.q = QT0;
2255: stq_kernel(addr, u.ll.upper);
2256: stq_kernel(addr + 8, u.ll.lower);
2257: break;
2258: #ifdef TARGET_SPARC64
2259: case MMU_HYPV_IDX:
2260: u.q = QT0;
2261: stq_hypv(addr, u.ll.upper);
2262: stq_hypv(addr + 8, u.ll.lower);
2263: break;
2264: #endif
2265: default:
2266: DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx);
2267: break;
2268: }
2269: #else
2270: u.q = QT0;
2271: stq_raw(address_mask(env, addr), u.ll.upper);
2272: stq_raw(address_mask(env, addr + 8), u.ll.lower);
2273: #endif
2274: }
2275:
2276: #ifndef TARGET_SPARC64
2277: #if !defined(CONFIG_USER_ONLY)
2278: static void do_unassigned_access(target_phys_addr_t addr, int is_write,
2279: int is_exec, int is_asi, int size)
2280: {
2281: int fault_type;
2282:
2283: #ifdef DEBUG_UNASSIGNED
2284: if (is_asi) {
2285: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
2286: " asi 0x%02x from " TARGET_FMT_lx "\n",
2287: is_exec ? "exec" : is_write ? "write" : "read", size,
2288: size == 1 ? "" : "s", addr, is_asi, env->pc);
2289: } else {
2290: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
2291: " from " TARGET_FMT_lx "\n",
2292: is_exec ? "exec" : is_write ? "write" : "read", size,
2293: size == 1 ? "" : "s", addr, env->pc);
2294: }
2295: #endif
2296: /* Don't overwrite translation and access faults */
2297: fault_type = (env->mmuregs[3] & 0x1c) >> 2;
2298: if ((fault_type > 4) || (fault_type == 0)) {
2299: env->mmuregs[3] = 0; /* Fault status register */
2300: if (is_asi) {
2301: env->mmuregs[3] |= 1 << 16;
2302: }
2303: if (env->psrs) {
2304: env->mmuregs[3] |= 1 << 5;
2305: }
2306: if (is_exec) {
2307: env->mmuregs[3] |= 1 << 6;
2308: }
2309: if (is_write) {
2310: env->mmuregs[3] |= 1 << 7;
2311: }
2312: env->mmuregs[3] |= (5 << 2) | 2;
2313: /* SuperSPARC will never place instruction fault addresses in the FAR */
2314: if (!is_exec) {
2315: env->mmuregs[4] = addr; /* Fault address register */
2316: }
2317: }
2318: /* overflow (same type fault was not read before another fault) */
2319: if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
2320: env->mmuregs[3] |= 1;
2321: }
2322:
2323: if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2324: if (is_exec) {
2325: helper_raise_exception(env, TT_CODE_ACCESS);
2326: } else {
2327: helper_raise_exception(env, TT_DATA_ACCESS);
2328: }
2329: }
2330:
2331: /* flush neverland mappings created during no-fault mode,
2332: so the sequential MMU faults report proper fault types */
2333: if (env->mmuregs[0] & MMU_NF) {
2334: tlb_flush(env, 1);
2335: }
2336: }
2337: #endif
2338: #else
2339: #if defined(CONFIG_USER_ONLY)
2340: static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
2341: int is_asi, int size)
2342: #else
2343: static void do_unassigned_access(target_phys_addr_t addr, int is_write,
2344: int is_exec, int is_asi, int size)
2345: #endif
2346: {
2347: #ifdef DEBUG_UNASSIGNED
2348: printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
2349: "\n", addr, env->pc);
2350: #endif
2351:
2352: if (is_exec) {
2353: helper_raise_exception(env, TT_CODE_ACCESS);
2354: } else {
2355: helper_raise_exception(env, TT_DATA_ACCESS);
2356: }
2357: }
2358: #endif
2359:
2360: #if !defined(CONFIG_USER_ONLY)
2361: void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
2362: int is_write, int is_exec, int is_asi, int size)
2363: {
2364: CPUState *saved_env;
2365:
2366: saved_env = env;
2367: env = env1;
2368: do_unassigned_access(addr, is_write, is_exec, is_asi, size);
2369: env = saved_env;
2370: }
2371: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.