root / target-sparc / op_helper.c @ eed152bb
History | View | Annotate | Download (49.4 kB)
1 | e8af50a3 | bellard | #include "exec.h" |
---|---|---|---|
2 | eed152bb | blueswir1 | #include "host-utils.h" |
3 | e8af50a3 | bellard | |
4 | 83469015 | bellard | //#define DEBUG_PCALL
|
5 | e80cfcfc | bellard | //#define DEBUG_MMU
|
6 | 952a328f | blueswir1 | //#define DEBUG_MXCC
|
7 | 94554550 | blueswir1 | //#define DEBUG_UNALIGNED
|
8 | 6c36d3fa | blueswir1 | //#define DEBUG_UNASSIGNED
|
9 | e80cfcfc | bellard | |
10 | 952a328f | blueswir1 | #ifdef DEBUG_MMU
|
11 | 952a328f | blueswir1 | #define DPRINTF_MMU(fmt, args...) \
|
12 | 952a328f | blueswir1 | do { printf("MMU: " fmt , ##args); } while (0) |
13 | 952a328f | blueswir1 | #else
|
14 | 952a328f | blueswir1 | #define DPRINTF_MMU(fmt, args...)
|
15 | 952a328f | blueswir1 | #endif
|
16 | 952a328f | blueswir1 | |
17 | 952a328f | blueswir1 | #ifdef DEBUG_MXCC
|
18 | 952a328f | blueswir1 | #define DPRINTF_MXCC(fmt, args...) \
|
19 | 952a328f | blueswir1 | do { printf("MXCC: " fmt , ##args); } while (0) |
20 | 952a328f | blueswir1 | #else
|
21 | 952a328f | blueswir1 | #define DPRINTF_MXCC(fmt, args...)
|
22 | 952a328f | blueswir1 | #endif
|
23 | 952a328f | blueswir1 | |
24 | 9d893301 | bellard | void raise_exception(int tt) |
25 | 9d893301 | bellard | { |
26 | 9d893301 | bellard | env->exception_index = tt; |
27 | 9d893301 | bellard | cpu_loop_exit(); |
28 | 3b46e624 | ths | } |
29 | 9d893301 | bellard | |
30 | 417454b0 | blueswir1 | void check_ieee_exceptions()
|
31 | 417454b0 | blueswir1 | { |
32 | 417454b0 | blueswir1 | T0 = get_float_exception_flags(&env->fp_status); |
33 | 417454b0 | blueswir1 | if (T0)
|
34 | 417454b0 | blueswir1 | { |
35 | 0f8a249a | blueswir1 | /* Copy IEEE 754 flags into FSR */
|
36 | 0f8a249a | blueswir1 | if (T0 & float_flag_invalid)
|
37 | 0f8a249a | blueswir1 | env->fsr |= FSR_NVC; |
38 | 0f8a249a | blueswir1 | if (T0 & float_flag_overflow)
|
39 | 0f8a249a | blueswir1 | env->fsr |= FSR_OFC; |
40 | 0f8a249a | blueswir1 | if (T0 & float_flag_underflow)
|
41 | 0f8a249a | blueswir1 | env->fsr |= FSR_UFC; |
42 | 0f8a249a | blueswir1 | if (T0 & float_flag_divbyzero)
|
43 | 0f8a249a | blueswir1 | env->fsr |= FSR_DZC; |
44 | 0f8a249a | blueswir1 | if (T0 & float_flag_inexact)
|
45 | 0f8a249a | blueswir1 | env->fsr |= FSR_NXC; |
46 | 0f8a249a | blueswir1 | |
47 | 0f8a249a | blueswir1 | if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) |
48 | 0f8a249a | blueswir1 | { |
49 | 0f8a249a | blueswir1 | /* Unmasked exception, generate a trap */
|
50 | 0f8a249a | blueswir1 | env->fsr |= FSR_FTT_IEEE_EXCP; |
51 | 0f8a249a | blueswir1 | raise_exception(TT_FP_EXCP); |
52 | 0f8a249a | blueswir1 | } |
53 | 0f8a249a | blueswir1 | else
|
54 | 0f8a249a | blueswir1 | { |
55 | 0f8a249a | blueswir1 | /* Accumulate exceptions */
|
56 | 0f8a249a | blueswir1 | env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
|
57 | 0f8a249a | blueswir1 | } |
58 | 417454b0 | blueswir1 | } |
59 | 417454b0 | blueswir1 | } |
60 | 417454b0 | blueswir1 | |
61 | a0c4cb4a | bellard | #ifdef USE_INT_TO_FLOAT_HELPERS
|
62 | a0c4cb4a | bellard | void do_fitos(void) |
63 | a0c4cb4a | bellard | { |
64 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
65 | ec230928 | ths | FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status); |
66 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
67 | a0c4cb4a | bellard | } |
68 | a0c4cb4a | bellard | |
69 | a0c4cb4a | bellard | void do_fitod(void) |
70 | a0c4cb4a | bellard | { |
71 | ec230928 | ths | DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status); |
72 | a0c4cb4a | bellard | } |
73 | 1e64e78d | blueswir1 | #ifdef TARGET_SPARC64
|
74 | 1e64e78d | blueswir1 | void do_fxtos(void) |
75 | 1e64e78d | blueswir1 | { |
76 | 1e64e78d | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
77 | 1e64e78d | blueswir1 | FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status); |
78 | 1e64e78d | blueswir1 | check_ieee_exceptions(); |
79 | 1e64e78d | blueswir1 | } |
80 | 1e64e78d | blueswir1 | |
81 | 1e64e78d | blueswir1 | void do_fxtod(void) |
82 | 1e64e78d | blueswir1 | { |
83 | 1e64e78d | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
84 | 1e64e78d | blueswir1 | DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); |
85 | 1e64e78d | blueswir1 | check_ieee_exceptions(); |
86 | 1e64e78d | blueswir1 | } |
87 | 1e64e78d | blueswir1 | #endif
|
88 | a0c4cb4a | bellard | #endif
|
89 | a0c4cb4a | bellard | |
90 | a0c4cb4a | bellard | void do_fabss(void) |
91 | e8af50a3 | bellard | { |
92 | 7a0e1f41 | bellard | FT0 = float32_abs(FT1); |
93 | e8af50a3 | bellard | } |
94 | e8af50a3 | bellard | |
95 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
96 | 3475187d | bellard | void do_fabsd(void) |
97 | 3475187d | bellard | { |
98 | 3475187d | bellard | DT0 = float64_abs(DT1); |
99 | 3475187d | bellard | } |
100 | 3475187d | bellard | #endif
|
101 | 3475187d | bellard | |
102 | a0c4cb4a | bellard | void do_fsqrts(void) |
103 | e8af50a3 | bellard | { |
104 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
105 | 7a0e1f41 | bellard | FT0 = float32_sqrt(FT1, &env->fp_status); |
106 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
107 | e8af50a3 | bellard | } |
108 | e8af50a3 | bellard | |
109 | a0c4cb4a | bellard | void do_fsqrtd(void) |
110 | e8af50a3 | bellard | { |
111 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
112 | 7a0e1f41 | bellard | DT0 = float64_sqrt(DT1, &env->fp_status); |
113 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
114 | e8af50a3 | bellard | } |
115 | e8af50a3 | bellard | |
116 | 417454b0 | blueswir1 | #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
|
117 | 65ce8c2f | bellard | void glue(do_, name) (void) \ |
118 | 65ce8c2f | bellard | { \ |
119 | 65ce8c2f | bellard | env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ |
120 | 65ce8c2f | bellard | switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
|
121 | 65ce8c2f | bellard | case float_relation_unordered: \
|
122 | 65ce8c2f | bellard | T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ |
123 | 417454b0 | blueswir1 | if ((env->fsr & FSR_NVM) || TRAP) { \
|
124 | 65ce8c2f | bellard | env->fsr |= T0; \ |
125 | 417454b0 | blueswir1 | env->fsr |= FSR_NVC; \ |
126 | 417454b0 | blueswir1 | env->fsr |= FSR_FTT_IEEE_EXCP; \ |
127 | 65ce8c2f | bellard | raise_exception(TT_FP_EXCP); \ |
128 | 65ce8c2f | bellard | } else { \
|
129 | 65ce8c2f | bellard | env->fsr |= FSR_NVA; \ |
130 | 65ce8c2f | bellard | } \ |
131 | 65ce8c2f | bellard | break; \
|
132 | 65ce8c2f | bellard | case float_relation_less: \
|
133 | 65ce8c2f | bellard | T0 = FSR_FCC0 << FS; \ |
134 | 65ce8c2f | bellard | break; \
|
135 | 65ce8c2f | bellard | case float_relation_greater: \
|
136 | 65ce8c2f | bellard | T0 = FSR_FCC1 << FS; \ |
137 | 65ce8c2f | bellard | break; \
|
138 | 65ce8c2f | bellard | default: \
|
139 | 65ce8c2f | bellard | T0 = 0; \
|
140 | 65ce8c2f | bellard | break; \
|
141 | 65ce8c2f | bellard | } \ |
142 | 65ce8c2f | bellard | env->fsr |= T0; \ |
143 | e8af50a3 | bellard | } |
144 | e8af50a3 | bellard | |
145 | 417454b0 | blueswir1 | GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0); |
146 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); |
147 | 417454b0 | blueswir1 | |
148 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1); |
149 | 417454b0 | blueswir1 | GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); |
150 | 3475187d | bellard | |
151 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
152 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0); |
153 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); |
154 | 417454b0 | blueswir1 | |
155 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0); |
156 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); |
157 | 417454b0 | blueswir1 | |
158 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0); |
159 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); |
160 | 417454b0 | blueswir1 | |
161 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1); |
162 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); |
163 | 3475187d | bellard | |
164 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1); |
165 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); |
166 | 3475187d | bellard | |
167 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); |
168 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); |
169 | 3475187d | bellard | #endif
|
170 | 3475187d | bellard | |
171 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
172 | 81ad8ba2 | blueswir1 | #ifndef CONFIG_USER_ONLY
|
173 | 952a328f | blueswir1 | |
174 | 952a328f | blueswir1 | #ifdef DEBUG_MXCC
|
175 | 952a328f | blueswir1 | static void dump_mxcc(CPUState *env) |
176 | 952a328f | blueswir1 | { |
177 | 952a328f | blueswir1 | printf("mxccdata: %016llx %016llx %016llx %016llx\n",
|
178 | 952a328f | blueswir1 | env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]); |
179 | 952a328f | blueswir1 | printf("mxccregs: %016llx %016llx %016llx %016llx\n"
|
180 | 952a328f | blueswir1 | " %016llx %016llx %016llx %016llx\n",
|
181 | 952a328f | blueswir1 | env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3], |
182 | 952a328f | blueswir1 | env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]); |
183 | 952a328f | blueswir1 | } |
184 | 952a328f | blueswir1 | #endif
|
185 | 952a328f | blueswir1 | |
186 | a0c4cb4a | bellard | void helper_ld_asi(int asi, int size, int sign) |
187 | e8af50a3 | bellard | { |
188 | 83469015 | bellard | uint32_t ret = 0;
|
189 | e909ec2f | blueswir1 | uint64_t tmp; |
190 | 952a328f | blueswir1 | #ifdef DEBUG_MXCC
|
191 | 952a328f | blueswir1 | uint32_t last_T0 = T0; |
192 | 952a328f | blueswir1 | #endif
|
193 | e80cfcfc | bellard | |
194 | e80cfcfc | bellard | switch (asi) {
|
195 | 6c36d3fa | blueswir1 | case 2: /* SuperSparc MXCC registers */ |
196 | 952a328f | blueswir1 | switch (T0) {
|
197 | 952a328f | blueswir1 | case 0x01c00a00: /* MXCC control register */ |
198 | 952a328f | blueswir1 | if (size == 8) { |
199 | 952a328f | blueswir1 | ret = env->mxccregs[3];
|
200 | 952a328f | blueswir1 | T0 = env->mxccregs[3] >> 32; |
201 | 952a328f | blueswir1 | } else
|
202 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
203 | 952a328f | blueswir1 | break;
|
204 | 952a328f | blueswir1 | case 0x01c00a04: /* MXCC control register */ |
205 | 952a328f | blueswir1 | if (size == 4) |
206 | 952a328f | blueswir1 | ret = env->mxccregs[3];
|
207 | 952a328f | blueswir1 | else
|
208 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
209 | 952a328f | blueswir1 | break;
|
210 | 952a328f | blueswir1 | case 0x01c00f00: /* MBus port address register */ |
211 | 952a328f | blueswir1 | if (size == 8) { |
212 | 952a328f | blueswir1 | ret = env->mxccregs[7];
|
213 | 952a328f | blueswir1 | T0 = env->mxccregs[7] >> 32; |
214 | 952a328f | blueswir1 | } else
|
215 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
216 | 952a328f | blueswir1 | break;
|
217 | 952a328f | blueswir1 | default:
|
218 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
|
219 | 952a328f | blueswir1 | break;
|
220 | 952a328f | blueswir1 | } |
221 | 952a328f | blueswir1 | DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
|
222 | 952a328f | blueswir1 | "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
|
223 | 952a328f | blueswir1 | #ifdef DEBUG_MXCC
|
224 | 952a328f | blueswir1 | dump_mxcc(env); |
225 | 952a328f | blueswir1 | #endif
|
226 | 6c36d3fa | blueswir1 | break;
|
227 | e8af50a3 | bellard | case 3: /* MMU probe */ |
228 | 0f8a249a | blueswir1 | { |
229 | 0f8a249a | blueswir1 | int mmulev;
|
230 | 0f8a249a | blueswir1 | |
231 | 0f8a249a | blueswir1 | mmulev = (T0 >> 8) & 15; |
232 | 0f8a249a | blueswir1 | if (mmulev > 4) |
233 | 0f8a249a | blueswir1 | ret = 0;
|
234 | 0f8a249a | blueswir1 | else {
|
235 | 0f8a249a | blueswir1 | ret = mmu_probe(env, T0, mmulev); |
236 | 0f8a249a | blueswir1 | //bswap32s(&ret);
|
237 | 0f8a249a | blueswir1 | } |
238 | 952a328f | blueswir1 | DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
|
239 | 0f8a249a | blueswir1 | } |
240 | 0f8a249a | blueswir1 | break;
|
241 | e8af50a3 | bellard | case 4: /* read MMU regs */ |
242 | 0f8a249a | blueswir1 | { |
243 | 0f8a249a | blueswir1 | int reg = (T0 >> 8) & 0xf; |
244 | 3b46e624 | ths | |
245 | 0f8a249a | blueswir1 | ret = env->mmuregs[reg]; |
246 | 0f8a249a | blueswir1 | if (reg == 3) /* Fault status cleared on read */ |
247 | 0f8a249a | blueswir1 | env->mmuregs[reg] = 0;
|
248 | 952a328f | blueswir1 | DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
|
249 | 0f8a249a | blueswir1 | } |
250 | 0f8a249a | blueswir1 | break;
|
251 | 6c36d3fa | blueswir1 | case 9: /* Supervisor code access */ |
252 | 6c36d3fa | blueswir1 | switch(size) {
|
253 | 6c36d3fa | blueswir1 | case 1: |
254 | 6c36d3fa | blueswir1 | ret = ldub_code(T0); |
255 | 6c36d3fa | blueswir1 | break;
|
256 | 6c36d3fa | blueswir1 | case 2: |
257 | 6c36d3fa | blueswir1 | ret = lduw_code(T0 & ~1);
|
258 | 6c36d3fa | blueswir1 | break;
|
259 | 6c36d3fa | blueswir1 | default:
|
260 | 6c36d3fa | blueswir1 | case 4: |
261 | 6c36d3fa | blueswir1 | ret = ldl_code(T0 & ~3);
|
262 | 6c36d3fa | blueswir1 | break;
|
263 | 6c36d3fa | blueswir1 | case 8: |
264 | e909ec2f | blueswir1 | tmp = ldq_code(T0 & ~7);
|
265 | e909ec2f | blueswir1 | ret = tmp >> 32;
|
266 | e909ec2f | blueswir1 | T0 = tmp & 0xffffffff;
|
267 | 6c36d3fa | blueswir1 | break;
|
268 | 6c36d3fa | blueswir1 | } |
269 | 6c36d3fa | blueswir1 | break;
|
270 | 81ad8ba2 | blueswir1 | case 0xa: /* User data access */ |
271 | 81ad8ba2 | blueswir1 | switch(size) {
|
272 | 81ad8ba2 | blueswir1 | case 1: |
273 | 81ad8ba2 | blueswir1 | ret = ldub_user(T0); |
274 | 81ad8ba2 | blueswir1 | break;
|
275 | 81ad8ba2 | blueswir1 | case 2: |
276 | 81ad8ba2 | blueswir1 | ret = lduw_user(T0 & ~1);
|
277 | 81ad8ba2 | blueswir1 | break;
|
278 | 81ad8ba2 | blueswir1 | default:
|
279 | 81ad8ba2 | blueswir1 | case 4: |
280 | 81ad8ba2 | blueswir1 | ret = ldl_user(T0 & ~3);
|
281 | 81ad8ba2 | blueswir1 | break;
|
282 | 81ad8ba2 | blueswir1 | case 8: |
283 | e909ec2f | blueswir1 | tmp = ldq_user(T0 & ~7);
|
284 | e909ec2f | blueswir1 | ret = tmp >> 32;
|
285 | e909ec2f | blueswir1 | T0 = tmp & 0xffffffff;
|
286 | 81ad8ba2 | blueswir1 | break;
|
287 | 81ad8ba2 | blueswir1 | } |
288 | 81ad8ba2 | blueswir1 | break;
|
289 | 81ad8ba2 | blueswir1 | case 0xb: /* Supervisor data access */ |
290 | 81ad8ba2 | blueswir1 | switch(size) {
|
291 | 81ad8ba2 | blueswir1 | case 1: |
292 | 81ad8ba2 | blueswir1 | ret = ldub_kernel(T0); |
293 | 81ad8ba2 | blueswir1 | break;
|
294 | 81ad8ba2 | blueswir1 | case 2: |
295 | 81ad8ba2 | blueswir1 | ret = lduw_kernel(T0 & ~1);
|
296 | 81ad8ba2 | blueswir1 | break;
|
297 | 81ad8ba2 | blueswir1 | default:
|
298 | 81ad8ba2 | blueswir1 | case 4: |
299 | 81ad8ba2 | blueswir1 | ret = ldl_kernel(T0 & ~3);
|
300 | 81ad8ba2 | blueswir1 | break;
|
301 | 81ad8ba2 | blueswir1 | case 8: |
302 | e909ec2f | blueswir1 | tmp = ldq_kernel(T0 & ~7);
|
303 | e909ec2f | blueswir1 | ret = tmp >> 32;
|
304 | e909ec2f | blueswir1 | T0 = tmp & 0xffffffff;
|
305 | 81ad8ba2 | blueswir1 | break;
|
306 | 81ad8ba2 | blueswir1 | } |
307 | 81ad8ba2 | blueswir1 | break;
|
308 | 6c36d3fa | blueswir1 | case 0xc: /* I-cache tag */ |
309 | 6c36d3fa | blueswir1 | case 0xd: /* I-cache data */ |
310 | 6c36d3fa | blueswir1 | case 0xe: /* D-cache tag */ |
311 | 6c36d3fa | blueswir1 | case 0xf: /* D-cache data */ |
312 | 6c36d3fa | blueswir1 | break;
|
313 | 6c36d3fa | blueswir1 | case 0x20: /* MMU passthrough */ |
314 | 02aab46a | bellard | switch(size) {
|
315 | 02aab46a | bellard | case 1: |
316 | 02aab46a | bellard | ret = ldub_phys(T0); |
317 | 02aab46a | bellard | break;
|
318 | 02aab46a | bellard | case 2: |
319 | 02aab46a | bellard | ret = lduw_phys(T0 & ~1);
|
320 | 02aab46a | bellard | break;
|
321 | 02aab46a | bellard | default:
|
322 | 02aab46a | bellard | case 4: |
323 | 02aab46a | bellard | ret = ldl_phys(T0 & ~3);
|
324 | 02aab46a | bellard | break;
|
325 | 9e61bde5 | bellard | case 8: |
326 | e909ec2f | blueswir1 | tmp = ldq_phys(T0 & ~7);
|
327 | e909ec2f | blueswir1 | ret = tmp >> 32;
|
328 | e909ec2f | blueswir1 | T0 = tmp & 0xffffffff;
|
329 | 0f8a249a | blueswir1 | break;
|
330 | 02aab46a | bellard | } |
331 | 0f8a249a | blueswir1 | break;
|
332 | 5dcb6b91 | blueswir1 | case 0x2e: /* MMU passthrough, 0xexxxxxxxx */ |
333 | 5dcb6b91 | blueswir1 | case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */ |
334 | 5dcb6b91 | blueswir1 | switch(size) {
|
335 | 5dcb6b91 | blueswir1 | case 1: |
336 | 5dcb6b91 | blueswir1 | ret = ldub_phys((target_phys_addr_t)T0 |
337 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
338 | 5dcb6b91 | blueswir1 | break;
|
339 | 5dcb6b91 | blueswir1 | case 2: |
340 | 5dcb6b91 | blueswir1 | ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
|
341 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
342 | 5dcb6b91 | blueswir1 | break;
|
343 | 5dcb6b91 | blueswir1 | default:
|
344 | 5dcb6b91 | blueswir1 | case 4: |
345 | 5dcb6b91 | blueswir1 | ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
|
346 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
347 | 5dcb6b91 | blueswir1 | break;
|
348 | 5dcb6b91 | blueswir1 | case 8: |
349 | e909ec2f | blueswir1 | tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
|
350 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
351 | e909ec2f | blueswir1 | ret = tmp >> 32;
|
352 | e909ec2f | blueswir1 | T0 = tmp & 0xffffffff;
|
353 | 0f8a249a | blueswir1 | break;
|
354 | 5dcb6b91 | blueswir1 | } |
355 | 0f8a249a | blueswir1 | break;
|
356 | 5dcb6b91 | blueswir1 | case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ |
357 | e8af50a3 | bellard | default:
|
358 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 0, 0, 1); |
359 | 0f8a249a | blueswir1 | ret = 0;
|
360 | 0f8a249a | blueswir1 | break;
|
361 | e8af50a3 | bellard | } |
362 | 81ad8ba2 | blueswir1 | if (sign) {
|
363 | 81ad8ba2 | blueswir1 | switch(size) {
|
364 | 81ad8ba2 | blueswir1 | case 1: |
365 | 81ad8ba2 | blueswir1 | T1 = (int8_t) ret; |
366 | e32664fb | blueswir1 | break;
|
367 | 81ad8ba2 | blueswir1 | case 2: |
368 | 81ad8ba2 | blueswir1 | T1 = (int16_t) ret; |
369 | e32664fb | blueswir1 | break;
|
370 | 81ad8ba2 | blueswir1 | default:
|
371 | 81ad8ba2 | blueswir1 | T1 = ret; |
372 | 81ad8ba2 | blueswir1 | break;
|
373 | 81ad8ba2 | blueswir1 | } |
374 | 81ad8ba2 | blueswir1 | } |
375 | 81ad8ba2 | blueswir1 | else
|
376 | 81ad8ba2 | blueswir1 | T1 = ret; |
377 | e8af50a3 | bellard | } |
378 | e8af50a3 | bellard | |
379 | 81ad8ba2 | blueswir1 | void helper_st_asi(int asi, int size) |
380 | e8af50a3 | bellard | { |
381 | e8af50a3 | bellard | switch(asi) {
|
382 | 6c36d3fa | blueswir1 | case 2: /* SuperSparc MXCC registers */ |
383 | 952a328f | blueswir1 | switch (T0) {
|
384 | 952a328f | blueswir1 | case 0x01c00000: /* MXCC stream data register 0 */ |
385 | 952a328f | blueswir1 | if (size == 8) |
386 | 952a328f | blueswir1 | env->mxccdata[0] = ((uint64_t)T1 << 32) | T2; |
387 | 952a328f | blueswir1 | else
|
388 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
389 | 952a328f | blueswir1 | break;
|
390 | 952a328f | blueswir1 | case 0x01c00008: /* MXCC stream data register 1 */ |
391 | 952a328f | blueswir1 | if (size == 8) |
392 | 952a328f | blueswir1 | env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; |
393 | 952a328f | blueswir1 | else
|
394 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
395 | 952a328f | blueswir1 | break;
|
396 | 952a328f | blueswir1 | case 0x01c00010: /* MXCC stream data register 2 */ |
397 | 952a328f | blueswir1 | if (size == 8) |
398 | 952a328f | blueswir1 | env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; |
399 | 952a328f | blueswir1 | else
|
400 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
401 | 952a328f | blueswir1 | break;
|
402 | 952a328f | blueswir1 | case 0x01c00018: /* MXCC stream data register 3 */ |
403 | 952a328f | blueswir1 | if (size == 8) |
404 | 952a328f | blueswir1 | env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; |
405 | 952a328f | blueswir1 | else
|
406 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
407 | 952a328f | blueswir1 | break;
|
408 | 952a328f | blueswir1 | case 0x01c00100: /* MXCC stream source */ |
409 | 952a328f | blueswir1 | if (size == 8) |
410 | 952a328f | blueswir1 | env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; |
411 | 952a328f | blueswir1 | else
|
412 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
413 | 952a328f | blueswir1 | env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); |
414 | 952a328f | blueswir1 | env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); |
415 | 952a328f | blueswir1 | env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); |
416 | 952a328f | blueswir1 | env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24); |
417 | 952a328f | blueswir1 | break;
|
418 | 952a328f | blueswir1 | case 0x01c00200: /* MXCC stream destination */ |
419 | 952a328f | blueswir1 | if (size == 8) |
420 | 952a328f | blueswir1 | env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; |
421 | 952a328f | blueswir1 | else
|
422 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
423 | 952a328f | blueswir1 | stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); |
424 | 952a328f | blueswir1 | stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); |
425 | 952a328f | blueswir1 | stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); |
426 | 952a328f | blueswir1 | stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]); |
427 | 952a328f | blueswir1 | break;
|
428 | 952a328f | blueswir1 | case 0x01c00a00: /* MXCC control register */ |
429 | 952a328f | blueswir1 | if (size == 8) |
430 | 952a328f | blueswir1 | env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; |
431 | 952a328f | blueswir1 | else
|
432 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
433 | 952a328f | blueswir1 | break;
|
434 | 952a328f | blueswir1 | case 0x01c00a04: /* MXCC control register */ |
435 | 952a328f | blueswir1 | if (size == 4) |
436 | 952a328f | blueswir1 | env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000) | T1; |
437 | 952a328f | blueswir1 | else
|
438 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
439 | 952a328f | blueswir1 | break;
|
440 | 952a328f | blueswir1 | case 0x01c00e00: /* MXCC error register */ |
441 | 952a328f | blueswir1 | if (size == 8) |
442 | 952a328f | blueswir1 | env->mxccregs[6] = ((uint64_t)T1 << 32) | T2; |
443 | 952a328f | blueswir1 | else
|
444 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
445 | 952a328f | blueswir1 | if (env->mxccregs[6] == 0xffffffffffffffffULL) { |
446 | 952a328f | blueswir1 | // this is probably a reset
|
447 | 952a328f | blueswir1 | } |
448 | 952a328f | blueswir1 | break;
|
449 | 952a328f | blueswir1 | case 0x01c00f00: /* MBus port address register */ |
450 | 952a328f | blueswir1 | if (size == 8) |
451 | 952a328f | blueswir1 | env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; |
452 | 952a328f | blueswir1 | else
|
453 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
|
454 | 952a328f | blueswir1 | break;
|
455 | 952a328f | blueswir1 | default:
|
456 | 952a328f | blueswir1 | DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
|
457 | 952a328f | blueswir1 | break;
|
458 | 952a328f | blueswir1 | } |
459 | 952a328f | blueswir1 | DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
|
460 | 952a328f | blueswir1 | #ifdef DEBUG_MXCC
|
461 | 952a328f | blueswir1 | dump_mxcc(env); |
462 | 952a328f | blueswir1 | #endif
|
463 | 6c36d3fa | blueswir1 | break;
|
464 | e8af50a3 | bellard | case 3: /* MMU flush */ |
465 | 0f8a249a | blueswir1 | { |
466 | 0f8a249a | blueswir1 | int mmulev;
|
467 | e80cfcfc | bellard | |
468 | 0f8a249a | blueswir1 | mmulev = (T0 >> 8) & 15; |
469 | 952a328f | blueswir1 | DPRINTF_MMU("mmu flush level %d\n", mmulev);
|
470 | 0f8a249a | blueswir1 | switch (mmulev) {
|
471 | 0f8a249a | blueswir1 | case 0: // flush page |
472 | 0f8a249a | blueswir1 | tlb_flush_page(env, T0 & 0xfffff000);
|
473 | 0f8a249a | blueswir1 | break;
|
474 | 0f8a249a | blueswir1 | case 1: // flush segment (256k) |
475 | 0f8a249a | blueswir1 | case 2: // flush region (16M) |
476 | 0f8a249a | blueswir1 | case 3: // flush context (4G) |
477 | 0f8a249a | blueswir1 | case 4: // flush entire |
478 | 0f8a249a | blueswir1 | tlb_flush(env, 1);
|
479 | 0f8a249a | blueswir1 | break;
|
480 | 0f8a249a | blueswir1 | default:
|
481 | 0f8a249a | blueswir1 | break;
|
482 | 0f8a249a | blueswir1 | } |
483 | 55754d9e | bellard | #ifdef DEBUG_MMU
|
484 | 0f8a249a | blueswir1 | dump_mmu(env); |
485 | 55754d9e | bellard | #endif
|
486 | 0f8a249a | blueswir1 | return;
|
487 | 0f8a249a | blueswir1 | } |
488 | e8af50a3 | bellard | case 4: /* write MMU regs */ |
489 | 0f8a249a | blueswir1 | { |
490 | 0f8a249a | blueswir1 | int reg = (T0 >> 8) & 0xf; |
491 | 0f8a249a | blueswir1 | uint32_t oldreg; |
492 | 3b46e624 | ths | |
493 | 0f8a249a | blueswir1 | oldreg = env->mmuregs[reg]; |
494 | 55754d9e | bellard | switch(reg) {
|
495 | 55754d9e | bellard | case 0: |
496 | 40ce0a9a | blueswir1 | env->mmuregs[reg] &= ~(MMU_E | MMU_NF | MMU_BM); |
497 | 40ce0a9a | blueswir1 | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF | MMU_BM); |
498 | 0f8a249a | blueswir1 | // Mappings generated during no-fault mode or MMU
|
499 | 0f8a249a | blueswir1 | // disabled mode are invalid in normal mode
|
500 | 6f7e9aec | bellard | if (oldreg != env->mmuregs[reg])
|
501 | 55754d9e | bellard | tlb_flush(env, 1);
|
502 | 55754d9e | bellard | break;
|
503 | 55754d9e | bellard | case 2: |
504 | 0f8a249a | blueswir1 | env->mmuregs[reg] = T1; |
505 | 55754d9e | bellard | if (oldreg != env->mmuregs[reg]) {
|
506 | 55754d9e | bellard | /* we flush when the MMU context changes because
|
507 | 55754d9e | bellard | QEMU has no MMU context support */
|
508 | 55754d9e | bellard | tlb_flush(env, 1);
|
509 | 55754d9e | bellard | } |
510 | 55754d9e | bellard | break;
|
511 | 55754d9e | bellard | case 3: |
512 | 55754d9e | bellard | case 4: |
513 | 55754d9e | bellard | break;
|
514 | 55754d9e | bellard | default:
|
515 | 0f8a249a | blueswir1 | env->mmuregs[reg] = T1; |
516 | 55754d9e | bellard | break;
|
517 | 55754d9e | bellard | } |
518 | 55754d9e | bellard | if (oldreg != env->mmuregs[reg]) {
|
519 | 952a328f | blueswir1 | DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
|
520 | 55754d9e | bellard | } |
521 | 952a328f | blueswir1 | #ifdef DEBUG_MMU
|
522 | 0f8a249a | blueswir1 | dump_mmu(env); |
523 | 55754d9e | bellard | #endif
|
524 | 0f8a249a | blueswir1 | return;
|
525 | 0f8a249a | blueswir1 | } |
526 | 81ad8ba2 | blueswir1 | case 0xa: /* User data access */ |
527 | 81ad8ba2 | blueswir1 | switch(size) {
|
528 | 81ad8ba2 | blueswir1 | case 1: |
529 | 81ad8ba2 | blueswir1 | stb_user(T0, T1); |
530 | 81ad8ba2 | blueswir1 | break;
|
531 | 81ad8ba2 | blueswir1 | case 2: |
532 | 81ad8ba2 | blueswir1 | stw_user(T0 & ~1, T1);
|
533 | 81ad8ba2 | blueswir1 | break;
|
534 | 81ad8ba2 | blueswir1 | default:
|
535 | 81ad8ba2 | blueswir1 | case 4: |
536 | 81ad8ba2 | blueswir1 | stl_user(T0 & ~3, T1);
|
537 | 81ad8ba2 | blueswir1 | break;
|
538 | 81ad8ba2 | blueswir1 | case 8: |
539 | e909ec2f | blueswir1 | stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2); |
540 | 81ad8ba2 | blueswir1 | break;
|
541 | 81ad8ba2 | blueswir1 | } |
542 | 81ad8ba2 | blueswir1 | break;
|
543 | 81ad8ba2 | blueswir1 | case 0xb: /* Supervisor data access */ |
544 | 81ad8ba2 | blueswir1 | switch(size) {
|
545 | 81ad8ba2 | blueswir1 | case 1: |
546 | 81ad8ba2 | blueswir1 | stb_kernel(T0, T1); |
547 | 81ad8ba2 | blueswir1 | break;
|
548 | 81ad8ba2 | blueswir1 | case 2: |
549 | 81ad8ba2 | blueswir1 | stw_kernel(T0 & ~1, T1);
|
550 | 81ad8ba2 | blueswir1 | break;
|
551 | 81ad8ba2 | blueswir1 | default:
|
552 | 81ad8ba2 | blueswir1 | case 4: |
553 | 81ad8ba2 | blueswir1 | stl_kernel(T0 & ~3, T1);
|
554 | 81ad8ba2 | blueswir1 | break;
|
555 | 81ad8ba2 | blueswir1 | case 8: |
556 | e909ec2f | blueswir1 | stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2); |
557 | 81ad8ba2 | blueswir1 | break;
|
558 | 81ad8ba2 | blueswir1 | } |
559 | 81ad8ba2 | blueswir1 | break;
|
560 | 6c36d3fa | blueswir1 | case 0xc: /* I-cache tag */ |
561 | 6c36d3fa | blueswir1 | case 0xd: /* I-cache data */ |
562 | 6c36d3fa | blueswir1 | case 0xe: /* D-cache tag */ |
563 | 6c36d3fa | blueswir1 | case 0xf: /* D-cache data */ |
564 | 6c36d3fa | blueswir1 | case 0x10: /* I/D-cache flush page */ |
565 | 6c36d3fa | blueswir1 | case 0x11: /* I/D-cache flush segment */ |
566 | 6c36d3fa | blueswir1 | case 0x12: /* I/D-cache flush region */ |
567 | 6c36d3fa | blueswir1 | case 0x13: /* I/D-cache flush context */ |
568 | 6c36d3fa | blueswir1 | case 0x14: /* I/D-cache flush user */ |
569 | 6c36d3fa | blueswir1 | break;
|
570 | e80cfcfc | bellard | case 0x17: /* Block copy, sta access */ |
571 | 0f8a249a | blueswir1 | { |
572 | 0f8a249a | blueswir1 | // value (T1) = src
|
573 | 0f8a249a | blueswir1 | // address (T0) = dst
|
574 | 0f8a249a | blueswir1 | // copy 32 bytes
|
575 | 6c36d3fa | blueswir1 | unsigned int i; |
576 | 6c36d3fa | blueswir1 | uint32_t src = T1 & ~3, dst = T0 & ~3, temp; |
577 | 3b46e624 | ths | |
578 | 6c36d3fa | blueswir1 | for (i = 0; i < 32; i += 4, src += 4, dst += 4) { |
579 | 6c36d3fa | blueswir1 | temp = ldl_kernel(src); |
580 | 6c36d3fa | blueswir1 | stl_kernel(dst, temp); |
581 | 6c36d3fa | blueswir1 | } |
582 | 0f8a249a | blueswir1 | } |
583 | 0f8a249a | blueswir1 | return;
|
584 | e80cfcfc | bellard | case 0x1f: /* Block fill, stda access */ |
585 | 0f8a249a | blueswir1 | { |
586 | 0f8a249a | blueswir1 | // value (T1, T2)
|
587 | 0f8a249a | blueswir1 | // address (T0) = dst
|
588 | 0f8a249a | blueswir1 | // fill 32 bytes
|
589 | 6c36d3fa | blueswir1 | unsigned int i; |
590 | 6c36d3fa | blueswir1 | uint32_t dst = T0 & 7;
|
591 | 6c36d3fa | blueswir1 | uint64_t val; |
592 | e80cfcfc | bellard | |
593 | 6c36d3fa | blueswir1 | val = (((uint64_t)T1) << 32) | T2;
|
594 | 6c36d3fa | blueswir1 | |
595 | 6c36d3fa | blueswir1 | for (i = 0; i < 32; i += 8, dst += 8) |
596 | 6c36d3fa | blueswir1 | stq_kernel(dst, val); |
597 | 0f8a249a | blueswir1 | } |
598 | 0f8a249a | blueswir1 | return;
|
599 | 6c36d3fa | blueswir1 | case 0x20: /* MMU passthrough */ |
600 | 0f8a249a | blueswir1 | { |
601 | 02aab46a | bellard | switch(size) {
|
602 | 02aab46a | bellard | case 1: |
603 | 02aab46a | bellard | stb_phys(T0, T1); |
604 | 02aab46a | bellard | break;
|
605 | 02aab46a | bellard | case 2: |
606 | 02aab46a | bellard | stw_phys(T0 & ~1, T1);
|
607 | 02aab46a | bellard | break;
|
608 | 02aab46a | bellard | case 4: |
609 | 02aab46a | bellard | default:
|
610 | 02aab46a | bellard | stl_phys(T0 & ~3, T1);
|
611 | 02aab46a | bellard | break;
|
612 | 9e61bde5 | bellard | case 8: |
613 | e909ec2f | blueswir1 | stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2); |
614 | 9e61bde5 | bellard | break;
|
615 | 02aab46a | bellard | } |
616 | 0f8a249a | blueswir1 | } |
617 | 0f8a249a | blueswir1 | return;
|
618 | 5dcb6b91 | blueswir1 | case 0x2e: /* MMU passthrough, 0xexxxxxxxx */ |
619 | 5dcb6b91 | blueswir1 | case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */ |
620 | 0f8a249a | blueswir1 | { |
621 | 5dcb6b91 | blueswir1 | switch(size) {
|
622 | 5dcb6b91 | blueswir1 | case 1: |
623 | 5dcb6b91 | blueswir1 | stb_phys((target_phys_addr_t)T0 |
624 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
625 | 5dcb6b91 | blueswir1 | break;
|
626 | 5dcb6b91 | blueswir1 | case 2: |
627 | 5dcb6b91 | blueswir1 | stw_phys((target_phys_addr_t)(T0 & ~1)
|
628 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
629 | 5dcb6b91 | blueswir1 | break;
|
630 | 5dcb6b91 | blueswir1 | case 4: |
631 | 5dcb6b91 | blueswir1 | default:
|
632 | 5dcb6b91 | blueswir1 | stl_phys((target_phys_addr_t)(T0 & ~3)
|
633 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
634 | 5dcb6b91 | blueswir1 | break;
|
635 | 5dcb6b91 | blueswir1 | case 8: |
636 | e909ec2f | blueswir1 | stq_phys((target_phys_addr_t)(T0 & ~7)
|
637 | e909ec2f | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), |
638 | e909ec2f | blueswir1 | ((uint64_t)T1 << 32) | T2);
|
639 | 5dcb6b91 | blueswir1 | break;
|
640 | 5dcb6b91 | blueswir1 | } |
641 | 0f8a249a | blueswir1 | } |
642 | 0f8a249a | blueswir1 | return;
|
643 | 6c36d3fa | blueswir1 | case 0x31: /* Ross RT620 I-cache flush */ |
644 | 6c36d3fa | blueswir1 | case 0x36: /* I-cache flash clear */ |
645 | 6c36d3fa | blueswir1 | case 0x37: /* D-cache flash clear */ |
646 | 6c36d3fa | blueswir1 | break;
|
647 | 6c36d3fa | blueswir1 | case 9: /* Supervisor code access, XXX */ |
648 | 5dcb6b91 | blueswir1 | case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ |
649 | e8af50a3 | bellard | default:
|
650 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 1, 0, 1); |
651 | 0f8a249a | blueswir1 | return;
|
652 | e8af50a3 | bellard | } |
653 | e8af50a3 | bellard | } |
654 | e8af50a3 | bellard | |
655 | 81ad8ba2 | blueswir1 | #endif /* CONFIG_USER_ONLY */ |
656 | 81ad8ba2 | blueswir1 | #else /* TARGET_SPARC64 */ |
657 | 81ad8ba2 | blueswir1 | |
658 | 81ad8ba2 | blueswir1 | #ifdef CONFIG_USER_ONLY
|
659 | 81ad8ba2 | blueswir1 | void helper_ld_asi(int asi, int size, int sign) |
660 | 81ad8ba2 | blueswir1 | { |
661 | 81ad8ba2 | blueswir1 | uint64_t ret = 0;
|
662 | 81ad8ba2 | blueswir1 | |
663 | 81ad8ba2 | blueswir1 | if (asi < 0x80) |
664 | 81ad8ba2 | blueswir1 | raise_exception(TT_PRIV_ACT); |
665 | 81ad8ba2 | blueswir1 | |
666 | 81ad8ba2 | blueswir1 | switch (asi) {
|
667 | 81ad8ba2 | blueswir1 | case 0x80: // Primary |
668 | 81ad8ba2 | blueswir1 | case 0x82: // Primary no-fault |
669 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
670 | 81ad8ba2 | blueswir1 | case 0x8a: // Primary no-fault LE |
671 | 81ad8ba2 | blueswir1 | { |
672 | 81ad8ba2 | blueswir1 | switch(size) {
|
673 | 81ad8ba2 | blueswir1 | case 1: |
674 | 81ad8ba2 | blueswir1 | ret = ldub_raw(T0); |
675 | 81ad8ba2 | blueswir1 | break;
|
676 | 81ad8ba2 | blueswir1 | case 2: |
677 | 81ad8ba2 | blueswir1 | ret = lduw_raw(T0 & ~1);
|
678 | 81ad8ba2 | blueswir1 | break;
|
679 | 81ad8ba2 | blueswir1 | case 4: |
680 | 81ad8ba2 | blueswir1 | ret = ldl_raw(T0 & ~3);
|
681 | 81ad8ba2 | blueswir1 | break;
|
682 | 81ad8ba2 | blueswir1 | default:
|
683 | 81ad8ba2 | blueswir1 | case 8: |
684 | 81ad8ba2 | blueswir1 | ret = ldq_raw(T0 & ~7);
|
685 | 81ad8ba2 | blueswir1 | break;
|
686 | 81ad8ba2 | blueswir1 | } |
687 | 81ad8ba2 | blueswir1 | } |
688 | 81ad8ba2 | blueswir1 | break;
|
689 | 81ad8ba2 | blueswir1 | case 0x81: // Secondary |
690 | 81ad8ba2 | blueswir1 | case 0x83: // Secondary no-fault |
691 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
692 | 81ad8ba2 | blueswir1 | case 0x8b: // Secondary no-fault LE |
693 | 81ad8ba2 | blueswir1 | // XXX
|
694 | 81ad8ba2 | blueswir1 | break;
|
695 | 81ad8ba2 | blueswir1 | default:
|
696 | 81ad8ba2 | blueswir1 | break;
|
697 | 81ad8ba2 | blueswir1 | } |
698 | 81ad8ba2 | blueswir1 | |
699 | 81ad8ba2 | blueswir1 | /* Convert from little endian */
|
700 | 81ad8ba2 | blueswir1 | switch (asi) {
|
701 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
702 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
703 | 81ad8ba2 | blueswir1 | case 0x8a: // Primary no-fault LE |
704 | 81ad8ba2 | blueswir1 | case 0x8b: // Secondary no-fault LE |
705 | 81ad8ba2 | blueswir1 | switch(size) {
|
706 | 81ad8ba2 | blueswir1 | case 2: |
707 | 81ad8ba2 | blueswir1 | ret = bswap16(ret); |
708 | e32664fb | blueswir1 | break;
|
709 | 81ad8ba2 | blueswir1 | case 4: |
710 | 81ad8ba2 | blueswir1 | ret = bswap32(ret); |
711 | e32664fb | blueswir1 | break;
|
712 | 81ad8ba2 | blueswir1 | case 8: |
713 | 81ad8ba2 | blueswir1 | ret = bswap64(ret); |
714 | e32664fb | blueswir1 | break;
|
715 | 81ad8ba2 | blueswir1 | default:
|
716 | 81ad8ba2 | blueswir1 | break;
|
717 | 81ad8ba2 | blueswir1 | } |
718 | 81ad8ba2 | blueswir1 | default:
|
719 | 81ad8ba2 | blueswir1 | break;
|
720 | 81ad8ba2 | blueswir1 | } |
721 | 81ad8ba2 | blueswir1 | |
722 | 81ad8ba2 | blueswir1 | /* Convert to signed number */
|
723 | 81ad8ba2 | blueswir1 | if (sign) {
|
724 | 81ad8ba2 | blueswir1 | switch(size) {
|
725 | 81ad8ba2 | blueswir1 | case 1: |
726 | 81ad8ba2 | blueswir1 | ret = (int8_t) ret; |
727 | e32664fb | blueswir1 | break;
|
728 | 81ad8ba2 | blueswir1 | case 2: |
729 | 81ad8ba2 | blueswir1 | ret = (int16_t) ret; |
730 | e32664fb | blueswir1 | break;
|
731 | 81ad8ba2 | blueswir1 | case 4: |
732 | 81ad8ba2 | blueswir1 | ret = (int32_t) ret; |
733 | e32664fb | blueswir1 | break;
|
734 | 81ad8ba2 | blueswir1 | default:
|
735 | 81ad8ba2 | blueswir1 | break;
|
736 | 81ad8ba2 | blueswir1 | } |
737 | 81ad8ba2 | blueswir1 | } |
738 | 81ad8ba2 | blueswir1 | T1 = ret; |
739 | 81ad8ba2 | blueswir1 | } |
740 | 81ad8ba2 | blueswir1 | |
741 | 81ad8ba2 | blueswir1 | void helper_st_asi(int asi, int size) |
742 | 81ad8ba2 | blueswir1 | { |
743 | 81ad8ba2 | blueswir1 | if (asi < 0x80) |
744 | 81ad8ba2 | blueswir1 | raise_exception(TT_PRIV_ACT); |
745 | 81ad8ba2 | blueswir1 | |
746 | 81ad8ba2 | blueswir1 | /* Convert to little endian */
|
747 | 81ad8ba2 | blueswir1 | switch (asi) {
|
748 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
749 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
750 | 81ad8ba2 | blueswir1 | switch(size) {
|
751 | 81ad8ba2 | blueswir1 | case 2: |
752 | 81ad8ba2 | blueswir1 | T0 = bswap16(T0); |
753 | e32664fb | blueswir1 | break;
|
754 | 81ad8ba2 | blueswir1 | case 4: |
755 | 81ad8ba2 | blueswir1 | T0 = bswap32(T0); |
756 | e32664fb | blueswir1 | break;
|
757 | 81ad8ba2 | blueswir1 | case 8: |
758 | 81ad8ba2 | blueswir1 | T0 = bswap64(T0); |
759 | e32664fb | blueswir1 | break;
|
760 | 81ad8ba2 | blueswir1 | default:
|
761 | 81ad8ba2 | blueswir1 | break;
|
762 | 81ad8ba2 | blueswir1 | } |
763 | 81ad8ba2 | blueswir1 | default:
|
764 | 81ad8ba2 | blueswir1 | break;
|
765 | 81ad8ba2 | blueswir1 | } |
766 | 81ad8ba2 | blueswir1 | |
767 | 81ad8ba2 | blueswir1 | switch(asi) {
|
768 | 81ad8ba2 | blueswir1 | case 0x80: // Primary |
769 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
770 | 81ad8ba2 | blueswir1 | { |
771 | 81ad8ba2 | blueswir1 | switch(size) {
|
772 | 81ad8ba2 | blueswir1 | case 1: |
773 | 81ad8ba2 | blueswir1 | stb_raw(T0, T1); |
774 | 81ad8ba2 | blueswir1 | break;
|
775 | 81ad8ba2 | blueswir1 | case 2: |
776 | 81ad8ba2 | blueswir1 | stw_raw(T0 & ~1, T1);
|
777 | 81ad8ba2 | blueswir1 | break;
|
778 | 81ad8ba2 | blueswir1 | case 4: |
779 | 81ad8ba2 | blueswir1 | stl_raw(T0 & ~3, T1);
|
780 | 81ad8ba2 | blueswir1 | break;
|
781 | 81ad8ba2 | blueswir1 | case 8: |
782 | 81ad8ba2 | blueswir1 | default:
|
783 | 81ad8ba2 | blueswir1 | stq_raw(T0 & ~7, T1);
|
784 | 81ad8ba2 | blueswir1 | break;
|
785 | 81ad8ba2 | blueswir1 | } |
786 | 81ad8ba2 | blueswir1 | } |
787 | 81ad8ba2 | blueswir1 | break;
|
788 | 81ad8ba2 | blueswir1 | case 0x81: // Secondary |
789 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
790 | 81ad8ba2 | blueswir1 | // XXX
|
791 | 81ad8ba2 | blueswir1 | return;
|
792 | 81ad8ba2 | blueswir1 | |
793 | 81ad8ba2 | blueswir1 | case 0x82: // Primary no-fault, RO |
794 | 81ad8ba2 | blueswir1 | case 0x83: // Secondary no-fault, RO |
795 | 81ad8ba2 | blueswir1 | case 0x8a: // Primary no-fault LE, RO |
796 | 81ad8ba2 | blueswir1 | case 0x8b: // Secondary no-fault LE, RO |
797 | 81ad8ba2 | blueswir1 | default:
|
798 | 81ad8ba2 | blueswir1 | do_unassigned_access(T0, 1, 0, 1); |
799 | 81ad8ba2 | blueswir1 | return;
|
800 | 81ad8ba2 | blueswir1 | } |
801 | 81ad8ba2 | blueswir1 | } |
802 | 81ad8ba2 | blueswir1 | |
803 | 81ad8ba2 | blueswir1 | #else /* CONFIG_USER_ONLY */ |
804 | 3475187d | bellard | |
805 | 3475187d | bellard | void helper_ld_asi(int asi, int size, int sign) |
806 | 3475187d | bellard | { |
807 | 83469015 | bellard | uint64_t ret = 0;
|
808 | 3475187d | bellard | |
809 | 6f27aba6 | blueswir1 | if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
810 | 20b749f6 | blueswir1 | || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) |
811 | 0f8a249a | blueswir1 | raise_exception(TT_PRIV_ACT); |
812 | 3475187d | bellard | |
813 | 3475187d | bellard | switch (asi) {
|
814 | 81ad8ba2 | blueswir1 | case 0x10: // As if user primary |
815 | 81ad8ba2 | blueswir1 | case 0x18: // As if user primary LE |
816 | 81ad8ba2 | blueswir1 | case 0x80: // Primary |
817 | 81ad8ba2 | blueswir1 | case 0x82: // Primary no-fault |
818 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
819 | 81ad8ba2 | blueswir1 | case 0x8a: // Primary no-fault LE |
820 | 81ad8ba2 | blueswir1 | if ((asi & 0x80) && (env->pstate & PS_PRIV)) { |
821 | 6f27aba6 | blueswir1 | if (env->hpstate & HS_PRIV) {
|
822 | 6f27aba6 | blueswir1 | switch(size) {
|
823 | 6f27aba6 | blueswir1 | case 1: |
824 | 6f27aba6 | blueswir1 | ret = ldub_hypv(T0); |
825 | 6f27aba6 | blueswir1 | break;
|
826 | 6f27aba6 | blueswir1 | case 2: |
827 | 6f27aba6 | blueswir1 | ret = lduw_hypv(T0 & ~1);
|
828 | 6f27aba6 | blueswir1 | break;
|
829 | 6f27aba6 | blueswir1 | case 4: |
830 | 6f27aba6 | blueswir1 | ret = ldl_hypv(T0 & ~3);
|
831 | 6f27aba6 | blueswir1 | break;
|
832 | 6f27aba6 | blueswir1 | default:
|
833 | 6f27aba6 | blueswir1 | case 8: |
834 | 6f27aba6 | blueswir1 | ret = ldq_hypv(T0 & ~7);
|
835 | 6f27aba6 | blueswir1 | break;
|
836 | 6f27aba6 | blueswir1 | } |
837 | 6f27aba6 | blueswir1 | } else {
|
838 | 6f27aba6 | blueswir1 | switch(size) {
|
839 | 6f27aba6 | blueswir1 | case 1: |
840 | 6f27aba6 | blueswir1 | ret = ldub_kernel(T0); |
841 | 6f27aba6 | blueswir1 | break;
|
842 | 6f27aba6 | blueswir1 | case 2: |
843 | 6f27aba6 | blueswir1 | ret = lduw_kernel(T0 & ~1);
|
844 | 6f27aba6 | blueswir1 | break;
|
845 | 6f27aba6 | blueswir1 | case 4: |
846 | 6f27aba6 | blueswir1 | ret = ldl_kernel(T0 & ~3);
|
847 | 6f27aba6 | blueswir1 | break;
|
848 | 6f27aba6 | blueswir1 | default:
|
849 | 6f27aba6 | blueswir1 | case 8: |
850 | 6f27aba6 | blueswir1 | ret = ldq_kernel(T0 & ~7);
|
851 | 6f27aba6 | blueswir1 | break;
|
852 | 6f27aba6 | blueswir1 | } |
853 | 81ad8ba2 | blueswir1 | } |
854 | 81ad8ba2 | blueswir1 | } else {
|
855 | 81ad8ba2 | blueswir1 | switch(size) {
|
856 | 81ad8ba2 | blueswir1 | case 1: |
857 | 81ad8ba2 | blueswir1 | ret = ldub_user(T0); |
858 | 81ad8ba2 | blueswir1 | break;
|
859 | 81ad8ba2 | blueswir1 | case 2: |
860 | 81ad8ba2 | blueswir1 | ret = lduw_user(T0 & ~1);
|
861 | 81ad8ba2 | blueswir1 | break;
|
862 | 81ad8ba2 | blueswir1 | case 4: |
863 | 81ad8ba2 | blueswir1 | ret = ldl_user(T0 & ~3);
|
864 | 81ad8ba2 | blueswir1 | break;
|
865 | 81ad8ba2 | blueswir1 | default:
|
866 | 81ad8ba2 | blueswir1 | case 8: |
867 | 81ad8ba2 | blueswir1 | ret = ldq_user(T0 & ~7);
|
868 | 81ad8ba2 | blueswir1 | break;
|
869 | 81ad8ba2 | blueswir1 | } |
870 | 81ad8ba2 | blueswir1 | } |
871 | 81ad8ba2 | blueswir1 | break;
|
872 | 3475187d | bellard | case 0x14: // Bypass |
873 | 3475187d | bellard | case 0x15: // Bypass, non-cacheable |
874 | 81ad8ba2 | blueswir1 | case 0x1c: // Bypass LE |
875 | 81ad8ba2 | blueswir1 | case 0x1d: // Bypass, non-cacheable LE |
876 | 0f8a249a | blueswir1 | { |
877 | 02aab46a | bellard | switch(size) {
|
878 | 02aab46a | bellard | case 1: |
879 | 02aab46a | bellard | ret = ldub_phys(T0); |
880 | 02aab46a | bellard | break;
|
881 | 02aab46a | bellard | case 2: |
882 | 02aab46a | bellard | ret = lduw_phys(T0 & ~1);
|
883 | 02aab46a | bellard | break;
|
884 | 02aab46a | bellard | case 4: |
885 | 02aab46a | bellard | ret = ldl_phys(T0 & ~3);
|
886 | 02aab46a | bellard | break;
|
887 | 02aab46a | bellard | default:
|
888 | 02aab46a | bellard | case 8: |
889 | 02aab46a | bellard | ret = ldq_phys(T0 & ~7);
|
890 | 02aab46a | bellard | break;
|
891 | 02aab46a | bellard | } |
892 | 0f8a249a | blueswir1 | break;
|
893 | 0f8a249a | blueswir1 | } |
894 | 83469015 | bellard | case 0x04: // Nucleus |
895 | 83469015 | bellard | case 0x0c: // Nucleus Little Endian (LE) |
896 | 83469015 | bellard | case 0x11: // As if user secondary |
897 | 83469015 | bellard | case 0x19: // As if user secondary LE |
898 | 83469015 | bellard | case 0x24: // Nucleus quad LDD 128 bit atomic |
899 | 83469015 | bellard | case 0x2c: // Nucleus quad LDD 128 bit atomic |
900 | 83469015 | bellard | case 0x4a: // UPA config |
901 | 81ad8ba2 | blueswir1 | case 0x81: // Secondary |
902 | 83469015 | bellard | case 0x83: // Secondary no-fault |
903 | 83469015 | bellard | case 0x89: // Secondary LE |
904 | 83469015 | bellard | case 0x8b: // Secondary no-fault LE |
905 | 0f8a249a | blueswir1 | // XXX
|
906 | 0f8a249a | blueswir1 | break;
|
907 | 3475187d | bellard | case 0x45: // LSU |
908 | 0f8a249a | blueswir1 | ret = env->lsu; |
909 | 0f8a249a | blueswir1 | break;
|
910 | 3475187d | bellard | case 0x50: // I-MMU regs |
911 | 0f8a249a | blueswir1 | { |
912 | 0f8a249a | blueswir1 | int reg = (T0 >> 3) & 0xf; |
913 | 3475187d | bellard | |
914 | 0f8a249a | blueswir1 | ret = env->immuregs[reg]; |
915 | 0f8a249a | blueswir1 | break;
|
916 | 0f8a249a | blueswir1 | } |
917 | 3475187d | bellard | case 0x51: // I-MMU 8k TSB pointer |
918 | 3475187d | bellard | case 0x52: // I-MMU 64k TSB pointer |
919 | 3475187d | bellard | case 0x55: // I-MMU data access |
920 | 0f8a249a | blueswir1 | // XXX
|
921 | 0f8a249a | blueswir1 | break;
|
922 | 83469015 | bellard | case 0x56: // I-MMU tag read |
923 | 0f8a249a | blueswir1 | { |
924 | 0f8a249a | blueswir1 | unsigned int i; |
925 | 0f8a249a | blueswir1 | |
926 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
927 | 0f8a249a | blueswir1 | // Valid, ctx match, vaddr match
|
928 | 0f8a249a | blueswir1 | if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && |
929 | 0f8a249a | blueswir1 | env->itlb_tag[i] == T0) { |
930 | 0f8a249a | blueswir1 | ret = env->itlb_tag[i]; |
931 | 0f8a249a | blueswir1 | break;
|
932 | 0f8a249a | blueswir1 | } |
933 | 0f8a249a | blueswir1 | } |
934 | 0f8a249a | blueswir1 | break;
|
935 | 0f8a249a | blueswir1 | } |
936 | 3475187d | bellard | case 0x58: // D-MMU regs |
937 | 0f8a249a | blueswir1 | { |
938 | 0f8a249a | blueswir1 | int reg = (T0 >> 3) & 0xf; |
939 | 3475187d | bellard | |
940 | 0f8a249a | blueswir1 | ret = env->dmmuregs[reg]; |
941 | 0f8a249a | blueswir1 | break;
|
942 | 0f8a249a | blueswir1 | } |
943 | 83469015 | bellard | case 0x5e: // D-MMU tag read |
944 | 0f8a249a | blueswir1 | { |
945 | 0f8a249a | blueswir1 | unsigned int i; |
946 | 0f8a249a | blueswir1 | |
947 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
948 | 0f8a249a | blueswir1 | // Valid, ctx match, vaddr match
|
949 | 0f8a249a | blueswir1 | if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && |
950 | 0f8a249a | blueswir1 | env->dtlb_tag[i] == T0) { |
951 | 0f8a249a | blueswir1 | ret = env->dtlb_tag[i]; |
952 | 0f8a249a | blueswir1 | break;
|
953 | 0f8a249a | blueswir1 | } |
954 | 0f8a249a | blueswir1 | } |
955 | 0f8a249a | blueswir1 | break;
|
956 | 0f8a249a | blueswir1 | } |
957 | 3475187d | bellard | case 0x59: // D-MMU 8k TSB pointer |
958 | 3475187d | bellard | case 0x5a: // D-MMU 64k TSB pointer |
959 | 3475187d | bellard | case 0x5b: // D-MMU data pointer |
960 | 3475187d | bellard | case 0x5d: // D-MMU data access |
961 | 83469015 | bellard | case 0x48: // Interrupt dispatch, RO |
962 | 83469015 | bellard | case 0x49: // Interrupt data receive |
963 | 83469015 | bellard | case 0x7f: // Incoming interrupt vector, RO |
964 | 0f8a249a | blueswir1 | // XXX
|
965 | 0f8a249a | blueswir1 | break;
|
966 | 3475187d | bellard | case 0x54: // I-MMU data in, WO |
967 | 3475187d | bellard | case 0x57: // I-MMU demap, WO |
968 | 3475187d | bellard | case 0x5c: // D-MMU data in, WO |
969 | 3475187d | bellard | case 0x5f: // D-MMU demap, WO |
970 | 83469015 | bellard | case 0x77: // Interrupt vector, WO |
971 | 3475187d | bellard | default:
|
972 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 0, 0, 1); |
973 | 0f8a249a | blueswir1 | ret = 0;
|
974 | 0f8a249a | blueswir1 | break;
|
975 | 3475187d | bellard | } |
976 | 81ad8ba2 | blueswir1 | |
977 | 81ad8ba2 | blueswir1 | /* Convert from little endian */
|
978 | 81ad8ba2 | blueswir1 | switch (asi) {
|
979 | 81ad8ba2 | blueswir1 | case 0x0c: // Nucleus Little Endian (LE) |
980 | 81ad8ba2 | blueswir1 | case 0x18: // As if user primary LE |
981 | 81ad8ba2 | blueswir1 | case 0x19: // As if user secondary LE |
982 | 81ad8ba2 | blueswir1 | case 0x1c: // Bypass LE |
983 | 81ad8ba2 | blueswir1 | case 0x1d: // Bypass, non-cacheable LE |
984 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
985 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
986 | 81ad8ba2 | blueswir1 | case 0x8a: // Primary no-fault LE |
987 | 81ad8ba2 | blueswir1 | case 0x8b: // Secondary no-fault LE |
988 | 81ad8ba2 | blueswir1 | switch(size) {
|
989 | 81ad8ba2 | blueswir1 | case 2: |
990 | 81ad8ba2 | blueswir1 | ret = bswap16(ret); |
991 | e32664fb | blueswir1 | break;
|
992 | 81ad8ba2 | blueswir1 | case 4: |
993 | 81ad8ba2 | blueswir1 | ret = bswap32(ret); |
994 | e32664fb | blueswir1 | break;
|
995 | 81ad8ba2 | blueswir1 | case 8: |
996 | 81ad8ba2 | blueswir1 | ret = bswap64(ret); |
997 | e32664fb | blueswir1 | break;
|
998 | 81ad8ba2 | blueswir1 | default:
|
999 | 81ad8ba2 | blueswir1 | break;
|
1000 | 81ad8ba2 | blueswir1 | } |
1001 | 81ad8ba2 | blueswir1 | default:
|
1002 | 81ad8ba2 | blueswir1 | break;
|
1003 | 81ad8ba2 | blueswir1 | } |
1004 | 81ad8ba2 | blueswir1 | |
1005 | 81ad8ba2 | blueswir1 | /* Convert to signed number */
|
1006 | 81ad8ba2 | blueswir1 | if (sign) {
|
1007 | 81ad8ba2 | blueswir1 | switch(size) {
|
1008 | 81ad8ba2 | blueswir1 | case 1: |
1009 | 81ad8ba2 | blueswir1 | ret = (int8_t) ret; |
1010 | e32664fb | blueswir1 | break;
|
1011 | 81ad8ba2 | blueswir1 | case 2: |
1012 | 81ad8ba2 | blueswir1 | ret = (int16_t) ret; |
1013 | e32664fb | blueswir1 | break;
|
1014 | 81ad8ba2 | blueswir1 | case 4: |
1015 | 81ad8ba2 | blueswir1 | ret = (int32_t) ret; |
1016 | e32664fb | blueswir1 | break;
|
1017 | 81ad8ba2 | blueswir1 | default:
|
1018 | 81ad8ba2 | blueswir1 | break;
|
1019 | 81ad8ba2 | blueswir1 | } |
1020 | 81ad8ba2 | blueswir1 | } |
1021 | 3475187d | bellard | T1 = ret; |
1022 | 3475187d | bellard | } |
1023 | 3475187d | bellard | |
1024 | 81ad8ba2 | blueswir1 | void helper_st_asi(int asi, int size) |
1025 | 3475187d | bellard | { |
1026 | 6f27aba6 | blueswir1 | if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
1027 | 20b749f6 | blueswir1 | || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) |
1028 | 0f8a249a | blueswir1 | raise_exception(TT_PRIV_ACT); |
1029 | 3475187d | bellard | |
1030 | 81ad8ba2 | blueswir1 | /* Convert to little endian */
|
1031 | 81ad8ba2 | blueswir1 | switch (asi) {
|
1032 | 81ad8ba2 | blueswir1 | case 0x0c: // Nucleus Little Endian (LE) |
1033 | 81ad8ba2 | blueswir1 | case 0x18: // As if user primary LE |
1034 | 81ad8ba2 | blueswir1 | case 0x19: // As if user secondary LE |
1035 | 81ad8ba2 | blueswir1 | case 0x1c: // Bypass LE |
1036 | 81ad8ba2 | blueswir1 | case 0x1d: // Bypass, non-cacheable LE |
1037 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
1038 | 81ad8ba2 | blueswir1 | case 0x89: // Secondary LE |
1039 | 81ad8ba2 | blueswir1 | switch(size) {
|
1040 | 81ad8ba2 | blueswir1 | case 2: |
1041 | 81ad8ba2 | blueswir1 | T0 = bswap16(T0); |
1042 | e32664fb | blueswir1 | break;
|
1043 | 81ad8ba2 | blueswir1 | case 4: |
1044 | 81ad8ba2 | blueswir1 | T0 = bswap32(T0); |
1045 | e32664fb | blueswir1 | break;
|
1046 | 81ad8ba2 | blueswir1 | case 8: |
1047 | 81ad8ba2 | blueswir1 | T0 = bswap64(T0); |
1048 | e32664fb | blueswir1 | break;
|
1049 | 81ad8ba2 | blueswir1 | default:
|
1050 | 81ad8ba2 | blueswir1 | break;
|
1051 | 81ad8ba2 | blueswir1 | } |
1052 | 81ad8ba2 | blueswir1 | default:
|
1053 | 81ad8ba2 | blueswir1 | break;
|
1054 | 81ad8ba2 | blueswir1 | } |
1055 | 81ad8ba2 | blueswir1 | |
1056 | 3475187d | bellard | switch(asi) {
|
1057 | 81ad8ba2 | blueswir1 | case 0x10: // As if user primary |
1058 | 81ad8ba2 | blueswir1 | case 0x18: // As if user primary LE |
1059 | 81ad8ba2 | blueswir1 | case 0x80: // Primary |
1060 | 81ad8ba2 | blueswir1 | case 0x88: // Primary LE |
1061 | 81ad8ba2 | blueswir1 | if ((asi & 0x80) && (env->pstate & PS_PRIV)) { |
1062 | 6f27aba6 | blueswir1 | if (env->hpstate & HS_PRIV) {
|
1063 | 6f27aba6 | blueswir1 | switch(size) {
|
1064 | 6f27aba6 | blueswir1 | case 1: |
1065 | 6f27aba6 | blueswir1 | stb_hypv(T0, T1); |
1066 | 6f27aba6 | blueswir1 | break;
|
1067 | 6f27aba6 | blueswir1 | case 2: |
1068 | 6f27aba6 | blueswir1 | stw_hypv(T0 & ~1, T1);
|
1069 | 6f27aba6 | blueswir1 | break;
|
1070 | 6f27aba6 | blueswir1 | case 4: |
1071 | 6f27aba6 | blueswir1 | stl_hypv(T0 & ~3, T1);
|
1072 | 6f27aba6 | blueswir1 | break;
|
1073 | 6f27aba6 | blueswir1 | case 8: |
1074 | 6f27aba6 | blueswir1 | default:
|
1075 | 6f27aba6 | blueswir1 | stq_hypv(T0 & ~7, T1);
|
1076 | 6f27aba6 | blueswir1 | break;
|
1077 | 6f27aba6 | blueswir1 | } |
1078 | 6f27aba6 | blueswir1 | } else {
|
1079 | 6f27aba6 | blueswir1 | switch(size) {
|
1080 | 6f27aba6 | blueswir1 | case 1: |
1081 | 6f27aba6 | blueswir1 | stb_kernel(T0, T1); |
1082 | 6f27aba6 | blueswir1 | break;
|
1083 | 6f27aba6 | blueswir1 | case 2: |
1084 | 6f27aba6 | blueswir1 | stw_kernel(T0 & ~1, T1);
|
1085 | 6f27aba6 | blueswir1 | break;
|
1086 | 6f27aba6 | blueswir1 | case 4: |
1087 | 6f27aba6 | blueswir1 | stl_kernel(T0 & ~3, T1);
|
1088 | 6f27aba6 | blueswir1 | break;
|
1089 | 6f27aba6 | blueswir1 | case 8: |
1090 | 6f27aba6 | blueswir1 | default:
|
1091 | 6f27aba6 | blueswir1 | stq_kernel(T0 & ~7, T1);
|
1092 | 6f27aba6 | blueswir1 | break;
|
1093 | 6f27aba6 | blueswir1 | } |
1094 | 81ad8ba2 | blueswir1 | } |
1095 | 81ad8ba2 | blueswir1 | } else {
|
1096 | 81ad8ba2 | blueswir1 | switch(size) {
|
1097 | 81ad8ba2 | blueswir1 | case 1: |
1098 | 81ad8ba2 | blueswir1 | stb_user(T0, T1); |
1099 | 81ad8ba2 | blueswir1 | break;
|
1100 | 81ad8ba2 | blueswir1 | case 2: |
1101 | 81ad8ba2 | blueswir1 | stw_user(T0 & ~1, T1);
|
1102 | 81ad8ba2 | blueswir1 | break;
|
1103 | 81ad8ba2 | blueswir1 | case 4: |
1104 | 81ad8ba2 | blueswir1 | stl_user(T0 & ~3, T1);
|
1105 | 81ad8ba2 | blueswir1 | break;
|
1106 | 81ad8ba2 | blueswir1 | case 8: |
1107 | 81ad8ba2 | blueswir1 | default:
|
1108 | 81ad8ba2 | blueswir1 | stq_user(T0 & ~7, T1);
|
1109 | 81ad8ba2 | blueswir1 | break;
|
1110 | 81ad8ba2 | blueswir1 | } |
1111 | 81ad8ba2 | blueswir1 | } |
1112 | 81ad8ba2 | blueswir1 | break;
|
1113 | 3475187d | bellard | case 0x14: // Bypass |
1114 | 3475187d | bellard | case 0x15: // Bypass, non-cacheable |
1115 | 81ad8ba2 | blueswir1 | case 0x1c: // Bypass LE |
1116 | 81ad8ba2 | blueswir1 | case 0x1d: // Bypass, non-cacheable LE |
1117 | 0f8a249a | blueswir1 | { |
1118 | 02aab46a | bellard | switch(size) {
|
1119 | 02aab46a | bellard | case 1: |
1120 | 02aab46a | bellard | stb_phys(T0, T1); |
1121 | 02aab46a | bellard | break;
|
1122 | 02aab46a | bellard | case 2: |
1123 | 02aab46a | bellard | stw_phys(T0 & ~1, T1);
|
1124 | 02aab46a | bellard | break;
|
1125 | 02aab46a | bellard | case 4: |
1126 | 02aab46a | bellard | stl_phys(T0 & ~3, T1);
|
1127 | 02aab46a | bellard | break;
|
1128 | 02aab46a | bellard | case 8: |
1129 | 02aab46a | bellard | default:
|
1130 | 02aab46a | bellard | stq_phys(T0 & ~7, T1);
|
1131 | 02aab46a | bellard | break;
|
1132 | 02aab46a | bellard | } |
1133 | 0f8a249a | blueswir1 | } |
1134 | 0f8a249a | blueswir1 | return;
|
1135 | 83469015 | bellard | case 0x04: // Nucleus |
1136 | 83469015 | bellard | case 0x0c: // Nucleus Little Endian (LE) |
1137 | 83469015 | bellard | case 0x11: // As if user secondary |
1138 | 83469015 | bellard | case 0x19: // As if user secondary LE |
1139 | 83469015 | bellard | case 0x24: // Nucleus quad LDD 128 bit atomic |
1140 | 83469015 | bellard | case 0x2c: // Nucleus quad LDD 128 bit atomic |
1141 | 83469015 | bellard | case 0x4a: // UPA config |
1142 | 51996525 | blueswir1 | case 0x81: // Secondary |
1143 | 83469015 | bellard | case 0x89: // Secondary LE |
1144 | 0f8a249a | blueswir1 | // XXX
|
1145 | 0f8a249a | blueswir1 | return;
|
1146 | 3475187d | bellard | case 0x45: // LSU |
1147 | 0f8a249a | blueswir1 | { |
1148 | 0f8a249a | blueswir1 | uint64_t oldreg; |
1149 | 0f8a249a | blueswir1 | |
1150 | 0f8a249a | blueswir1 | oldreg = env->lsu; |
1151 | 0f8a249a | blueswir1 | env->lsu = T1 & (DMMU_E | IMMU_E); |
1152 | 0f8a249a | blueswir1 | // Mappings generated during D/I MMU disabled mode are
|
1153 | 0f8a249a | blueswir1 | // invalid in normal mode
|
1154 | 0f8a249a | blueswir1 | if (oldreg != env->lsu) {
|
1155 | 952a328f | blueswir1 | DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); |
1156 | 83469015 | bellard | #ifdef DEBUG_MMU
|
1157 | 0f8a249a | blueswir1 | dump_mmu(env); |
1158 | 83469015 | bellard | #endif
|
1159 | 0f8a249a | blueswir1 | tlb_flush(env, 1);
|
1160 | 0f8a249a | blueswir1 | } |
1161 | 0f8a249a | blueswir1 | return;
|
1162 | 0f8a249a | blueswir1 | } |
1163 | 3475187d | bellard | case 0x50: // I-MMU regs |
1164 | 0f8a249a | blueswir1 | { |
1165 | 0f8a249a | blueswir1 | int reg = (T0 >> 3) & 0xf; |
1166 | 0f8a249a | blueswir1 | uint64_t oldreg; |
1167 | 3b46e624 | ths | |
1168 | 0f8a249a | blueswir1 | oldreg = env->immuregs[reg]; |
1169 | 3475187d | bellard | switch(reg) {
|
1170 | 3475187d | bellard | case 0: // RO |
1171 | 3475187d | bellard | case 4: |
1172 | 3475187d | bellard | return;
|
1173 | 3475187d | bellard | case 1: // Not in I-MMU |
1174 | 3475187d | bellard | case 2: |
1175 | 3475187d | bellard | case 7: |
1176 | 3475187d | bellard | case 8: |
1177 | 3475187d | bellard | return;
|
1178 | 3475187d | bellard | case 3: // SFSR |
1179 | 0f8a249a | blueswir1 | if ((T1 & 1) == 0) |
1180 | 0f8a249a | blueswir1 | T1 = 0; // Clear SFSR |
1181 | 3475187d | bellard | break;
|
1182 | 3475187d | bellard | case 5: // TSB access |
1183 | 3475187d | bellard | case 6: // Tag access |
1184 | 3475187d | bellard | default:
|
1185 | 3475187d | bellard | break;
|
1186 | 3475187d | bellard | } |
1187 | 0f8a249a | blueswir1 | env->immuregs[reg] = T1; |
1188 | 3475187d | bellard | if (oldreg != env->immuregs[reg]) {
|
1189 | 952a328f | blueswir1 | DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); |
1190 | 3475187d | bellard | } |
1191 | 952a328f | blueswir1 | #ifdef DEBUG_MMU
|
1192 | 0f8a249a | blueswir1 | dump_mmu(env); |
1193 | 3475187d | bellard | #endif
|
1194 | 0f8a249a | blueswir1 | return;
|
1195 | 0f8a249a | blueswir1 | } |
1196 | 3475187d | bellard | case 0x54: // I-MMU data in |
1197 | 0f8a249a | blueswir1 | { |
1198 | 0f8a249a | blueswir1 | unsigned int i; |
1199 | 0f8a249a | blueswir1 | |
1200 | 0f8a249a | blueswir1 | // Try finding an invalid entry
|
1201 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
1202 | 0f8a249a | blueswir1 | if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) { |
1203 | 0f8a249a | blueswir1 | env->itlb_tag[i] = env->immuregs[6];
|
1204 | 0f8a249a | blueswir1 | env->itlb_tte[i] = T1; |
1205 | 0f8a249a | blueswir1 | return;
|
1206 | 0f8a249a | blueswir1 | } |
1207 | 0f8a249a | blueswir1 | } |
1208 | 0f8a249a | blueswir1 | // Try finding an unlocked entry
|
1209 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
1210 | 0f8a249a | blueswir1 | if ((env->itlb_tte[i] & 0x40) == 0) { |
1211 | 0f8a249a | blueswir1 | env->itlb_tag[i] = env->immuregs[6];
|
1212 | 0f8a249a | blueswir1 | env->itlb_tte[i] = T1; |
1213 | 0f8a249a | blueswir1 | return;
|
1214 | 0f8a249a | blueswir1 | } |
1215 | 0f8a249a | blueswir1 | } |
1216 | 0f8a249a | blueswir1 | // error state?
|
1217 | 0f8a249a | blueswir1 | return;
|
1218 | 0f8a249a | blueswir1 | } |
1219 | 3475187d | bellard | case 0x55: // I-MMU data access |
1220 | 0f8a249a | blueswir1 | { |
1221 | 0f8a249a | blueswir1 | unsigned int i = (T0 >> 3) & 0x3f; |
1222 | 3475187d | bellard | |
1223 | 0f8a249a | blueswir1 | env->itlb_tag[i] = env->immuregs[6];
|
1224 | 0f8a249a | blueswir1 | env->itlb_tte[i] = T1; |
1225 | 0f8a249a | blueswir1 | return;
|
1226 | 0f8a249a | blueswir1 | } |
1227 | 3475187d | bellard | case 0x57: // I-MMU demap |
1228 | 0f8a249a | blueswir1 | // XXX
|
1229 | 0f8a249a | blueswir1 | return;
|
1230 | 3475187d | bellard | case 0x58: // D-MMU regs |
1231 | 0f8a249a | blueswir1 | { |
1232 | 0f8a249a | blueswir1 | int reg = (T0 >> 3) & 0xf; |
1233 | 0f8a249a | blueswir1 | uint64_t oldreg; |
1234 | 3b46e624 | ths | |
1235 | 0f8a249a | blueswir1 | oldreg = env->dmmuregs[reg]; |
1236 | 3475187d | bellard | switch(reg) {
|
1237 | 3475187d | bellard | case 0: // RO |
1238 | 3475187d | bellard | case 4: |
1239 | 3475187d | bellard | return;
|
1240 | 3475187d | bellard | case 3: // SFSR |
1241 | 0f8a249a | blueswir1 | if ((T1 & 1) == 0) { |
1242 | 0f8a249a | blueswir1 | T1 = 0; // Clear SFSR, Fault address |
1243 | 0f8a249a | blueswir1 | env->dmmuregs[4] = 0; |
1244 | 0f8a249a | blueswir1 | } |
1245 | 0f8a249a | blueswir1 | env->dmmuregs[reg] = T1; |
1246 | 3475187d | bellard | break;
|
1247 | 3475187d | bellard | case 1: // Primary context |
1248 | 3475187d | bellard | case 2: // Secondary context |
1249 | 3475187d | bellard | case 5: // TSB access |
1250 | 3475187d | bellard | case 6: // Tag access |
1251 | 3475187d | bellard | case 7: // Virtual Watchpoint |
1252 | 3475187d | bellard | case 8: // Physical Watchpoint |
1253 | 3475187d | bellard | default:
|
1254 | 3475187d | bellard | break;
|
1255 | 3475187d | bellard | } |
1256 | 0f8a249a | blueswir1 | env->dmmuregs[reg] = T1; |
1257 | 3475187d | bellard | if (oldreg != env->dmmuregs[reg]) {
|
1258 | 952a328f | blueswir1 | DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); |
1259 | 3475187d | bellard | } |
1260 | 952a328f | blueswir1 | #ifdef DEBUG_MMU
|
1261 | 0f8a249a | blueswir1 | dump_mmu(env); |
1262 | 3475187d | bellard | #endif
|
1263 | 0f8a249a | blueswir1 | return;
|
1264 | 0f8a249a | blueswir1 | } |
1265 | 3475187d | bellard | case 0x5c: // D-MMU data in |
1266 | 0f8a249a | blueswir1 | { |
1267 | 0f8a249a | blueswir1 | unsigned int i; |
1268 | 0f8a249a | blueswir1 | |
1269 | 0f8a249a | blueswir1 | // Try finding an invalid entry
|
1270 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
1271 | 0f8a249a | blueswir1 | if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) { |
1272 | 0f8a249a | blueswir1 | env->dtlb_tag[i] = env->dmmuregs[6];
|
1273 | 0f8a249a | blueswir1 | env->dtlb_tte[i] = T1; |
1274 | 0f8a249a | blueswir1 | return;
|
1275 | 0f8a249a | blueswir1 | } |
1276 | 0f8a249a | blueswir1 | } |
1277 | 0f8a249a | blueswir1 | // Try finding an unlocked entry
|
1278 | 0f8a249a | blueswir1 | for (i = 0; i < 64; i++) { |
1279 | 0f8a249a | blueswir1 | if ((env->dtlb_tte[i] & 0x40) == 0) { |
1280 | 0f8a249a | blueswir1 | env->dtlb_tag[i] = env->dmmuregs[6];
|
1281 | 0f8a249a | blueswir1 | env->dtlb_tte[i] = T1; |
1282 | 0f8a249a | blueswir1 | return;
|
1283 | 0f8a249a | blueswir1 | } |
1284 | 0f8a249a | blueswir1 | } |
1285 | 0f8a249a | blueswir1 | // error state?
|
1286 | 0f8a249a | blueswir1 | return;
|
1287 | 0f8a249a | blueswir1 | } |
1288 | 3475187d | bellard | case 0x5d: // D-MMU data access |
1289 | 0f8a249a | blueswir1 | { |
1290 | 0f8a249a | blueswir1 | unsigned int i = (T0 >> 3) & 0x3f; |
1291 | 3475187d | bellard | |
1292 | 0f8a249a | blueswir1 | env->dtlb_tag[i] = env->dmmuregs[6];
|
1293 | 0f8a249a | blueswir1 | env->dtlb_tte[i] = T1; |
1294 | 0f8a249a | blueswir1 | return;
|
1295 | 0f8a249a | blueswir1 | } |
1296 | 3475187d | bellard | case 0x5f: // D-MMU demap |
1297 | 83469015 | bellard | case 0x49: // Interrupt data receive |
1298 | 0f8a249a | blueswir1 | // XXX
|
1299 | 0f8a249a | blueswir1 | return;
|
1300 | 3475187d | bellard | case 0x51: // I-MMU 8k TSB pointer, RO |
1301 | 3475187d | bellard | case 0x52: // I-MMU 64k TSB pointer, RO |
1302 | 3475187d | bellard | case 0x56: // I-MMU tag read, RO |
1303 | 3475187d | bellard | case 0x59: // D-MMU 8k TSB pointer, RO |
1304 | 3475187d | bellard | case 0x5a: // D-MMU 64k TSB pointer, RO |
1305 | 3475187d | bellard | case 0x5b: // D-MMU data pointer, RO |
1306 | 3475187d | bellard | case 0x5e: // D-MMU tag read, RO |
1307 | 83469015 | bellard | case 0x48: // Interrupt dispatch, RO |
1308 | 83469015 | bellard | case 0x7f: // Incoming interrupt vector, RO |
1309 | 83469015 | bellard | case 0x82: // Primary no-fault, RO |
1310 | 83469015 | bellard | case 0x83: // Secondary no-fault, RO |
1311 | 83469015 | bellard | case 0x8a: // Primary no-fault LE, RO |
1312 | 83469015 | bellard | case 0x8b: // Secondary no-fault LE, RO |
1313 | 3475187d | bellard | default:
|
1314 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 1, 0, 1); |
1315 | 0f8a249a | blueswir1 | return;
|
1316 | 3475187d | bellard | } |
1317 | 3475187d | bellard | } |
1318 | 81ad8ba2 | blueswir1 | #endif /* CONFIG_USER_ONLY */ |
1319 | 3391c818 | blueswir1 | |
1320 | 3391c818 | blueswir1 | void helper_ldf_asi(int asi, int size, int rd) |
1321 | 3391c818 | blueswir1 | { |
1322 | 3391c818 | blueswir1 | target_ulong tmp_T0 = T0, tmp_T1 = T1; |
1323 | 3391c818 | blueswir1 | unsigned int i; |
1324 | 3391c818 | blueswir1 | |
1325 | 3391c818 | blueswir1 | switch (asi) {
|
1326 | 3391c818 | blueswir1 | case 0xf0: // Block load primary |
1327 | 3391c818 | blueswir1 | case 0xf1: // Block load secondary |
1328 | 3391c818 | blueswir1 | case 0xf8: // Block load primary LE |
1329 | 3391c818 | blueswir1 | case 0xf9: // Block load secondary LE |
1330 | 51996525 | blueswir1 | if (rd & 7) { |
1331 | 51996525 | blueswir1 | raise_exception(TT_ILL_INSN); |
1332 | 51996525 | blueswir1 | return;
|
1333 | 51996525 | blueswir1 | } |
1334 | 51996525 | blueswir1 | if (T0 & 0x3f) { |
1335 | 51996525 | blueswir1 | raise_exception(TT_UNALIGNED); |
1336 | 51996525 | blueswir1 | return;
|
1337 | 51996525 | blueswir1 | } |
1338 | 51996525 | blueswir1 | for (i = 0; i < 16; i++) { |
1339 | 51996525 | blueswir1 | helper_ld_asi(asi & 0x8f, 4, 0); |
1340 | 51996525 | blueswir1 | *(uint32_t *)&env->fpr[rd++] = T1; |
1341 | 51996525 | blueswir1 | T0 += 4;
|
1342 | 3391c818 | blueswir1 | } |
1343 | 3391c818 | blueswir1 | T0 = tmp_T0; |
1344 | 3391c818 | blueswir1 | T1 = tmp_T1; |
1345 | 3391c818 | blueswir1 | |
1346 | 3391c818 | blueswir1 | return;
|
1347 | 3391c818 | blueswir1 | default:
|
1348 | 3391c818 | blueswir1 | break;
|
1349 | 3391c818 | blueswir1 | } |
1350 | 3391c818 | blueswir1 | |
1351 | 3391c818 | blueswir1 | helper_ld_asi(asi, size, 0);
|
1352 | 3391c818 | blueswir1 | switch(size) {
|
1353 | 3391c818 | blueswir1 | default:
|
1354 | 3391c818 | blueswir1 | case 4: |
1355 | 3391c818 | blueswir1 | *((uint32_t *)&FT0) = T1; |
1356 | 3391c818 | blueswir1 | break;
|
1357 | 3391c818 | blueswir1 | case 8: |
1358 | 3391c818 | blueswir1 | *((int64_t *)&DT0) = T1; |
1359 | 3391c818 | blueswir1 | break;
|
1360 | 3391c818 | blueswir1 | } |
1361 | 3391c818 | blueswir1 | T1 = tmp_T1; |
1362 | 3391c818 | blueswir1 | } |
1363 | 3391c818 | blueswir1 | |
1364 | 3391c818 | blueswir1 | void helper_stf_asi(int asi, int size, int rd) |
1365 | 3391c818 | blueswir1 | { |
1366 | 3391c818 | blueswir1 | target_ulong tmp_T0 = T0, tmp_T1 = T1; |
1367 | 3391c818 | blueswir1 | unsigned int i; |
1368 | 3391c818 | blueswir1 | |
1369 | 3391c818 | blueswir1 | switch (asi) {
|
1370 | 3391c818 | blueswir1 | case 0xf0: // Block store primary |
1371 | 3391c818 | blueswir1 | case 0xf1: // Block store secondary |
1372 | 3391c818 | blueswir1 | case 0xf8: // Block store primary LE |
1373 | 3391c818 | blueswir1 | case 0xf9: // Block store secondary LE |
1374 | 51996525 | blueswir1 | if (rd & 7) { |
1375 | 51996525 | blueswir1 | raise_exception(TT_ILL_INSN); |
1376 | 51996525 | blueswir1 | return;
|
1377 | 51996525 | blueswir1 | } |
1378 | 51996525 | blueswir1 | if (T0 & 0x3f) { |
1379 | 51996525 | blueswir1 | raise_exception(TT_UNALIGNED); |
1380 | 51996525 | blueswir1 | return;
|
1381 | 51996525 | blueswir1 | } |
1382 | 51996525 | blueswir1 | for (i = 0; i < 16; i++) { |
1383 | 51996525 | blueswir1 | T1 = *(uint32_t *)&env->fpr[rd++]; |
1384 | 51996525 | blueswir1 | helper_st_asi(asi & 0x8f, 4); |
1385 | 51996525 | blueswir1 | T0 += 4;
|
1386 | 3391c818 | blueswir1 | } |
1387 | 3391c818 | blueswir1 | T0 = tmp_T0; |
1388 | 3391c818 | blueswir1 | T1 = tmp_T1; |
1389 | 3391c818 | blueswir1 | |
1390 | 3391c818 | blueswir1 | return;
|
1391 | 3391c818 | blueswir1 | default:
|
1392 | 3391c818 | blueswir1 | break;
|
1393 | 3391c818 | blueswir1 | } |
1394 | 3391c818 | blueswir1 | |
1395 | 3391c818 | blueswir1 | switch(size) {
|
1396 | 3391c818 | blueswir1 | default:
|
1397 | 3391c818 | blueswir1 | case 4: |
1398 | 3391c818 | blueswir1 | T1 = *((uint32_t *)&FT0); |
1399 | 3391c818 | blueswir1 | break;
|
1400 | 3391c818 | blueswir1 | case 8: |
1401 | 3391c818 | blueswir1 | T1 = *((int64_t *)&DT0); |
1402 | 3391c818 | blueswir1 | break;
|
1403 | 3391c818 | blueswir1 | } |
1404 | 3391c818 | blueswir1 | helper_st_asi(asi, size); |
1405 | 3391c818 | blueswir1 | T1 = tmp_T1; |
1406 | 3391c818 | blueswir1 | } |
1407 | 3391c818 | blueswir1 | |
1408 | 81ad8ba2 | blueswir1 | #endif /* TARGET_SPARC64 */ |
1409 | 3475187d | bellard | |
1410 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
1411 | a0c4cb4a | bellard | void helper_rett()
|
1412 | e8af50a3 | bellard | { |
1413 | af7bf89b | bellard | unsigned int cwp; |
1414 | af7bf89b | bellard | |
1415 | d4218d99 | blueswir1 | if (env->psret == 1) |
1416 | d4218d99 | blueswir1 | raise_exception(TT_ILL_INSN); |
1417 | d4218d99 | blueswir1 | |
1418 | e8af50a3 | bellard | env->psret = 1;
|
1419 | 5fafdf24 | ths | cwp = (env->cwp + 1) & (NWINDOWS - 1); |
1420 | e8af50a3 | bellard | if (env->wim & (1 << cwp)) { |
1421 | e8af50a3 | bellard | raise_exception(TT_WIN_UNF); |
1422 | e8af50a3 | bellard | } |
1423 | e8af50a3 | bellard | set_cwp(cwp); |
1424 | e8af50a3 | bellard | env->psrs = env->psrps; |
1425 | e8af50a3 | bellard | } |
1426 | 3475187d | bellard | #endif
|
1427 | e8af50a3 | bellard | |
1428 | 8d5f07fa | bellard | void helper_ldfsr(void) |
1429 | e8af50a3 | bellard | { |
1430 | 7a0e1f41 | bellard | int rnd_mode;
|
1431 | e8af50a3 | bellard | switch (env->fsr & FSR_RD_MASK) {
|
1432 | e8af50a3 | bellard | case FSR_RD_NEAREST:
|
1433 | 7a0e1f41 | bellard | rnd_mode = float_round_nearest_even; |
1434 | 0f8a249a | blueswir1 | break;
|
1435 | ed910241 | bellard | default:
|
1436 | e8af50a3 | bellard | case FSR_RD_ZERO:
|
1437 | 7a0e1f41 | bellard | rnd_mode = float_round_to_zero; |
1438 | 0f8a249a | blueswir1 | break;
|
1439 | e8af50a3 | bellard | case FSR_RD_POS:
|
1440 | 7a0e1f41 | bellard | rnd_mode = float_round_up; |
1441 | 0f8a249a | blueswir1 | break;
|
1442 | e8af50a3 | bellard | case FSR_RD_NEG:
|
1443 | 7a0e1f41 | bellard | rnd_mode = float_round_down; |
1444 | 0f8a249a | blueswir1 | break;
|
1445 | e8af50a3 | bellard | } |
1446 | 7a0e1f41 | bellard | set_float_rounding_mode(rnd_mode, &env->fp_status); |
1447 | e8af50a3 | bellard | } |
1448 | e80cfcfc | bellard | |
1449 | e80cfcfc | bellard | void helper_debug()
|
1450 | e80cfcfc | bellard | { |
1451 | e80cfcfc | bellard | env->exception_index = EXCP_DEBUG; |
1452 | e80cfcfc | bellard | cpu_loop_exit(); |
1453 | e80cfcfc | bellard | } |
1454 | af7bf89b | bellard | |
1455 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
1456 | af7bf89b | bellard | void do_wrpsr()
|
1457 | af7bf89b | bellard | { |
1458 | d4218d99 | blueswir1 | if ((T0 & PSR_CWP) >= NWINDOWS)
|
1459 | d4218d99 | blueswir1 | raise_exception(TT_ILL_INSN); |
1460 | d4218d99 | blueswir1 | else
|
1461 | d4218d99 | blueswir1 | PUT_PSR(env, T0); |
1462 | af7bf89b | bellard | } |
1463 | af7bf89b | bellard | |
1464 | af7bf89b | bellard | void do_rdpsr()
|
1465 | af7bf89b | bellard | { |
1466 | af7bf89b | bellard | T0 = GET_PSR(env); |
1467 | af7bf89b | bellard | } |
1468 | 3475187d | bellard | |
1469 | 3475187d | bellard | #else
|
1470 | 3475187d | bellard | |
1471 | 3475187d | bellard | void do_popc()
|
1472 | 3475187d | bellard | { |
1473 | eed152bb | blueswir1 | T0 = ctpop64(T1); |
1474 | 3475187d | bellard | } |
1475 | 83469015 | bellard | |
1476 | 83469015 | bellard | static inline uint64_t *get_gregset(uint64_t pstate) |
1477 | 83469015 | bellard | { |
1478 | 83469015 | bellard | switch (pstate) {
|
1479 | 83469015 | bellard | default:
|
1480 | 83469015 | bellard | case 0: |
1481 | 0f8a249a | blueswir1 | return env->bgregs;
|
1482 | 83469015 | bellard | case PS_AG:
|
1483 | 0f8a249a | blueswir1 | return env->agregs;
|
1484 | 83469015 | bellard | case PS_MG:
|
1485 | 0f8a249a | blueswir1 | return env->mgregs;
|
1486 | 83469015 | bellard | case PS_IG:
|
1487 | 0f8a249a | blueswir1 | return env->igregs;
|
1488 | 83469015 | bellard | } |
1489 | 83469015 | bellard | } |
1490 | 83469015 | bellard | |
1491 | 8f1f22f6 | blueswir1 | static inline void change_pstate(uint64_t new_pstate) |
1492 | 83469015 | bellard | { |
1493 | 8f1f22f6 | blueswir1 | uint64_t pstate_regs, new_pstate_regs; |
1494 | 83469015 | bellard | uint64_t *src, *dst; |
1495 | 83469015 | bellard | |
1496 | 83469015 | bellard | pstate_regs = env->pstate & 0xc01;
|
1497 | 83469015 | bellard | new_pstate_regs = new_pstate & 0xc01;
|
1498 | 83469015 | bellard | if (new_pstate_regs != pstate_regs) {
|
1499 | 0f8a249a | blueswir1 | // Switch global register bank
|
1500 | 0f8a249a | blueswir1 | src = get_gregset(new_pstate_regs); |
1501 | 0f8a249a | blueswir1 | dst = get_gregset(pstate_regs); |
1502 | 0f8a249a | blueswir1 | memcpy32(dst, env->gregs); |
1503 | 0f8a249a | blueswir1 | memcpy32(env->gregs, src); |
1504 | 83469015 | bellard | } |
1505 | 83469015 | bellard | env->pstate = new_pstate; |
1506 | 83469015 | bellard | } |
1507 | 83469015 | bellard | |
1508 | 8f1f22f6 | blueswir1 | void do_wrpstate(void) |
1509 | 8f1f22f6 | blueswir1 | { |
1510 | 8f1f22f6 | blueswir1 | change_pstate(T0 & 0xf3f);
|
1511 | 8f1f22f6 | blueswir1 | } |
1512 | 8f1f22f6 | blueswir1 | |
1513 | 83469015 | bellard | void do_done(void) |
1514 | 83469015 | bellard | { |
1515 | 83469015 | bellard | env->tl--; |
1516 | 83469015 | bellard | env->pc = env->tnpc[env->tl]; |
1517 | 83469015 | bellard | env->npc = env->tnpc[env->tl] + 4;
|
1518 | 83469015 | bellard | PUT_CCR(env, env->tstate[env->tl] >> 32);
|
1519 | 83469015 | bellard | env->asi = (env->tstate[env->tl] >> 24) & 0xff; |
1520 | 8f1f22f6 | blueswir1 | change_pstate((env->tstate[env->tl] >> 8) & 0xf3f); |
1521 | 17d996e1 | blueswir1 | PUT_CWP64(env, env->tstate[env->tl] & 0xff);
|
1522 | 83469015 | bellard | } |
1523 | 83469015 | bellard | |
1524 | 83469015 | bellard | void do_retry(void) |
1525 | 83469015 | bellard | { |
1526 | 83469015 | bellard | env->tl--; |
1527 | 83469015 | bellard | env->pc = env->tpc[env->tl]; |
1528 | 83469015 | bellard | env->npc = env->tnpc[env->tl]; |
1529 | 83469015 | bellard | PUT_CCR(env, env->tstate[env->tl] >> 32);
|
1530 | 83469015 | bellard | env->asi = (env->tstate[env->tl] >> 24) & 0xff; |
1531 | 8f1f22f6 | blueswir1 | change_pstate((env->tstate[env->tl] >> 8) & 0xf3f); |
1532 | 17d996e1 | blueswir1 | PUT_CWP64(env, env->tstate[env->tl] & 0xff);
|
1533 | 83469015 | bellard | } |
1534 | 3475187d | bellard | #endif
|
1535 | ee5bbe38 | bellard | |
1536 | ee5bbe38 | bellard | void set_cwp(int new_cwp) |
1537 | ee5bbe38 | bellard | { |
1538 | ee5bbe38 | bellard | /* put the modified wrap registers at their proper location */
|
1539 | ee5bbe38 | bellard | if (env->cwp == (NWINDOWS - 1)) |
1540 | ee5bbe38 | bellard | memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
|
1541 | ee5bbe38 | bellard | env->cwp = new_cwp; |
1542 | ee5bbe38 | bellard | /* put the wrap registers at their temporary location */
|
1543 | ee5bbe38 | bellard | if (new_cwp == (NWINDOWS - 1)) |
1544 | ee5bbe38 | bellard | memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
|
1545 | ee5bbe38 | bellard | env->regwptr = env->regbase + (new_cwp * 16);
|
1546 | ee5bbe38 | bellard | REGWPTR = env->regwptr; |
1547 | ee5bbe38 | bellard | } |
1548 | ee5bbe38 | bellard | |
1549 | ee5bbe38 | bellard | void cpu_set_cwp(CPUState *env1, int new_cwp) |
1550 | ee5bbe38 | bellard | { |
1551 | ee5bbe38 | bellard | CPUState *saved_env; |
1552 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
1553 | ee5bbe38 | bellard | target_ulong *saved_regwptr; |
1554 | ee5bbe38 | bellard | #endif
|
1555 | ee5bbe38 | bellard | |
1556 | ee5bbe38 | bellard | saved_env = env; |
1557 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
1558 | ee5bbe38 | bellard | saved_regwptr = REGWPTR; |
1559 | ee5bbe38 | bellard | #endif
|
1560 | ee5bbe38 | bellard | env = env1; |
1561 | ee5bbe38 | bellard | set_cwp(new_cwp); |
1562 | ee5bbe38 | bellard | env = saved_env; |
1563 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
1564 | ee5bbe38 | bellard | REGWPTR = saved_regwptr; |
1565 | ee5bbe38 | bellard | #endif
|
1566 | ee5bbe38 | bellard | } |
1567 | ee5bbe38 | bellard | |
1568 | ee5bbe38 | bellard | #ifdef TARGET_SPARC64
|
1569 | ee5bbe38 | bellard | void do_interrupt(int intno) |
1570 | ee5bbe38 | bellard | { |
1571 | ee5bbe38 | bellard | #ifdef DEBUG_PCALL
|
1572 | ee5bbe38 | bellard | if (loglevel & CPU_LOG_INT) {
|
1573 | 0f8a249a | blueswir1 | static int count; |
1574 | 0f8a249a | blueswir1 | fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n", |
1575 | ee5bbe38 | bellard | count, intno, |
1576 | ee5bbe38 | bellard | env->pc, |
1577 | ee5bbe38 | bellard | env->npc, env->regwptr[6]);
|
1578 | 0f8a249a | blueswir1 | cpu_dump_state(env, logfile, fprintf, 0);
|
1579 | ee5bbe38 | bellard | #if 0
|
1580 | 0f8a249a | blueswir1 | {
|
1581 | 0f8a249a | blueswir1 | int i;
|
1582 | 0f8a249a | blueswir1 | uint8_t *ptr;
|
1583 | 0f8a249a | blueswir1 | |
1584 | 0f8a249a | blueswir1 | fprintf(logfile, " code=");
|
1585 | 0f8a249a | blueswir1 | ptr = (uint8_t *)env->pc;
|
1586 | 0f8a249a | blueswir1 | for(i = 0; i < 16; i++) {
|
1587 | 0f8a249a | blueswir1 | fprintf(logfile, " %02x", ldub(ptr + i));
|
1588 | 0f8a249a | blueswir1 | }
|
1589 | 0f8a249a | blueswir1 | fprintf(logfile, "\n");
|
1590 | 0f8a249a | blueswir1 | }
|
1591 | ee5bbe38 | bellard | #endif
|
1592 | 0f8a249a | blueswir1 | count++; |
1593 | ee5bbe38 | bellard | } |
1594 | ee5bbe38 | bellard | #endif
|
1595 | 5fafdf24 | ths | #if !defined(CONFIG_USER_ONLY)
|
1596 | 83469015 | bellard | if (env->tl == MAXTL) {
|
1597 | c68ea704 | bellard | cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
|
1598 | 0f8a249a | blueswir1 | return;
|
1599 | ee5bbe38 | bellard | } |
1600 | ee5bbe38 | bellard | #endif
|
1601 | ee5bbe38 | bellard | env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | |
1602 | 0f8a249a | blueswir1 | ((env->pstate & 0xf3f) << 8) | GET_CWP64(env); |
1603 | ee5bbe38 | bellard | env->tpc[env->tl] = env->pc; |
1604 | ee5bbe38 | bellard | env->tnpc[env->tl] = env->npc; |
1605 | ee5bbe38 | bellard | env->tt[env->tl] = intno; |
1606 | 8f1f22f6 | blueswir1 | change_pstate(PS_PEF | PS_PRIV | PS_AG); |
1607 | 8f1f22f6 | blueswir1 | |
1608 | 8f1f22f6 | blueswir1 | if (intno == TT_CLRWIN)
|
1609 | 8f1f22f6 | blueswir1 | set_cwp((env->cwp - 1) & (NWINDOWS - 1)); |
1610 | 8f1f22f6 | blueswir1 | else if ((intno & 0x1c0) == TT_SPILL) |
1611 | 8f1f22f6 | blueswir1 | set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1)); |
1612 | 8f1f22f6 | blueswir1 | else if ((intno & 0x1c0) == TT_FILL) |
1613 | 8f1f22f6 | blueswir1 | set_cwp((env->cwp + 1) & (NWINDOWS - 1)); |
1614 | 83469015 | bellard | env->tbr &= ~0x7fffULL;
|
1615 | 83469015 | bellard | env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); |
1616 | 83469015 | bellard | if (env->tl < MAXTL - 1) { |
1617 | 0f8a249a | blueswir1 | env->tl++; |
1618 | 83469015 | bellard | } else {
|
1619 | 0f8a249a | blueswir1 | env->pstate |= PS_RED; |
1620 | 0f8a249a | blueswir1 | if (env->tl != MAXTL)
|
1621 | 0f8a249a | blueswir1 | env->tl++; |
1622 | 83469015 | bellard | } |
1623 | ee5bbe38 | bellard | env->pc = env->tbr; |
1624 | ee5bbe38 | bellard | env->npc = env->pc + 4;
|
1625 | ee5bbe38 | bellard | env->exception_index = 0;
|
1626 | ee5bbe38 | bellard | } |
1627 | ee5bbe38 | bellard | #else
|
1628 | ee5bbe38 | bellard | void do_interrupt(int intno) |
1629 | ee5bbe38 | bellard | { |
1630 | ee5bbe38 | bellard | int cwp;
|
1631 | ee5bbe38 | bellard | |
1632 | ee5bbe38 | bellard | #ifdef DEBUG_PCALL
|
1633 | ee5bbe38 | bellard | if (loglevel & CPU_LOG_INT) {
|
1634 | 0f8a249a | blueswir1 | static int count; |
1635 | 0f8a249a | blueswir1 | fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
|
1636 | ee5bbe38 | bellard | count, intno, |
1637 | ee5bbe38 | bellard | env->pc, |
1638 | ee5bbe38 | bellard | env->npc, env->regwptr[6]);
|
1639 | 0f8a249a | blueswir1 | cpu_dump_state(env, logfile, fprintf, 0);
|
1640 | ee5bbe38 | bellard | #if 0
|
1641 | 0f8a249a | blueswir1 | {
|
1642 | 0f8a249a | blueswir1 | int i;
|
1643 | 0f8a249a | blueswir1 | uint8_t *ptr;
|
1644 | 0f8a249a | blueswir1 | |
1645 | 0f8a249a | blueswir1 | fprintf(logfile, " code=");
|
1646 | 0f8a249a | blueswir1 | ptr = (uint8_t *)env->pc;
|
1647 | 0f8a249a | blueswir1 | for(i = 0; i < 16; i++) {
|
1648 | 0f8a249a | blueswir1 | fprintf(logfile, " %02x", ldub(ptr + i));
|
1649 | 0f8a249a | blueswir1 | }
|
1650 | 0f8a249a | blueswir1 | fprintf(logfile, "\n");
|
1651 | 0f8a249a | blueswir1 | }
|
1652 | ee5bbe38 | bellard | #endif
|
1653 | 0f8a249a | blueswir1 | count++; |
1654 | ee5bbe38 | bellard | } |
1655 | ee5bbe38 | bellard | #endif
|
1656 | 5fafdf24 | ths | #if !defined(CONFIG_USER_ONLY)
|
1657 | ee5bbe38 | bellard | if (env->psret == 0) { |
1658 | c68ea704 | bellard | cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
|
1659 | 0f8a249a | blueswir1 | return;
|
1660 | ee5bbe38 | bellard | } |
1661 | ee5bbe38 | bellard | #endif
|
1662 | ee5bbe38 | bellard | env->psret = 0;
|
1663 | 5fafdf24 | ths | cwp = (env->cwp - 1) & (NWINDOWS - 1); |
1664 | ee5bbe38 | bellard | set_cwp(cwp); |
1665 | ee5bbe38 | bellard | env->regwptr[9] = env->pc;
|
1666 | ee5bbe38 | bellard | env->regwptr[10] = env->npc;
|
1667 | ee5bbe38 | bellard | env->psrps = env->psrs; |
1668 | ee5bbe38 | bellard | env->psrs = 1;
|
1669 | ee5bbe38 | bellard | env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
|
1670 | ee5bbe38 | bellard | env->pc = env->tbr; |
1671 | ee5bbe38 | bellard | env->npc = env->pc + 4;
|
1672 | ee5bbe38 | bellard | env->exception_index = 0;
|
1673 | ee5bbe38 | bellard | } |
1674 | ee5bbe38 | bellard | #endif
|
1675 | ee5bbe38 | bellard | |
1676 | 5fafdf24 | ths | #if !defined(CONFIG_USER_ONLY)
|
1677 | ee5bbe38 | bellard | |
1678 | d2889a3e | blueswir1 | static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
1679 | d2889a3e | blueswir1 | void *retaddr);
|
1680 | d2889a3e | blueswir1 | |
1681 | ee5bbe38 | bellard | #define MMUSUFFIX _mmu
|
1682 | d2889a3e | blueswir1 | #define ALIGNED_ONLY
|
1683 | ee5bbe38 | bellard | #define GETPC() (__builtin_return_address(0)) |
1684 | ee5bbe38 | bellard | |
1685 | ee5bbe38 | bellard | #define SHIFT 0 |
1686 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1687 | ee5bbe38 | bellard | |
1688 | ee5bbe38 | bellard | #define SHIFT 1 |
1689 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1690 | ee5bbe38 | bellard | |
1691 | ee5bbe38 | bellard | #define SHIFT 2 |
1692 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1693 | ee5bbe38 | bellard | |
1694 | ee5bbe38 | bellard | #define SHIFT 3 |
1695 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1696 | ee5bbe38 | bellard | |
1697 | d2889a3e | blueswir1 | static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
1698 | d2889a3e | blueswir1 | void *retaddr)
|
1699 | d2889a3e | blueswir1 | { |
1700 | 94554550 | blueswir1 | #ifdef DEBUG_UNALIGNED
|
1701 | 94554550 | blueswir1 | printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
|
1702 | 94554550 | blueswir1 | #endif
|
1703 | 94554550 | blueswir1 | raise_exception(TT_UNALIGNED); |
1704 | d2889a3e | blueswir1 | } |
1705 | ee5bbe38 | bellard | |
1706 | ee5bbe38 | bellard | /* try to fill the TLB and return an exception if error. If retaddr is
|
1707 | ee5bbe38 | bellard | NULL, it means that the function was called in C code (i.e. not
|
1708 | ee5bbe38 | bellard | from generated code or from helper.c) */
|
1709 | ee5bbe38 | bellard | /* XXX: fix it to restore all registers */
|
1710 | 6ebbf390 | j_mayer | void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
1711 | ee5bbe38 | bellard | { |
1712 | ee5bbe38 | bellard | TranslationBlock *tb; |
1713 | ee5bbe38 | bellard | int ret;
|
1714 | ee5bbe38 | bellard | unsigned long pc; |
1715 | ee5bbe38 | bellard | CPUState *saved_env; |
1716 | ee5bbe38 | bellard | |
1717 | ee5bbe38 | bellard | /* XXX: hack to restore env in all cases, even if not called from
|
1718 | ee5bbe38 | bellard | generated code */
|
1719 | ee5bbe38 | bellard | saved_env = env; |
1720 | ee5bbe38 | bellard | env = cpu_single_env; |
1721 | ee5bbe38 | bellard | |
1722 | 6ebbf390 | j_mayer | ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
|
1723 | ee5bbe38 | bellard | if (ret) {
|
1724 | ee5bbe38 | bellard | if (retaddr) {
|
1725 | ee5bbe38 | bellard | /* now we have a real cpu fault */
|
1726 | ee5bbe38 | bellard | pc = (unsigned long)retaddr; |
1727 | ee5bbe38 | bellard | tb = tb_find_pc(pc); |
1728 | ee5bbe38 | bellard | if (tb) {
|
1729 | ee5bbe38 | bellard | /* the PC is inside the translated code. It means that we have
|
1730 | ee5bbe38 | bellard | a virtual CPU fault */
|
1731 | ee5bbe38 | bellard | cpu_restore_state(tb, env, pc, (void *)T2);
|
1732 | ee5bbe38 | bellard | } |
1733 | ee5bbe38 | bellard | } |
1734 | ee5bbe38 | bellard | cpu_loop_exit(); |
1735 | ee5bbe38 | bellard | } |
1736 | ee5bbe38 | bellard | env = saved_env; |
1737 | ee5bbe38 | bellard | } |
1738 | ee5bbe38 | bellard | |
1739 | ee5bbe38 | bellard | #endif
|
1740 | 6c36d3fa | blueswir1 | |
1741 | 6c36d3fa | blueswir1 | #ifndef TARGET_SPARC64
|
1742 | 5dcb6b91 | blueswir1 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
1743 | 6c36d3fa | blueswir1 | int is_asi)
|
1744 | 6c36d3fa | blueswir1 | { |
1745 | 6c36d3fa | blueswir1 | CPUState *saved_env; |
1746 | 6c36d3fa | blueswir1 | |
1747 | 6c36d3fa | blueswir1 | /* XXX: hack to restore env in all cases, even if not called from
|
1748 | 6c36d3fa | blueswir1 | generated code */
|
1749 | 6c36d3fa | blueswir1 | saved_env = env; |
1750 | 6c36d3fa | blueswir1 | env = cpu_single_env; |
1751 | 6c36d3fa | blueswir1 | if (env->mmuregs[3]) /* Fault status register */ |
1752 | 0f8a249a | blueswir1 | env->mmuregs[3] = 1; /* overflow (not read before another fault) */ |
1753 | 6c36d3fa | blueswir1 | if (is_asi)
|
1754 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 16; |
1755 | 6c36d3fa | blueswir1 | if (env->psrs)
|
1756 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 5; |
1757 | 6c36d3fa | blueswir1 | if (is_exec)
|
1758 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 6; |
1759 | 6c36d3fa | blueswir1 | if (is_write)
|
1760 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 7; |
1761 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= (5 << 2) | 2; |
1762 | 6c36d3fa | blueswir1 | env->mmuregs[4] = addr; /* Fault address register */ |
1763 | 6c36d3fa | blueswir1 | if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { |
1764 | 6c36d3fa | blueswir1 | #ifdef DEBUG_UNASSIGNED
|
1765 | 5dcb6b91 | blueswir1 | printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx |
1766 | 6c36d3fa | blueswir1 | "\n", addr, env->pc);
|
1767 | 6c36d3fa | blueswir1 | #endif
|
1768 | 1b2e93c1 | blueswir1 | if (is_exec)
|
1769 | 1b2e93c1 | blueswir1 | raise_exception(TT_CODE_ACCESS); |
1770 | 1b2e93c1 | blueswir1 | else
|
1771 | 1b2e93c1 | blueswir1 | raise_exception(TT_DATA_ACCESS); |
1772 | 6c36d3fa | blueswir1 | } |
1773 | 6c36d3fa | blueswir1 | env = saved_env; |
1774 | 6c36d3fa | blueswir1 | } |
1775 | 6c36d3fa | blueswir1 | #else
|
1776 | 5dcb6b91 | blueswir1 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
1777 | 6c36d3fa | blueswir1 | int is_asi)
|
1778 | 6c36d3fa | blueswir1 | { |
1779 | 6c36d3fa | blueswir1 | #ifdef DEBUG_UNASSIGNED
|
1780 | 6c36d3fa | blueswir1 | CPUState *saved_env; |
1781 | 6c36d3fa | blueswir1 | |
1782 | 6c36d3fa | blueswir1 | /* XXX: hack to restore env in all cases, even if not called from
|
1783 | 6c36d3fa | blueswir1 | generated code */
|
1784 | 6c36d3fa | blueswir1 | saved_env = env; |
1785 | 6c36d3fa | blueswir1 | env = cpu_single_env; |
1786 | 5dcb6b91 | blueswir1 | printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n", |
1787 | 6c36d3fa | blueswir1 | addr, env->pc); |
1788 | 6c36d3fa | blueswir1 | env = saved_env; |
1789 | 6c36d3fa | blueswir1 | #endif
|
1790 | 1b2e93c1 | blueswir1 | if (is_exec)
|
1791 | 1b2e93c1 | blueswir1 | raise_exception(TT_CODE_ACCESS); |
1792 | 1b2e93c1 | blueswir1 | else
|
1793 | 1b2e93c1 | blueswir1 | raise_exception(TT_DATA_ACCESS); |
1794 | 6c36d3fa | blueswir1 | } |
1795 | 6c36d3fa | blueswir1 | #endif
|
1796 | 20c9f095 | blueswir1 | |
1797 | 20c9f095 | blueswir1 | #ifdef TARGET_SPARC64
|
1798 | 20c9f095 | blueswir1 | void do_tick_set_count(void *opaque, uint64_t count) |
1799 | 20c9f095 | blueswir1 | { |
1800 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1801 | 20c9f095 | blueswir1 | ptimer_set_count(opaque, -count); |
1802 | d8bdf5fa | blueswir1 | #endif
|
1803 | 20c9f095 | blueswir1 | } |
1804 | 20c9f095 | blueswir1 | |
1805 | 20c9f095 | blueswir1 | uint64_t do_tick_get_count(void *opaque)
|
1806 | 20c9f095 | blueswir1 | { |
1807 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1808 | 20c9f095 | blueswir1 | return -ptimer_get_count(opaque);
|
1809 | d8bdf5fa | blueswir1 | #else
|
1810 | d8bdf5fa | blueswir1 | return 0; |
1811 | d8bdf5fa | blueswir1 | #endif
|
1812 | 20c9f095 | blueswir1 | } |
1813 | 20c9f095 | blueswir1 | |
1814 | 20c9f095 | blueswir1 | void do_tick_set_limit(void *opaque, uint64_t limit) |
1815 | 20c9f095 | blueswir1 | { |
1816 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1817 | 20c9f095 | blueswir1 | ptimer_set_limit(opaque, -limit, 0);
|
1818 | d8bdf5fa | blueswir1 | #endif
|
1819 | 20c9f095 | blueswir1 | } |
1820 | 20c9f095 | blueswir1 | #endif |