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