3 |
3 |
//#define DEBUG_PCALL
|
4 |
4 |
//#define DEBUG_MMU
|
5 |
5 |
//#define DEBUG_UNALIGNED
|
|
6 |
//#define DEBUG_UNASSIGNED
|
6 |
7 |
|
7 |
8 |
void raise_exception(int tt)
|
8 |
9 |
{
|
... | ... | |
151 |
152 |
uint32_t ret = 0;
|
152 |
153 |
|
153 |
154 |
switch (asi) {
|
|
155 |
case 2: /* SuperSparc MXCC registers */
|
|
156 |
break;
|
154 |
157 |
case 3: /* MMU probe */
|
155 |
158 |
{
|
156 |
159 |
int mmulev;
|
... | ... | |
179 |
182 |
#endif
|
180 |
183 |
}
|
181 |
184 |
break;
|
182 |
|
case 0x20 ... 0x2f: /* MMU passthrough */
|
|
185 |
case 9: /* Supervisor code access */
|
|
186 |
switch(size) {
|
|
187 |
case 1:
|
|
188 |
ret = ldub_code(T0);
|
|
189 |
break;
|
|
190 |
case 2:
|
|
191 |
ret = lduw_code(T0 & ~1);
|
|
192 |
break;
|
|
193 |
default:
|
|
194 |
case 4:
|
|
195 |
ret = ldl_code(T0 & ~3);
|
|
196 |
break;
|
|
197 |
case 8:
|
|
198 |
ret = ldl_code(T0 & ~3);
|
|
199 |
T0 = ldl_code((T0 + 4) & ~3);
|
|
200 |
break;
|
|
201 |
}
|
|
202 |
break;
|
|
203 |
case 0xc: /* I-cache tag */
|
|
204 |
case 0xd: /* I-cache data */
|
|
205 |
case 0xe: /* D-cache tag */
|
|
206 |
case 0xf: /* D-cache data */
|
|
207 |
break;
|
|
208 |
case 0x20: /* MMU passthrough */
|
183 |
209 |
switch(size) {
|
184 |
210 |
case 1:
|
185 |
211 |
ret = ldub_phys(T0);
|
... | ... | |
197 |
223 |
break;
|
198 |
224 |
}
|
199 |
225 |
break;
|
|
226 |
case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
|
200 |
227 |
default:
|
|
228 |
do_unassigned_access(T0, 0, 0, 1);
|
201 |
229 |
ret = 0;
|
202 |
230 |
break;
|
203 |
231 |
}
|
... | ... | |
207 |
235 |
void helper_st_asi(int asi, int size, int sign)
|
208 |
236 |
{
|
209 |
237 |
switch(asi) {
|
|
238 |
case 2: /* SuperSparc MXCC registers */
|
|
239 |
break;
|
210 |
240 |
case 3: /* MMU flush */
|
211 |
241 |
{
|
212 |
242 |
int mmulev;
|
... | ... | |
271 |
301 |
#endif
|
272 |
302 |
return;
|
273 |
303 |
}
|
|
304 |
case 0xc: /* I-cache tag */
|
|
305 |
case 0xd: /* I-cache data */
|
|
306 |
case 0xe: /* D-cache tag */
|
|
307 |
case 0xf: /* D-cache data */
|
|
308 |
case 0x10: /* I/D-cache flush page */
|
|
309 |
case 0x11: /* I/D-cache flush segment */
|
|
310 |
case 0x12: /* I/D-cache flush region */
|
|
311 |
case 0x13: /* I/D-cache flush context */
|
|
312 |
case 0x14: /* I/D-cache flush user */
|
|
313 |
break;
|
274 |
314 |
case 0x17: /* Block copy, sta access */
|
275 |
315 |
{
|
276 |
316 |
// value (T1) = src
|
277 |
317 |
// address (T0) = dst
|
278 |
318 |
// copy 32 bytes
|
279 |
|
uint32_t src = T1, dst = T0;
|
280 |
|
uint8_t temp[32];
|
|
319 |
unsigned int i;
|
|
320 |
uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
|
281 |
321 |
|
282 |
|
tswap32s(&src);
|
283 |
|
|
284 |
|
cpu_physical_memory_read(src, (void *) &temp, 32);
|
285 |
|
cpu_physical_memory_write(dst, (void *) &temp, 32);
|
|
322 |
for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
|
|
323 |
temp = ldl_kernel(src);
|
|
324 |
stl_kernel(dst, temp);
|
|
325 |
}
|
286 |
326 |
}
|
287 |
327 |
return;
|
288 |
328 |
case 0x1f: /* Block fill, stda access */
|
... | ... | |
290 |
330 |
// value (T1, T2)
|
291 |
331 |
// address (T0) = dst
|
292 |
332 |
// fill 32 bytes
|
293 |
|
int i;
|
294 |
|
uint32_t dst = T0;
|
295 |
|
uint64_t val;
|
296 |
|
|
297 |
|
val = (((uint64_t)T1) << 32) | T2;
|
298 |
|
tswap64s(&val);
|
|
333 |
unsigned int i;
|
|
334 |
uint32_t dst = T0 & 7;
|
|
335 |
uint64_t val;
|
299 |
336 |
|
300 |
|
for (i = 0; i < 32; i += 8, dst += 8) {
|
301 |
|
cpu_physical_memory_write(dst, (void *) &val, 8);
|
302 |
|
}
|
|
337 |
val = (((uint64_t)T1) << 32) | T2;
|
|
338 |
|
|
339 |
for (i = 0; i < 32; i += 8, dst += 8)
|
|
340 |
stq_kernel(dst, val);
|
303 |
341 |
}
|
304 |
342 |
return;
|
305 |
|
case 0x20 ... 0x2f: /* MMU passthrough */
|
|
343 |
case 0x20: /* MMU passthrough */
|
306 |
344 |
{
|
307 |
345 |
switch(size) {
|
308 |
346 |
case 1:
|
... | ... | |
322 |
360 |
}
|
323 |
361 |
}
|
324 |
362 |
return;
|
|
363 |
case 0x31: /* Ross RT620 I-cache flush */
|
|
364 |
case 0x36: /* I-cache flash clear */
|
|
365 |
case 0x37: /* D-cache flash clear */
|
|
366 |
break;
|
|
367 |
case 9: /* Supervisor code access, XXX */
|
|
368 |
case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
|
325 |
369 |
default:
|
|
370 |
do_unassigned_access(T0, 1, 0, 1);
|
326 |
371 |
return;
|
327 |
372 |
}
|
328 |
373 |
}
|
... | ... | |
441 |
486 |
case 0x5f: // D-MMU demap, WO
|
442 |
487 |
case 0x77: // Interrupt vector, WO
|
443 |
488 |
default:
|
|
489 |
do_unassigned_access(T0, 0, 0, 1);
|
444 |
490 |
ret = 0;
|
445 |
491 |
break;
|
446 |
492 |
}
|
... | ... | |
656 |
702 |
case 0x8a: // Primary no-fault LE, RO
|
657 |
703 |
case 0x8b: // Secondary no-fault LE, RO
|
658 |
704 |
default:
|
|
705 |
do_unassigned_access(T0, 1, 0, 1);
|
659 |
706 |
return;
|
660 |
707 |
}
|
661 |
708 |
}
|
... | ... | |
986 |
1033 |
}
|
987 |
1034 |
|
988 |
1035 |
#endif
|
|
1036 |
|
|
1037 |
#ifndef TARGET_SPARC64
|
|
1038 |
void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
|
|
1039 |
int is_asi)
|
|
1040 |
{
|
|
1041 |
CPUState *saved_env;
|
|
1042 |
|
|
1043 |
/* XXX: hack to restore env in all cases, even if not called from
|
|
1044 |
generated code */
|
|
1045 |
saved_env = env;
|
|
1046 |
env = cpu_single_env;
|
|
1047 |
if (env->mmuregs[3]) /* Fault status register */
|
|
1048 |
env->mmuregs[3] = 1; /* overflow (not read before another fault) */
|
|
1049 |
if (is_asi)
|
|
1050 |
env->mmuregs[3] |= 1 << 16;
|
|
1051 |
if (env->psrs)
|
|
1052 |
env->mmuregs[3] |= 1 << 5;
|
|
1053 |
if (is_exec)
|
|
1054 |
env->mmuregs[3] |= 1 << 6;
|
|
1055 |
if (is_write)
|
|
1056 |
env->mmuregs[3] |= 1 << 7;
|
|
1057 |
env->mmuregs[3] |= (5 << 2) | 2;
|
|
1058 |
env->mmuregs[4] = addr; /* Fault address register */
|
|
1059 |
if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
|
|
1060 |
#ifdef DEBUG_UNASSIGNED
|
|
1061 |
printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx
|
|
1062 |
"\n", addr, env->pc);
|
|
1063 |
#endif
|
|
1064 |
raise_exception(TT_DATA_ACCESS);
|
|
1065 |
}
|
|
1066 |
env = saved_env;
|
|
1067 |
}
|
|
1068 |
#else
|
|
1069 |
void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
|
|
1070 |
int is_asi)
|
|
1071 |
{
|
|
1072 |
#ifdef DEBUG_UNASSIGNED
|
|
1073 |
CPUState *saved_env;
|
|
1074 |
|
|
1075 |
/* XXX: hack to restore env in all cases, even if not called from
|
|
1076 |
generated code */
|
|
1077 |
saved_env = env;
|
|
1078 |
env = cpu_single_env;
|
|
1079 |
printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx "\n",
|
|
1080 |
addr, env->pc);
|
|
1081 |
env = saved_env;
|
|
1082 |
#endif
|
|
1083 |
raise_exception(TT_DATA_ACCESS);
|
|
1084 |
}
|
|
1085 |
#endif
|