Revision 1a2fb1c0
b/target-sparc/exec.h | ||
---|---|---|
52 | 52 |
void cpu_lock(void); |
53 | 53 |
void cpu_unlock(void); |
54 | 54 |
void cpu_loop_exit(void); |
55 |
void helper_flush(target_ulong addr); |
|
56 |
void helper_ld_asi(int asi, int size, int sign); |
|
57 |
void helper_st_asi(int asi, int size); |
|
58 |
void helper_ldf_asi(int asi, int size, int rd); |
|
59 |
void helper_stf_asi(int asi, int size, int rd); |
|
60 |
void helper_rett(void); |
|
61 | 55 |
void helper_ldfsr(void); |
62 | 56 |
void set_cwp(int new_cwp); |
63 | 57 |
void do_fitos(void); |
... | ... | |
101 | 95 |
void do_fcmpeq_fcc2(void); |
102 | 96 |
void do_fcmpeq_fcc3(void); |
103 | 97 |
#endif |
104 |
void do_popc(); |
|
105 |
void do_wrpstate(); |
|
106 |
void do_done(); |
|
107 |
void do_retry(); |
|
108 | 98 |
#endif |
109 |
void do_ldd_kernel(target_ulong addr); |
|
110 |
void do_ldd_user(target_ulong addr); |
|
111 |
void do_ldd_raw(target_ulong addr); |
|
112 | 99 |
void do_interrupt(int intno); |
113 | 100 |
void raise_exception(int tt); |
114 | 101 |
void check_ieee_exceptions(); |
115 | 102 |
void memcpy32(target_ulong *dst, const target_ulong *src); |
116 | 103 |
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev); |
117 | 104 |
void dump_mmu(CPUState *env); |
118 |
void helper_debug(); |
|
119 |
void do_wrpsr(); |
|
120 |
void do_rdpsr(); |
|
121 | 105 |
|
122 | 106 |
/* XXX: move that to a generic header */ |
123 | 107 |
#if !defined(CONFIG_USER_ONLY) |
b/target-sparc/helper.h | ||
---|---|---|
1 |
#define TCG_HELPER_PROTO |
|
2 |
|
|
3 |
#ifndef TARGET_SPARC64 |
|
4 |
void TCG_HELPER_PROTO helper_rett(void); |
|
5 |
void TCG_HELPER_PROTO helper_wrpsr(target_ulong new_psr); |
|
6 |
target_ulong TCG_HELPER_PROTO helper_rdpsr(void); |
|
7 |
#else |
|
8 |
void TCG_HELPER_PROTO helper_wrpstate(target_ulong new_state); |
|
9 |
void TCG_HELPER_PROTO helper_done(void); |
|
10 |
void TCG_HELPER_PROTO helper_retry(void); |
|
11 |
target_ulong TCG_HELPER_PROTO helper_popc(target_ulong val); |
|
12 |
void TCG_HELPER_PROTO helper_ldf_asi(target_ulong addr, int asi, int size, |
|
13 |
int rd); |
|
14 |
void TCG_HELPER_PROTO helper_stf_asi(target_ulong addr, int asi, int size, |
|
15 |
int rd); |
|
16 |
target_ulong TCG_HELPER_PROTO |
|
17 |
helper_cas_asi(target_ulong addr, target_ulong val1, |
|
18 |
target_ulong val2, uint32_t asi); |
|
19 |
target_ulong TCG_HELPER_PROTO |
|
20 |
helper_casx_asi(target_ulong addr, target_ulong val1, |
|
21 |
target_ulong val2, uint32_t asi); |
|
22 |
#endif |
|
23 |
void TCG_HELPER_PROTO helper_trap(target_ulong nb_trap); |
|
24 |
void TCG_HELPER_PROTO helper_trapcc(target_ulong nb_trap, |
|
25 |
target_ulong do_trap); |
|
26 |
void TCG_HELPER_PROTO helper_debug(void); |
|
27 |
void TCG_HELPER_PROTO helper_flush(target_ulong addr); |
|
28 |
uint64_t TCG_HELPER_PROTO helper_pack64(target_ulong high, target_ulong low); |
|
29 |
uint64_t TCG_HELPER_PROTO helper_ld_asi(target_ulong addr, int asi, |
|
30 |
int size, int sign); |
|
31 |
void TCG_HELPER_PROTO helper_st_asi(target_ulong addr, uint64_t val, int asi, |
|
32 |
int size); |
b/target-sparc/op.c | ||
---|---|---|
19 | 19 |
*/ |
20 | 20 |
|
21 | 21 |
#include "exec.h" |
22 |
|
|
23 |
/*XXX*/ |
|
24 |
#define REGNAME g0 |
|
25 |
#define REG (env->gregs[0]) |
|
26 |
#include "op_template.h" |
|
27 |
#define REGNAME g1 |
|
28 |
#define REG (env->gregs[1]) |
|
29 |
#include "op_template.h" |
|
30 |
#define REGNAME g2 |
|
31 |
#define REG (env->gregs[2]) |
|
32 |
#include "op_template.h" |
|
33 |
#define REGNAME g3 |
|
34 |
#define REG (env->gregs[3]) |
|
35 |
#include "op_template.h" |
|
36 |
#define REGNAME g4 |
|
37 |
#define REG (env->gregs[4]) |
|
38 |
#include "op_template.h" |
|
39 |
#define REGNAME g5 |
|
40 |
#define REG (env->gregs[5]) |
|
41 |
#include "op_template.h" |
|
42 |
#define REGNAME g6 |
|
43 |
#define REG (env->gregs[6]) |
|
44 |
#include "op_template.h" |
|
45 |
#define REGNAME g7 |
|
46 |
#define REG (env->gregs[7]) |
|
47 |
#include "op_template.h" |
|
48 |
#define REGNAME i0 |
|
49 |
#define REG (REGWPTR[16]) |
|
50 |
#include "op_template.h" |
|
51 |
#define REGNAME i1 |
|
52 |
#define REG (REGWPTR[17]) |
|
53 |
#include "op_template.h" |
|
54 |
#define REGNAME i2 |
|
55 |
#define REG (REGWPTR[18]) |
|
56 |
#include "op_template.h" |
|
57 |
#define REGNAME i3 |
|
58 |
#define REG (REGWPTR[19]) |
|
59 |
#include "op_template.h" |
|
60 |
#define REGNAME i4 |
|
61 |
#define REG (REGWPTR[20]) |
|
62 |
#include "op_template.h" |
|
63 |
#define REGNAME i5 |
|
64 |
#define REG (REGWPTR[21]) |
|
65 |
#include "op_template.h" |
|
66 |
#define REGNAME i6 |
|
67 |
#define REG (REGWPTR[22]) |
|
68 |
#include "op_template.h" |
|
69 |
#define REGNAME i7 |
|
70 |
#define REG (REGWPTR[23]) |
|
71 |
#include "op_template.h" |
|
72 |
#define REGNAME l0 |
|
73 |
#define REG (REGWPTR[8]) |
|
74 |
#include "op_template.h" |
|
75 |
#define REGNAME l1 |
|
76 |
#define REG (REGWPTR[9]) |
|
77 |
#include "op_template.h" |
|
78 |
#define REGNAME l2 |
|
79 |
#define REG (REGWPTR[10]) |
|
80 |
#include "op_template.h" |
|
81 |
#define REGNAME l3 |
|
82 |
#define REG (REGWPTR[11]) |
|
83 |
#include "op_template.h" |
|
84 |
#define REGNAME l4 |
|
85 |
#define REG (REGWPTR[12]) |
|
86 |
#include "op_template.h" |
|
87 |
#define REGNAME l5 |
|
88 |
#define REG (REGWPTR[13]) |
|
89 |
#include "op_template.h" |
|
90 |
#define REGNAME l6 |
|
91 |
#define REG (REGWPTR[14]) |
|
92 |
#include "op_template.h" |
|
93 |
#define REGNAME l7 |
|
94 |
#define REG (REGWPTR[15]) |
|
95 |
#include "op_template.h" |
|
96 |
#define REGNAME o0 |
|
97 |
#define REG (REGWPTR[0]) |
|
98 |
#include "op_template.h" |
|
99 |
#define REGNAME o1 |
|
100 |
#define REG (REGWPTR[1]) |
|
101 |
#include "op_template.h" |
|
102 |
#define REGNAME o2 |
|
103 |
#define REG (REGWPTR[2]) |
|
104 |
#include "op_template.h" |
|
105 |
#define REGNAME o3 |
|
106 |
#define REG (REGWPTR[3]) |
|
107 |
#include "op_template.h" |
|
108 |
#define REGNAME o4 |
|
109 |
#define REG (REGWPTR[4]) |
|
110 |
#include "op_template.h" |
|
111 |
#define REGNAME o5 |
|
112 |
#define REG (REGWPTR[5]) |
|
113 |
#include "op_template.h" |
|
114 |
#define REGNAME o6 |
|
115 |
#define REG (REGWPTR[6]) |
|
116 |
#include "op_template.h" |
|
117 |
#define REGNAME o7 |
|
118 |
#define REG (REGWPTR[7]) |
|
119 |
#include "op_template.h" |
|
22 |
#include "helper.h" |
|
120 | 23 |
|
121 | 24 |
#define REGNAME f0 |
122 | 25 |
#define REG (env->fpr[0]) |
... | ... | |
267 | 170 |
#endif |
268 | 171 |
|
269 | 172 |
#ifdef TARGET_SPARC64 |
270 |
#ifdef WORDS_BIGENDIAN |
|
271 |
typedef union UREG64 { |
|
272 |
struct { uint16_t v3, v2, v1, v0; } w; |
|
273 |
struct { uint32_t v1, v0; } l; |
|
274 |
uint64_t q; |
|
275 |
} UREG64; |
|
276 |
#else |
|
277 |
typedef union UREG64 { |
|
278 |
struct { uint16_t v0, v1, v2, v3; } w; |
|
279 |
struct { uint32_t v0, v1; } l; |
|
280 |
uint64_t q; |
|
281 |
} UREG64; |
|
282 |
#endif |
|
283 |
|
|
284 |
#define PARAMQ1 \ |
|
285 |
({\ |
|
286 |
UREG64 __p;\ |
|
287 |
__p.l.v1 = PARAM1;\ |
|
288 |
__p.l.v0 = PARAM2;\ |
|
289 |
__p.q;\ |
|
290 |
}) |
|
291 |
|
|
292 |
void OPPROTO op_movq_T0_im64(void) |
|
293 |
{ |
|
294 |
T0 = PARAMQ1; |
|
295 |
} |
|
296 |
|
|
297 |
void OPPROTO op_movq_T1_im64(void) |
|
298 |
{ |
|
299 |
T1 = PARAMQ1; |
|
300 |
} |
|
301 |
|
|
302 | 173 |
#define XFLAG_SET(x) ((env->xcc&x)?1:0) |
303 |
|
|
304 |
#else |
|
305 |
#define EIP (env->pc) |
|
306 | 174 |
#endif |
307 | 175 |
|
308 | 176 |
#define FLAG_SET(x) ((env->psr&x)?1:0) |
309 | 177 |
|
310 |
void OPPROTO op_movl_T0_0(void) |
|
311 |
{ |
|
312 |
T0 = 0; |
|
313 |
} |
|
314 |
|
|
315 |
void OPPROTO op_movl_T0_im(void) |
|
316 |
{ |
|
317 |
T0 = (uint32_t)PARAM1; |
|
318 |
} |
|
319 |
|
|
320 |
void OPPROTO op_movl_T1_im(void) |
|
321 |
{ |
|
322 |
T1 = (uint32_t)PARAM1; |
|
323 |
} |
|
324 |
|
|
325 |
void OPPROTO op_movl_T2_im(void) |
|
326 |
{ |
|
327 |
T2 = (uint32_t)PARAM1; |
|
328 |
} |
|
329 |
|
|
330 |
void OPPROTO op_movl_T0_sim(void) |
|
331 |
{ |
|
332 |
T0 = (int32_t)PARAM1; |
|
333 |
} |
|
334 |
|
|
335 |
void OPPROTO op_movl_T1_sim(void) |
|
336 |
{ |
|
337 |
T1 = (int32_t)PARAM1; |
|
338 |
} |
|
339 |
|
|
340 |
void OPPROTO op_movl_T2_sim(void) |
|
341 |
{ |
|
342 |
T2 = (int32_t)PARAM1; |
|
343 |
} |
|
344 |
|
|
345 |
void OPPROTO op_movl_T0_env(void) |
|
346 |
{ |
|
347 |
T0 = *(uint32_t *)((char *)env + PARAM1); |
|
348 |
} |
|
349 |
|
|
350 |
void OPPROTO op_movl_env_T0(void) |
|
351 |
{ |
|
352 |
*(uint32_t *)((char *)env + PARAM1) = T0; |
|
353 |
} |
|
354 |
|
|
355 |
void OPPROTO op_movtl_T0_env(void) |
|
356 |
{ |
|
357 |
T0 = *(target_ulong *)((char *)env + PARAM1); |
|
358 |
} |
|
359 |
|
|
360 |
void OPPROTO op_movtl_env_T0(void) |
|
361 |
{ |
|
362 |
*(target_ulong *)((char *)env + PARAM1) = T0; |
|
363 |
} |
|
364 |
|
|
365 |
void OPPROTO op_add_T1_T0(void) |
|
366 |
{ |
|
367 |
T0 += T1; |
|
368 |
} |
|
369 |
|
|
370 | 178 |
void OPPROTO op_add_T1_T0_cc(void) |
371 | 179 |
{ |
372 | 180 |
target_ulong src1; |
... | ... | |
565 | 373 |
FORCE_RET(); |
566 | 374 |
} |
567 | 375 |
|
568 |
void OPPROTO op_sub_T1_T0(void) |
|
569 |
{ |
|
570 |
T0 -= T1; |
|
571 |
} |
|
572 |
|
|
573 | 376 |
void OPPROTO op_sub_T1_T0_cc(void) |
574 | 377 |
{ |
575 | 378 |
target_ulong src1; |
... | ... | |
765 | 568 |
FORCE_RET(); |
766 | 569 |
} |
767 | 570 |
|
768 |
void OPPROTO op_and_T1_T0(void) |
|
769 |
{ |
|
770 |
T0 &= T1; |
|
771 |
} |
|
772 |
|
|
773 |
void OPPROTO op_or_T1_T0(void) |
|
774 |
{ |
|
775 |
T0 |= T1; |
|
776 |
} |
|
777 |
|
|
778 |
void OPPROTO op_xor_T1_T0(void) |
|
779 |
{ |
|
780 |
T0 ^= T1; |
|
781 |
} |
|
782 |
|
|
783 | 571 |
void OPPROTO op_andn_T1_T0(void) |
784 | 572 |
{ |
785 | 573 |
T0 &= ~T1; |
... | ... | |
921 | 709 |
} |
922 | 710 |
|
923 | 711 |
#ifdef TARGET_SPARC64 |
924 |
void OPPROTO op_mulx_T1_T0(void) |
|
925 |
{ |
|
926 |
T0 *= T1; |
|
927 |
FORCE_RET(); |
|
928 |
} |
|
929 |
|
|
930 | 712 |
void OPPROTO op_udivx_T1_T0(void) |
931 | 713 |
{ |
932 | 714 |
if (T1 == 0) { |
... | ... | |
972 | 754 |
FORCE_RET(); |
973 | 755 |
} |
974 | 756 |
|
975 |
void OPPROTO op_sll(void) |
|
976 |
{ |
|
977 |
T0 <<= (T1 & 0x1f); |
|
978 |
} |
|
979 |
|
|
980 |
#ifdef TARGET_SPARC64 |
|
981 |
void OPPROTO op_sllx(void) |
|
982 |
{ |
|
983 |
T0 <<= (T1 & 0x3f); |
|
984 |
} |
|
985 |
|
|
986 |
void OPPROTO op_srl(void) |
|
987 |
{ |
|
988 |
T0 = (T0 & 0xffffffff) >> (T1 & 0x1f); |
|
989 |
} |
|
990 |
|
|
991 |
void OPPROTO op_srlx(void) |
|
992 |
{ |
|
993 |
T0 >>= (T1 & 0x3f); |
|
994 |
} |
|
995 |
|
|
996 |
void OPPROTO op_sra(void) |
|
997 |
{ |
|
998 |
T0 = ((int32_t) (T0 & 0xffffffff)) >> (T1 & 0x1f); |
|
999 |
} |
|
1000 |
|
|
1001 |
void OPPROTO op_srax(void) |
|
1002 |
{ |
|
1003 |
T0 = ((int64_t) T0) >> (T1 & 0x3f); |
|
1004 |
} |
|
1005 |
#else |
|
1006 |
void OPPROTO op_srl(void) |
|
1007 |
{ |
|
1008 |
T0 >>= (T1 & 0x1f); |
|
1009 |
} |
|
1010 |
|
|
1011 |
void OPPROTO op_sra(void) |
|
1012 |
{ |
|
1013 |
T0 = ((int32_t) T0) >> (T1 & 0x1f); |
|
1014 |
} |
|
1015 |
#endif |
|
1016 |
|
|
1017 | 757 |
/* Load and store */ |
1018 | 758 |
#define MEMSUFFIX _raw |
1019 | 759 |
#include "op_mem.h" |
... | ... | |
1042 | 782 |
} |
1043 | 783 |
|
1044 | 784 |
#ifndef TARGET_SPARC64 |
1045 |
void OPPROTO op_rdpsr(void) |
|
1046 |
{ |
|
1047 |
do_rdpsr(); |
|
1048 |
} |
|
1049 |
|
|
1050 |
void OPPROTO op_wrpsr(void) |
|
1051 |
{ |
|
1052 |
do_wrpsr(); |
|
1053 |
FORCE_RET(); |
|
1054 |
} |
|
1055 |
|
|
1056 |
void OPPROTO op_wrwim(void) |
|
1057 |
{ |
|
1058 |
#if NWINDOWS == 32 |
|
1059 |
env->wim = T0; |
|
1060 |
#else |
|
1061 |
env->wim = T0 & ((1 << NWINDOWS) - 1); |
|
1062 |
#endif |
|
1063 |
} |
|
1064 |
|
|
1065 |
void OPPROTO op_rett(void) |
|
1066 |
{ |
|
1067 |
helper_rett(); |
|
1068 |
FORCE_RET(); |
|
1069 |
} |
|
1070 |
|
|
1071 | 785 |
/* XXX: use another pointer for %iN registers to avoid slow wrapping |
1072 | 786 |
handling ? */ |
1073 | 787 |
void OPPROTO op_save(void) |
... | ... | |
1178 | 892 |
env->tt[env->tl] = T0; |
1179 | 893 |
} |
1180 | 894 |
|
1181 |
void OPPROTO op_rdpstate(void) |
|
1182 |
{ |
|
1183 |
T0 = env->pstate; |
|
1184 |
} |
|
1185 |
|
|
1186 |
void OPPROTO op_wrpstate(void) |
|
1187 |
{ |
|
1188 |
do_wrpstate(); |
|
1189 |
} |
|
1190 |
|
|
1191 | 895 |
// CWP handling is reversed in V9, but we still use the V8 register |
1192 | 896 |
// order. |
1193 | 897 |
void OPPROTO op_rdcwp(void) |
... | ... | |
1247 | 951 |
FORCE_RET(); |
1248 | 952 |
} |
1249 | 953 |
|
1250 |
void OPPROTO op_trap_T0(void) |
|
1251 |
{ |
|
1252 |
env->exception_index = TT_TRAP + (T0 & 0x7f); |
|
1253 |
cpu_loop_exit(); |
|
1254 |
FORCE_RET(); |
|
1255 |
} |
|
1256 |
|
|
1257 |
void OPPROTO op_trapcc_T0(void) |
|
1258 |
{ |
|
1259 |
if (T2) { |
|
1260 |
env->exception_index = TT_TRAP + (T0 & 0x7f); |
|
1261 |
cpu_loop_exit(); |
|
1262 |
} |
|
1263 |
FORCE_RET(); |
|
1264 |
} |
|
1265 |
|
|
1266 | 954 |
void OPPROTO op_fpexception_im(void) |
1267 | 955 |
{ |
1268 | 956 |
env->exception_index = TT_FP_EXCP; |
... | ... | |
1272 | 960 |
FORCE_RET(); |
1273 | 961 |
} |
1274 | 962 |
|
1275 |
void OPPROTO op_debug(void) |
|
1276 |
{ |
|
1277 |
helper_debug(); |
|
1278 |
} |
|
1279 |
|
|
1280 | 963 |
void OPPROTO op_eval_ba(void) |
1281 | 964 |
{ |
1282 | 965 |
T2 = 1; |
... | ... | |
1499 | 1182 |
{ |
1500 | 1183 |
T2 = ((int64_t)T0 >= 0); |
1501 | 1184 |
} |
1502 |
|
|
1503 |
void OPPROTO op_jmp_im64(void) |
|
1504 |
{ |
|
1505 |
env->pc = PARAMQ1; |
|
1506 |
} |
|
1507 |
|
|
1508 |
void OPPROTO op_movq_npc_im64(void) |
|
1509 |
{ |
|
1510 |
env->npc = PARAMQ1; |
|
1511 |
} |
|
1512 | 1185 |
#endif |
1513 | 1186 |
|
1514 |
void OPPROTO op_jmp_im(void) |
|
1515 |
{ |
|
1516 |
env->pc = (uint32_t)PARAM1; |
|
1517 |
} |
|
1518 |
|
|
1519 |
void OPPROTO op_movl_npc_im(void) |
|
1520 |
{ |
|
1521 |
env->npc = (uint32_t)PARAM1; |
|
1522 |
} |
|
1523 |
|
|
1524 |
void OPPROTO op_movl_npc_T0(void) |
|
1525 |
{ |
|
1526 |
env->npc = T0; |
|
1527 |
} |
|
1528 |
|
|
1529 | 1187 |
void OPPROTO op_mov_pc_npc(void) |
1530 | 1188 |
{ |
1531 | 1189 |
env->pc = env->npc; |
... | ... | |
1556 | 1214 |
FORCE_RET(); |
1557 | 1215 |
} |
1558 | 1216 |
|
1559 |
void OPPROTO op_flush_T0(void) |
|
1560 |
{ |
|
1561 |
helper_flush(T0); |
|
1562 |
} |
|
1563 |
|
|
1564 | 1217 |
void OPPROTO op_clear_ieee_excp_and_FTT(void) |
1565 | 1218 |
{ |
1566 | 1219 |
env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);; |
... | ... | |
1993 | 1646 |
env->otherwin--; |
1994 | 1647 |
FORCE_RET(); |
1995 | 1648 |
} |
1996 |
|
|
1997 |
void OPPROTO op_popc(void) |
|
1998 |
{ |
|
1999 |
do_popc(); |
|
2000 |
} |
|
2001 |
|
|
2002 |
void OPPROTO op_done(void) |
|
2003 |
{ |
|
2004 |
do_done(); |
|
2005 |
} |
|
2006 |
|
|
2007 |
void OPPROTO op_retry(void) |
|
2008 |
{ |
|
2009 |
do_retry(); |
|
2010 |
} |
|
2011 |
|
|
2012 |
void OPPROTO op_sir(void) |
|
2013 |
{ |
|
2014 |
T0 = 0; // XXX |
|
2015 |
} |
|
2016 |
|
|
2017 |
void OPPROTO op_ld_asi_reg() |
|
2018 |
{ |
|
2019 |
T0 += PARAM1; |
|
2020 |
helper_ld_asi(env->asi, PARAM2, PARAM3); |
|
2021 |
} |
|
2022 |
|
|
2023 |
void OPPROTO op_st_asi_reg() |
|
2024 |
{ |
|
2025 |
T0 += PARAM1; |
|
2026 |
helper_st_asi(env->asi, PARAM2); |
|
2027 |
} |
|
2028 |
|
|
2029 |
void OPPROTO op_ldf_asi_reg() |
|
2030 |
{ |
|
2031 |
T0 += PARAM1; |
|
2032 |
helper_ldf_asi(env->asi, PARAM2, PARAM3); |
|
2033 |
} |
|
2034 |
|
|
2035 |
void OPPROTO op_stf_asi_reg() |
|
2036 |
{ |
|
2037 |
T0 += PARAM1; |
|
2038 |
helper_stf_asi(env->asi, PARAM2, PARAM3); |
|
2039 |
} |
|
2040 |
|
|
2041 |
void OPPROTO op_ldf_asi() |
|
2042 |
{ |
|
2043 |
helper_ldf_asi(PARAM1, PARAM2, PARAM3); |
|
2044 |
} |
|
2045 |
|
|
2046 |
void OPPROTO op_stf_asi() |
|
2047 |
{ |
|
2048 |
helper_stf_asi(PARAM1, PARAM2, PARAM3); |
|
2049 |
} |
|
2050 |
|
|
2051 |
void OPPROTO op_ldstub_asi_reg() /* XXX: should be atomically */ |
|
2052 |
{ |
|
2053 |
target_ulong tmp; |
|
2054 |
|
|
2055 |
T0 += PARAM1; |
|
2056 |
helper_ld_asi(env->asi, 1, 0); |
|
2057 |
tmp = T1; |
|
2058 |
T1 = 0xff; |
|
2059 |
helper_st_asi(env->asi, 1); |
|
2060 |
T1 = tmp; |
|
2061 |
} |
|
2062 |
|
|
2063 |
void OPPROTO op_swap_asi_reg() /* XXX: should be atomically */ |
|
2064 |
{ |
|
2065 |
target_ulong tmp1, tmp2; |
|
2066 |
|
|
2067 |
T0 += PARAM1; |
|
2068 |
tmp1 = T1; |
|
2069 |
helper_ld_asi(env->asi, 4, 0); |
|
2070 |
tmp2 = T1; |
|
2071 |
T1 = tmp1; |
|
2072 |
helper_st_asi(env->asi, 4); |
|
2073 |
T1 = tmp2; |
|
2074 |
} |
|
2075 |
|
|
2076 |
void OPPROTO op_ldda_asi() |
|
2077 |
{ |
|
2078 |
helper_ld_asi(PARAM1, 8, 0); |
|
2079 |
T0 = T1 & 0xffffffffUL; |
|
2080 |
T1 >>= 32; |
|
2081 |
} |
|
2082 |
|
|
2083 |
void OPPROTO op_ldda_asi_reg() |
|
2084 |
{ |
|
2085 |
T0 += PARAM1; |
|
2086 |
helper_ld_asi(env->asi, 8, 0); |
|
2087 |
T0 = T1 & 0xffffffffUL; |
|
2088 |
T1 >>= 32; |
|
2089 |
} |
|
2090 |
|
|
2091 |
void OPPROTO op_stda_asi() |
|
2092 |
{ |
|
2093 |
T1 <<= 32; |
|
2094 |
T1 += T2 & 0xffffffffUL; |
|
2095 |
helper_st_asi(PARAM1, 8); |
|
2096 |
} |
|
2097 |
|
|
2098 |
void OPPROTO op_stda_asi_reg() |
|
2099 |
{ |
|
2100 |
T0 += PARAM1; |
|
2101 |
T1 <<= 32; |
|
2102 |
T1 += T2 & 0xffffffffUL; |
|
2103 |
helper_st_asi(env->asi, 8); |
|
2104 |
} |
|
2105 |
|
|
2106 |
void OPPROTO op_cas_asi() /* XXX: should be atomically */ |
|
2107 |
{ |
|
2108 |
target_ulong tmp; |
|
2109 |
|
|
2110 |
tmp = T1 & 0xffffffffUL; |
|
2111 |
helper_ld_asi(PARAM1, 4, 0); |
|
2112 |
if (tmp == T1) { |
|
2113 |
tmp = T1; |
|
2114 |
T1 = T2 & 0xffffffffUL; |
|
2115 |
helper_st_asi(PARAM1, 4); |
|
2116 |
T1 = tmp; |
|
2117 |
} |
|
2118 |
T1 &= 0xffffffffUL; |
|
2119 |
} |
|
2120 |
|
|
2121 |
void OPPROTO op_cas_asi_reg() /* XXX: should be atomically */ |
|
2122 |
{ |
|
2123 |
target_ulong tmp; |
|
2124 |
|
|
2125 |
T0 += PARAM1; |
|
2126 |
tmp = T1 & 0xffffffffUL; |
|
2127 |
helper_ld_asi(env->asi, 4, 0); |
|
2128 |
if (tmp == T1) { |
|
2129 |
tmp = T1; |
|
2130 |
T1 = T2 & 0xffffffffUL; |
|
2131 |
helper_st_asi(env->asi, 4); |
|
2132 |
T1 = tmp; |
|
2133 |
} |
|
2134 |
T1 &= 0xffffffffUL; |
|
2135 |
} |
|
2136 |
|
|
2137 |
void OPPROTO op_casx_asi() /* XXX: should be atomically */ |
|
2138 |
{ |
|
2139 |
target_ulong tmp; |
|
2140 |
|
|
2141 |
tmp = T1; |
|
2142 |
helper_ld_asi(PARAM1, 8, 0); |
|
2143 |
if (tmp == T1) { |
|
2144 |
tmp = T1; |
|
2145 |
T1 = T2; |
|
2146 |
helper_st_asi(PARAM1, 8); |
|
2147 |
T1 = tmp; |
|
2148 |
} |
|
2149 |
} |
|
2150 |
|
|
2151 |
void OPPROTO op_casx_asi_reg() /* XXX: should be atomically */ |
|
2152 |
{ |
|
2153 |
target_ulong tmp; |
|
2154 |
|
|
2155 |
T0 += PARAM1; |
|
2156 |
tmp = T1; |
|
2157 |
helper_ld_asi(env->asi, 8, 0); |
|
2158 |
if (tmp == T1) { |
|
2159 |
tmp = T1; |
|
2160 |
T1 = T2; |
|
2161 |
helper_st_asi(env->asi, 8); |
|
2162 |
T1 = tmp; |
|
2163 |
} |
|
2164 |
} |
|
2165 |
#endif |
|
2166 |
|
|
2167 |
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) |
|
2168 |
void OPPROTO op_ld_asi() |
|
2169 |
{ |
|
2170 |
helper_ld_asi(PARAM1, PARAM2, PARAM3); |
|
2171 |
} |
|
2172 |
|
|
2173 |
void OPPROTO op_st_asi() |
|
2174 |
{ |
|
2175 |
helper_st_asi(PARAM1, PARAM2); |
|
2176 |
} |
|
2177 |
|
|
2178 |
void OPPROTO op_ldstub_asi() /* XXX: should be atomically */ |
|
2179 |
{ |
|
2180 |
target_ulong tmp; |
|
2181 |
|
|
2182 |
helper_ld_asi(PARAM1, 1, 0); |
|
2183 |
tmp = T1; |
|
2184 |
T1 = 0xff; |
|
2185 |
helper_st_asi(PARAM1, 1); |
|
2186 |
T1 = tmp; |
|
2187 |
} |
|
2188 |
|
|
2189 |
void OPPROTO op_swap_asi() /* XXX: should be atomically */ |
|
2190 |
{ |
|
2191 |
target_ulong tmp1, tmp2; |
|
2192 |
|
|
2193 |
tmp1 = T1; |
|
2194 |
helper_ld_asi(PARAM1, 4, 0); |
|
2195 |
tmp2 = T1; |
|
2196 |
T1 = tmp1; |
|
2197 |
helper_st_asi(PARAM1, 4); |
|
2198 |
T1 = tmp2; |
|
2199 |
} |
|
2200 | 1649 |
#endif |
2201 | 1650 |
|
2202 | 1651 |
#ifdef TARGET_SPARC64 |
b/target-sparc/op_helper.c | ||
---|---|---|
1 | 1 |
#include "exec.h" |
2 | 2 |
#include "host-utils.h" |
3 |
#include "helper.h" |
|
3 | 4 |
|
4 | 5 |
//#define DEBUG_PCALL |
5 | 6 |
//#define DEBUG_MMU |
... | ... | |
35 | 36 |
cpu_loop_exit(); |
36 | 37 |
} |
37 | 38 |
|
38 |
void check_ieee_exceptions()
|
|
39 |
void helper_trap(target_ulong nb_trap)
|
|
39 | 40 |
{ |
40 |
T0 = get_float_exception_flags(&env->fp_status); |
|
41 |
if (T0) |
|
42 |
{ |
|
41 |
env->exception_index = TT_TRAP + (nb_trap & 0x7f); |
|
42 |
cpu_loop_exit(); |
|
43 |
} |
|
44 |
|
|
45 |
void helper_trapcc(target_ulong nb_trap, target_ulong do_trap) |
|
46 |
{ |
|
47 |
if (do_trap) { |
|
48 |
env->exception_index = TT_TRAP + (nb_trap & 0x7f); |
|
49 |
cpu_loop_exit(); |
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
void check_ieee_exceptions(void) |
|
54 |
{ |
|
55 |
target_ulong status; |
|
56 |
|
|
57 |
status = get_float_exception_flags(&env->fp_status); |
|
58 |
if (status) { |
|
43 | 59 |
/* Copy IEEE 754 flags into FSR */ |
44 |
if (T0 & float_flag_invalid)
|
|
60 |
if (status & float_flag_invalid)
|
|
45 | 61 |
env->fsr |= FSR_NVC; |
46 |
if (T0 & float_flag_overflow)
|
|
62 |
if (status & float_flag_overflow)
|
|
47 | 63 |
env->fsr |= FSR_OFC; |
48 |
if (T0 & float_flag_underflow)
|
|
64 |
if (status & float_flag_underflow)
|
|
49 | 65 |
env->fsr |= FSR_UFC; |
50 |
if (T0 & float_flag_divbyzero)
|
|
66 |
if (status & float_flag_divbyzero)
|
|
51 | 67 |
env->fsr |= FSR_DZC; |
52 |
if (T0 & float_flag_inexact)
|
|
68 |
if (status & float_flag_inexact)
|
|
53 | 69 |
env->fsr |= FSR_NXC; |
54 | 70 |
|
55 |
if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) |
|
56 |
{ |
|
71 |
if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) { |
|
57 | 72 |
/* Unmasked exception, generate a trap */ |
58 | 73 |
env->fsr |= FSR_FTT_IEEE_EXCP; |
59 | 74 |
raise_exception(TT_FP_EXCP); |
60 |
} |
|
61 |
else |
|
62 |
{ |
|
75 |
} else { |
|
63 | 76 |
/* Accumulate exceptions */ |
64 | 77 |
env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5; |
65 | 78 |
} |
66 |
}
|
|
79 |
} |
|
67 | 80 |
} |
68 | 81 |
|
69 | 82 |
#ifdef USE_INT_TO_FLOAT_HELPERS |
... | ... | |
157 | 170 |
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ |
158 | 171 |
void glue(do_, name) (void) \ |
159 | 172 |
{ \ |
173 |
target_ulong new_fsr; \ |
|
174 |
\ |
|
160 | 175 |
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ |
161 | 176 |
switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ |
162 | 177 |
case float_relation_unordered: \ |
163 |
T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
|
|
178 |
new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
|
|
164 | 179 |
if ((env->fsr & FSR_NVM) || TRAP) { \ |
165 |
env->fsr |= T0; \
|
|
180 |
env->fsr |= new_fsr; \
|
|
166 | 181 |
env->fsr |= FSR_NVC; \ |
167 | 182 |
env->fsr |= FSR_FTT_IEEE_EXCP; \ |
168 | 183 |
raise_exception(TT_FP_EXCP); \ |
... | ... | |
171 | 186 |
} \ |
172 | 187 |
break; \ |
173 | 188 |
case float_relation_less: \ |
174 |
T0 = FSR_FCC0 << FS; \
|
|
189 |
new_fsr = FSR_FCC0 << FS; \
|
|
175 | 190 |
break; \ |
176 | 191 |
case float_relation_greater: \ |
177 |
T0 = FSR_FCC1 << FS; \
|
|
192 |
new_fsr = FSR_FCC1 << FS; \
|
|
178 | 193 |
break; \ |
179 | 194 |
default: \ |
180 |
T0 = 0; \
|
|
195 |
new_fsr = 0; \
|
|
181 | 196 |
break; \ |
182 | 197 |
} \ |
183 |
env->fsr |= T0; \
|
|
198 |
env->fsr |= new_fsr; \
|
|
184 | 199 |
} |
185 | 200 |
|
186 | 201 |
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0); |
... | ... | |
222 | 237 |
#endif |
223 | 238 |
#endif |
224 | 239 |
|
225 |
#ifndef TARGET_SPARC64 |
|
226 |
#ifndef CONFIG_USER_ONLY |
|
227 |
|
|
228 |
#ifdef DEBUG_MXCC |
|
240 |
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC) |
|
229 | 241 |
static void dump_mxcc(CPUState *env) |
230 | 242 |
{ |
231 | 243 |
printf("mxccdata: %016llx %016llx %016llx %016llx\n", |
... | ... | |
237 | 249 |
} |
238 | 250 |
#endif |
239 | 251 |
|
240 |
#ifdef DEBUG_ASI |
|
241 |
static void dump_asi(const char * txt, uint32_t addr, int asi, int size, |
|
242 |
uint32_t r1, uint32_t r2) |
|
252 |
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \ |
|
253 |
&& defined(DEBUG_ASI) |
|
254 |
static void dump_asi(const char *txt, target_ulong addr, int asi, int size, |
|
255 |
uint64_t r1) |
|
243 | 256 |
{ |
244 | 257 |
switch (size) |
245 | 258 |
{ |
246 | 259 |
case 1: |
247 |
DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff); |
|
260 |
DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt, |
|
261 |
addr, asi, r1 & 0xff); |
|
248 | 262 |
break; |
249 | 263 |
case 2: |
250 |
DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff); |
|
264 |
DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt, |
|
265 |
addr, asi, r1 & 0xffff); |
|
251 | 266 |
break; |
252 | 267 |
case 4: |
253 |
DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1); |
|
268 |
DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt, |
|
269 |
addr, asi, r1 & 0xffffffff); |
|
254 | 270 |
break; |
255 | 271 |
case 8: |
256 |
DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi,
|
|
257 |
r2 | ((uint64_t)r1 << 32));
|
|
272 |
DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
|
|
273 |
addr, asi, r1);
|
|
258 | 274 |
break; |
259 | 275 |
} |
260 | 276 |
} |
261 | 277 |
#endif |
262 | 278 |
|
263 |
void helper_ld_asi(int asi, int size, int sign) |
|
279 |
#ifndef TARGET_SPARC64 |
|
280 |
#ifndef CONFIG_USER_ONLY |
|
281 |
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
|
264 | 282 |
{ |
265 |
uint32_t ret = 0; |
|
266 |
uint64_t tmp; |
|
283 |
uint64_t ret = 0; |
|
267 | 284 |
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI) |
268 |
uint32_t last_T0 = T0;
|
|
285 |
uint32_t last_addr = addr;
|
|
269 | 286 |
#endif |
270 | 287 |
|
271 | 288 |
switch (asi) { |
272 | 289 |
case 2: /* SuperSparc MXCC registers */ |
273 |
switch (T0) {
|
|
290 |
switch (addr) {
|
|
274 | 291 |
case 0x01c00a00: /* MXCC control register */ |
275 |
if (size == 8) { |
|
276 |
ret = env->mxccregs[3] >> 32; |
|
277 |
T0 = env->mxccregs[3]; |
|
278 |
} else |
|
279 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); |
|
292 |
if (size == 8) |
|
293 |
ret = env->mxccregs[3]; |
|
294 |
else |
|
295 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); |
|
280 | 296 |
break; |
281 | 297 |
case 0x01c00a04: /* MXCC control register */ |
282 | 298 |
if (size == 4) |
283 | 299 |
ret = env->mxccregs[3]; |
284 | 300 |
else |
285 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
301 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
286 | 302 |
break; |
287 | 303 |
case 0x01c00c00: /* Module reset register */ |
288 | 304 |
if (size == 8) { |
289 |
ret = env->mxccregs[5] >> 32; |
|
290 |
T0 = env->mxccregs[5]; |
|
305 |
ret = env->mxccregs[5]; |
|
291 | 306 |
// should we do something here? |
292 | 307 |
} else |
293 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
308 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
294 | 309 |
break; |
295 | 310 |
case 0x01c00f00: /* MBus port address register */ |
296 |
if (size == 8) { |
|
297 |
ret = env->mxccregs[7] >> 32; |
|
298 |
T0 = env->mxccregs[7]; |
|
299 |
} else |
|
300 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); |
|
311 |
if (size == 8) |
|
312 |
ret = env->mxccregs[7]; |
|
313 |
else |
|
314 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size); |
|
301 | 315 |
break; |
302 | 316 |
default: |
303 |
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
|
|
317 |
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
|
|
304 | 318 |
break; |
305 | 319 |
} |
306 |
DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
|
|
307 |
"T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
|
|
320 |
DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
|
|
321 |
"addr = %08x\n", asi, size, sign, last_addr, ret, addr);
|
|
308 | 322 |
#ifdef DEBUG_MXCC |
309 | 323 |
dump_mxcc(env); |
310 | 324 |
#endif |
... | ... | |
313 | 327 |
{ |
314 | 328 |
int mmulev; |
315 | 329 |
|
316 |
mmulev = (T0 >> 8) & 15;
|
|
330 |
mmulev = (addr >> 8) & 15;
|
|
317 | 331 |
if (mmulev > 4) |
318 | 332 |
ret = 0; |
319 |
else { |
|
320 |
ret = mmu_probe(env, T0, mmulev); |
|
321 |
//bswap32s(&ret); |
|
322 |
} |
|
323 |
DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); |
|
333 |
else |
|
334 |
ret = mmu_probe(env, addr, mmulev); |
|
335 |
DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n", |
|
336 |
addr, mmulev, ret); |
|
324 | 337 |
} |
325 | 338 |
break; |
326 | 339 |
case 4: /* read MMU regs */ |
327 | 340 |
{ |
328 |
int reg = (T0 >> 8) & 0x1f;
|
|
341 |
int reg = (addr >> 8) & 0x1f;
|
|
329 | 342 |
|
330 | 343 |
ret = env->mmuregs[reg]; |
331 | 344 |
if (reg == 3) /* Fault status cleared on read */ |
... | ... | |
334 | 347 |
ret = env->mmuregs[3]; |
335 | 348 |
else if (reg == 0x14) /* Fault address read */ |
336 | 349 |
ret = env->mmuregs[4]; |
337 |
DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
|
|
350 |
DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
|
|
338 | 351 |
} |
339 | 352 |
break; |
340 | 353 |
case 5: // Turbosparc ITLB Diagnostic |
... | ... | |
344 | 357 |
case 9: /* Supervisor code access */ |
345 | 358 |
switch(size) { |
346 | 359 |
case 1: |
347 |
ret = ldub_code(T0);
|
|
360 |
ret = ldub_code(addr);
|
|
348 | 361 |
break; |
349 | 362 |
case 2: |
350 |
ret = lduw_code(T0 & ~1);
|
|
363 |
ret = lduw_code(addr & ~1);
|
|
351 | 364 |
break; |
352 | 365 |
default: |
353 | 366 |
case 4: |
354 |
ret = ldl_code(T0 & ~3);
|
|
367 |
ret = ldl_code(addr & ~3);
|
|
355 | 368 |
break; |
356 | 369 |
case 8: |
357 |
tmp = ldq_code(T0 & ~7); |
|
358 |
ret = tmp >> 32; |
|
359 |
T0 = tmp; |
|
370 |
ret = ldq_code(addr & ~7); |
|
360 | 371 |
break; |
361 | 372 |
} |
362 | 373 |
break; |
363 | 374 |
case 0xa: /* User data access */ |
364 | 375 |
switch(size) { |
365 | 376 |
case 1: |
366 |
ret = ldub_user(T0);
|
|
377 |
ret = ldub_user(addr);
|
|
367 | 378 |
break; |
368 | 379 |
case 2: |
369 |
ret = lduw_user(T0 & ~1);
|
|
380 |
ret = lduw_user(addr & ~1);
|
|
370 | 381 |
break; |
371 | 382 |
default: |
372 | 383 |
case 4: |
373 |
ret = ldl_user(T0 & ~3);
|
|
384 |
ret = ldl_user(addr & ~3);
|
|
374 | 385 |
break; |
375 | 386 |
case 8: |
376 |
tmp = ldq_user(T0 & ~7); |
|
377 |
ret = tmp >> 32; |
|
378 |
T0 = tmp; |
|
387 |
ret = ldq_user(addr & ~7); |
|
379 | 388 |
break; |
380 | 389 |
} |
381 | 390 |
break; |
382 | 391 |
case 0xb: /* Supervisor data access */ |
383 | 392 |
switch(size) { |
384 | 393 |
case 1: |
385 |
ret = ldub_kernel(T0);
|
|
394 |
ret = ldub_kernel(addr);
|
|
386 | 395 |
break; |
387 | 396 |
case 2: |
388 |
ret = lduw_kernel(T0 & ~1);
|
|
397 |
ret = lduw_kernel(addr & ~1);
|
|
389 | 398 |
break; |
390 | 399 |
default: |
391 | 400 |
case 4: |
392 |
ret = ldl_kernel(T0 & ~3);
|
|
401 |
ret = ldl_kernel(addr & ~3);
|
|
393 | 402 |
break; |
394 | 403 |
case 8: |
395 |
tmp = ldq_kernel(T0 & ~7); |
|
396 |
ret = tmp >> 32; |
|
397 |
T0 = tmp; |
|
404 |
ret = ldq_kernel(addr & ~7); |
|
398 | 405 |
break; |
399 | 406 |
} |
400 | 407 |
break; |
... | ... | |
406 | 413 |
case 0x20: /* MMU passthrough */ |
407 | 414 |
switch(size) { |
408 | 415 |
case 1: |
409 |
ret = ldub_phys(T0);
|
|
416 |
ret = ldub_phys(addr);
|
|
410 | 417 |
break; |
411 | 418 |
case 2: |
412 |
ret = lduw_phys(T0 & ~1);
|
|
419 |
ret = lduw_phys(addr & ~1);
|
|
413 | 420 |
break; |
414 | 421 |
default: |
415 | 422 |
case 4: |
416 |
ret = ldl_phys(T0 & ~3);
|
|
423 |
ret = ldl_phys(addr & ~3);
|
|
417 | 424 |
break; |
418 | 425 |
case 8: |
419 |
tmp = ldq_phys(T0 & ~7); |
|
420 |
ret = tmp >> 32; |
|
421 |
T0 = tmp; |
|
426 |
ret = ldq_phys(addr & ~7); |
|
422 | 427 |
break; |
423 | 428 |
} |
424 | 429 |
break; |
425 | 430 |
case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ |
426 | 431 |
switch(size) { |
427 | 432 |
case 1: |
428 |
ret = ldub_phys((target_phys_addr_t)T0
|
|
433 |
ret = ldub_phys((target_phys_addr_t)addr
|
|
429 | 434 |
| ((target_phys_addr_t)(asi & 0xf) << 32)); |
430 | 435 |
break; |
431 | 436 |
case 2: |
432 |
ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
|
|
437 |
ret = lduw_phys((target_phys_addr_t)(addr & ~1)
|
|
433 | 438 |
| ((target_phys_addr_t)(asi & 0xf) << 32)); |
434 | 439 |
break; |
435 | 440 |
default: |
436 | 441 |
case 4: |
437 |
ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
|
|
442 |
ret = ldl_phys((target_phys_addr_t)(addr & ~3)
|
|
438 | 443 |
| ((target_phys_addr_t)(asi & 0xf) << 32)); |
439 | 444 |
break; |
440 | 445 |
case 8: |
441 |
tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
|
|
446 |
ret = ldq_phys((target_phys_addr_t)(addr & ~7)
|
|
442 | 447 |
| ((target_phys_addr_t)(asi & 0xf) << 32)); |
443 |
ret = tmp >> 32; |
|
444 |
T0 = tmp; |
|
445 | 448 |
break; |
446 | 449 |
} |
447 | 450 |
break; |
... | ... | |
453 | 456 |
break; |
454 | 457 |
case 8: /* User code access, XXX */ |
455 | 458 |
default: |
456 |
do_unassigned_access(T0, 0, 0, asi);
|
|
459 |
do_unassigned_access(addr, 0, 0, asi);
|
|
457 | 460 |
ret = 0; |
458 | 461 |
break; |
459 | 462 |
} |
460 | 463 |
if (sign) { |
461 | 464 |
switch(size) { |
462 | 465 |
case 1: |
463 |
T1 = (int8_t) ret;
|
|
466 |
ret = (int8_t) ret;
|
|
464 | 467 |
break; |
465 | 468 |
case 2: |
466 |
T1 = (int16_t) ret; |
|
469 |
ret = (int16_t) ret; |
|
470 |
break; |
|
471 |
case 4: |
|
472 |
ret = (int32_t) ret; |
|
467 | 473 |
break; |
468 | 474 |
default: |
469 |
T1 = ret; |
|
470 | 475 |
break; |
471 | 476 |
} |
472 | 477 |
} |
473 |
else |
|
474 |
T1 = ret; |
|
475 | 478 |
#ifdef DEBUG_ASI |
476 |
dump_asi("read ", last_T0, asi, size, T1, T0);
|
|
479 |
dump_asi("read ", last_addr, asi, size, ret);
|
|
477 | 480 |
#endif |
481 |
return ret; |
|
478 | 482 |
} |
479 | 483 |
|
480 |
void helper_st_asi(int asi, int size) |
|
484 |
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
|
|
481 | 485 |
{ |
482 | 486 |
switch(asi) { |
483 | 487 |
case 2: /* SuperSparc MXCC registers */ |
484 |
switch (T0) {
|
|
488 |
switch (addr) {
|
|
485 | 489 |
case 0x01c00000: /* MXCC stream data register 0 */ |
486 | 490 |
if (size == 8) |
487 |
env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
|
|
491 |
env->mxccdata[0] = val;
|
|
488 | 492 |
else |
489 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
493 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
490 | 494 |
break; |
491 | 495 |
case 0x01c00008: /* MXCC stream data register 1 */ |
492 | 496 |
if (size == 8) |
493 |
env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
|
|
497 |
env->mxccdata[1] = val;
|
|
494 | 498 |
else |
495 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
499 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
496 | 500 |
break; |
497 | 501 |
case 0x01c00010: /* MXCC stream data register 2 */ |
498 | 502 |
if (size == 8) |
499 |
env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
|
|
503 |
env->mxccdata[2] = val;
|
|
500 | 504 |
else |
501 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
505 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
502 | 506 |
break; |
503 | 507 |
case 0x01c00018: /* MXCC stream data register 3 */ |
504 | 508 |
if (size == 8) |
505 |
env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
|
|
509 |
env->mxccdata[3] = val;
|
|
506 | 510 |
else |
507 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
511 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
508 | 512 |
break; |
509 | 513 |
case 0x01c00100: /* MXCC stream source */ |
510 | 514 |
if (size == 8) |
511 |
env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
|
|
515 |
env->mxccregs[0] = val;
|
|
512 | 516 |
else |
513 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
517 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
514 | 518 |
env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); |
515 | 519 |
env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); |
516 | 520 |
env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); |
... | ... | |
518 | 522 |
break; |
519 | 523 |
case 0x01c00200: /* MXCC stream destination */ |
520 | 524 |
if (size == 8) |
521 |
env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
|
|
525 |
env->mxccregs[1] = val;
|
|
522 | 526 |
else |
523 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
527 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
524 | 528 |
stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); |
525 | 529 |
stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); |
526 | 530 |
stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); |
... | ... | |
528 | 532 |
break; |
529 | 533 |
case 0x01c00a00: /* MXCC control register */ |
530 | 534 |
if (size == 8) |
531 |
env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
|
|
535 |
env->mxccregs[3] = val;
|
|
532 | 536 |
else |
533 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
537 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
534 | 538 |
break; |
535 | 539 |
case 0x01c00a04: /* MXCC control register */ |
536 | 540 |
if (size == 4) |
537 |
env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1;
|
|
541 |
env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
|
|
538 | 542 |
else |
539 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
543 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
540 | 544 |
break; |
541 | 545 |
case 0x01c00e00: /* MXCC error register */ |
542 | 546 |
// writing a 1 bit clears the error |
543 | 547 |
if (size == 8) |
544 |
env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2);
|
|
548 |
env->mxccregs[6] &= ~val;
|
|
545 | 549 |
else |
546 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
550 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
547 | 551 |
break; |
548 | 552 |
case 0x01c00f00: /* MBus port address register */ |
549 | 553 |
if (size == 8) |
550 |
env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
|
|
554 |
env->mxccregs[7] = val;
|
|
551 | 555 |
else |
552 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
|
556 |
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
|
|
553 | 557 |
break; |
554 | 558 |
default: |
555 |
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
|
|
559 |
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
|
|
556 | 560 |
break; |
557 | 561 |
} |
558 |
DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
|
|
562 |
DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
|
|
559 | 563 |
#ifdef DEBUG_MXCC |
560 | 564 |
dump_mxcc(env); |
561 | 565 |
#endif |
... | ... | |
564 | 568 |
{ |
565 | 569 |
int mmulev; |
566 | 570 |
|
567 |
mmulev = (T0 >> 8) & 15;
|
|
571 |
mmulev = (addr >> 8) & 15;
|
|
568 | 572 |
DPRINTF_MMU("mmu flush level %d\n", mmulev); |
569 | 573 |
switch (mmulev) { |
570 | 574 |
case 0: // flush page |
571 |
tlb_flush_page(env, T0 & 0xfffff000);
|
|
575 |
tlb_flush_page(env, addr & 0xfffff000);
|
|
572 | 576 |
break; |
573 | 577 |
case 1: // flush segment (256k) |
574 | 578 |
case 2: // flush region (16M) |
... | ... | |
586 | 590 |
break; |
587 | 591 |
case 4: /* write MMU regs */ |
588 | 592 |
{ |
589 |
int reg = (T0 >> 8) & 0x1f;
|
|
593 |
int reg = (addr >> 8) & 0x1f;
|
|
590 | 594 |
uint32_t oldreg; |
591 | 595 |
|
592 | 596 |
oldreg = env->mmuregs[reg]; |
593 | 597 |
switch(reg) { |
594 | 598 |
case 0: // Control Register |
595 | 599 |
env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | |
596 |
(T1 & 0x00ffffff);
|
|
600 |
(val & 0x00ffffff);
|
|
597 | 601 |
// Mappings generated during no-fault mode or MMU |
598 | 602 |
// disabled mode are invalid in normal mode |
599 | 603 |
if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) != |
... | ... | |
601 | 605 |
tlb_flush(env, 1); |
602 | 606 |
break; |
603 | 607 |
case 1: // Context Table Pointer Register |
604 |
env->mmuregs[reg] = T1 & env->mmu_ctpr_mask;
|
|
608 |
env->mmuregs[reg] = val & env->mmu_ctpr_mask;
|
|
605 | 609 |
break; |
606 | 610 |
case 2: // Context Register |
607 |
env->mmuregs[reg] = T1 & env->mmu_cxr_mask;
|
|
611 |
env->mmuregs[reg] = val & env->mmu_cxr_mask;
|
|
608 | 612 |
if (oldreg != env->mmuregs[reg]) { |
609 | 613 |
/* we flush when the MMU context changes because |
610 | 614 |
QEMU has no MMU context support */ |
... | ... | |
615 | 619 |
case 4: // Synchronous Fault Address Register |
616 | 620 |
break; |
617 | 621 |
case 0x10: // TLB Replacement Control Register |
618 |
env->mmuregs[reg] = T1 & env->mmu_trcr_mask;
|
|
622 |
env->mmuregs[reg] = val & env->mmu_trcr_mask;
|
|
619 | 623 |
break; |
620 | 624 |
case 0x13: // Synchronous Fault Status Register with Read and Clear |
621 |
env->mmuregs[3] = T1 & env->mmu_sfsr_mask;
|
|
625 |
env->mmuregs[3] = val & env->mmu_sfsr_mask;
|
|
622 | 626 |
break; |
623 | 627 |
case 0x14: // Synchronous Fault Address Register |
624 |
env->mmuregs[4] = T1;
|
|
628 |
env->mmuregs[4] = val;
|
|
625 | 629 |
break; |
626 | 630 |
default: |
627 |
env->mmuregs[reg] = T1;
|
|
631 |
env->mmuregs[reg] = val;
|
|
628 | 632 |
break; |
629 | 633 |
} |
630 | 634 |
if (oldreg != env->mmuregs[reg]) { |
... | ... | |
642 | 646 |
case 0xa: /* User data access */ |
643 | 647 |
switch(size) { |
644 | 648 |
case 1: |
645 |
stb_user(T0, T1);
|
|
649 |
stb_user(addr, val);
|
|
646 | 650 |
break; |
647 | 651 |
case 2: |
648 |
stw_user(T0 & ~1, T1);
|
|
652 |
stw_user(addr & ~1, val);
|
|
649 | 653 |
break; |
650 | 654 |
default: |
651 | 655 |
case 4: |
652 |
stl_user(T0 & ~3, T1);
|
|
656 |
stl_user(addr & ~3, val);
|
|
653 | 657 |
break; |
654 | 658 |
case 8: |
655 |
stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
|
|
659 |
stq_user(addr & ~7, val);
|
|
656 | 660 |
break; |
657 | 661 |
} |
658 | 662 |
break; |
659 | 663 |
case 0xb: /* Supervisor data access */ |
660 | 664 |
switch(size) { |
661 | 665 |
case 1: |
662 |
stb_kernel(T0, T1);
|
|
666 |
stb_kernel(addr, val);
|
|
663 | 667 |
break; |
664 | 668 |
case 2: |
665 |
stw_kernel(T0 & ~1, T1);
|
|
669 |
stw_kernel(addr & ~1, val);
|
|
666 | 670 |
break; |
667 | 671 |
default: |
668 | 672 |
case 4: |
669 |
stl_kernel(T0 & ~3, T1);
|
|
673 |
stl_kernel(addr & ~3, val);
|
|
670 | 674 |
break; |
671 | 675 |
case 8: |
672 |
stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
|
|
676 |
stq_kernel(addr & ~7, val);
|
|
673 | 677 |
break; |
674 | 678 |
} |
675 | 679 |
break; |
... | ... | |
685 | 689 |
break; |
686 | 690 |
case 0x17: /* Block copy, sta access */ |
687 | 691 |
{ |
688 |
// value (T1) = src
|
|
689 |
// address (T0) = dst
|
|
692 |
// val = src |
|
693 |
// addr = dst |
|
690 | 694 |
// copy 32 bytes |
691 | 695 |
unsigned int i; |
692 |
uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
|
|
696 |
uint32_t src = val & ~3, dst = addr & ~3, temp;
|
|
693 | 697 |
|
694 | 698 |
for (i = 0; i < 32; i += 4, src += 4, dst += 4) { |
695 | 699 |
temp = ldl_kernel(src); |
... | ... | |
699 | 703 |
break; |
700 | 704 |
case 0x1f: /* Block fill, stda access */ |
701 | 705 |
{ |
702 |
// value (T1, T2) |
|
703 |
// address (T0) = dst |
|
704 |
// fill 32 bytes |
|
706 |
// addr = dst |
|
707 |
// fill 32 bytes with val |
|
705 | 708 |
unsigned int i; |
706 |
uint32_t dst = T0 & 7; |
|
707 |
uint64_t val; |
|
708 |
|
|
709 |
val = (((uint64_t)T1) << 32) | T2; |
|
709 |
uint32_t dst = addr & 7; |
|
710 | 710 |
|
711 | 711 |
for (i = 0; i < 32; i += 8, dst += 8) |
712 | 712 |
stq_kernel(dst, val); |
... | ... | |
716 | 716 |
{ |
717 | 717 |
switch(size) { |
718 | 718 |
case 1: |
719 |
stb_phys(T0, T1);
|
|
719 |
stb_phys(addr, val);
|
|
720 | 720 |
break; |
721 | 721 |
case 2: |
722 |
stw_phys(T0 & ~1, T1);
|
|
722 |
stw_phys(addr & ~1, val);
|
|
723 | 723 |
break; |
724 | 724 |
case 4: |
725 | 725 |
default: |
726 |
stl_phys(T0 & ~3, T1);
|
|
726 |
stl_phys(addr & ~3, val);
|
|
727 | 727 |
break; |
728 | 728 |
case 8: |
729 |
stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
|
|
729 |
stq_phys(addr & ~7, val);
|
|
730 | 730 |
break; |
731 | 731 |
} |
732 | 732 |
} |
... | ... | |
735 | 735 |
{ |
736 | 736 |
switch(size) { |
737 | 737 |
case 1: |
738 |
stb_phys((target_phys_addr_t)T0
|
|
739 |
| ((target_phys_addr_t)(asi & 0xf) << 32), T1);
|
|
738 |
stb_phys((target_phys_addr_t)addr
|
|
739 |
| ((target_phys_addr_t)(asi & 0xf) << 32), val);
|
|
740 | 740 |
break; |
741 | 741 |
case 2: |
742 |
stw_phys((target_phys_addr_t)(T0 & ~1)
|
|
743 |
| ((target_phys_addr_t)(asi & 0xf) << 32), T1);
|
|
742 |
stw_phys((target_phys_addr_t)(addr & ~1)
|
|
743 |
| ((target_phys_addr_t)(asi & 0xf) << 32), val);
|
|
744 | 744 |
break; |
745 | 745 |
case 4: |
746 | 746 |
default: |
747 |
stl_phys((target_phys_addr_t)(T0 & ~3)
|
|
748 |
| ((target_phys_addr_t)(asi & 0xf) << 32), T1);
|
|
747 |
stl_phys((target_phys_addr_t)(addr & ~3)
|
|
748 |
| ((target_phys_addr_t)(asi & 0xf) << 32), val);
|
|
749 | 749 |
break; |
750 | 750 |
case 8: |
751 |
stq_phys((target_phys_addr_t)(T0 & ~7) |
|
752 |
| ((target_phys_addr_t)(asi & 0xf) << 32), |
|
753 |
((uint64_t)T1 << 32) | T2); |
|
751 |
stq_phys((target_phys_addr_t)(addr & ~7) |
|
752 |
| ((target_phys_addr_t)(asi & 0xf) << 32), val); |
|
754 | 753 |
break; |
755 | 754 |
} |
756 | 755 |
} |
... | ... | |
767 | 766 |
case 8: /* User code access, XXX */ |
768 | 767 |
case 9: /* Supervisor code access, XXX */ |
769 | 768 |
default: |
770 |
do_unassigned_access(T0, 1, 0, asi);
|
|
769 |
do_unassigned_access(addr, 1, 0, asi);
|
|
771 | 770 |
break; |
772 | 771 |
} |
773 | 772 |
#ifdef DEBUG_ASI |
774 |
dump_asi("write", T0, asi, size, T1, T2);
|
|
773 |
dump_asi("write", addr, asi, size, val);
|
|
775 | 774 |
#endif |
776 | 775 |
} |
777 | 776 |
|
... | ... | |
779 | 778 |
#else /* TARGET_SPARC64 */ |
780 | 779 |
|
781 | 780 |
#ifdef CONFIG_USER_ONLY |
782 |
void helper_ld_asi(int asi, int size, int sign)
|
|
781 |
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
|
|
783 | 782 |
{ |
784 | 783 |
uint64_t ret = 0; |
784 |
#if defined(DEBUG_ASI) |
|
785 |
target_ulong last_addr = addr; |
|
786 |
#endif |
|
785 | 787 |
|
786 | 788 |
if (asi < 0x80) |
787 | 789 |
raise_exception(TT_PRIV_ACT); |
... | ... | |
794 | 796 |
{ |
795 | 797 |
switch(size) { |
796 | 798 |
case 1: |
797 |
ret = ldub_raw(T0);
|
|
799 |
ret = ldub_raw(addr);
|
|
798 | 800 |
break; |
Also available in: Unified diff