Revision 6c36d3fa target-sparc/op_helper.c
b/target-sparc/op_helper.c | ||
---|---|---|
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 |
Also available in: Unified diff