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