root / target-sparc / op_helper.c @ 17d996e1
History | View | Annotate | Download (29.7 kB)
1 | e8af50a3 | bellard | #include "exec.h" |
---|---|---|---|
2 | e8af50a3 | bellard | |
3 | 83469015 | bellard | //#define DEBUG_PCALL
|
4 | e80cfcfc | bellard | //#define DEBUG_MMU
|
5 | 94554550 | blueswir1 | //#define DEBUG_UNALIGNED
|
6 | 6c36d3fa | blueswir1 | //#define DEBUG_UNASSIGNED
|
7 | e80cfcfc | bellard | |
8 | 9d893301 | bellard | void raise_exception(int tt) |
9 | 9d893301 | bellard | { |
10 | 9d893301 | bellard | env->exception_index = tt; |
11 | 9d893301 | bellard | cpu_loop_exit(); |
12 | 9d893301 | bellard | } |
13 | 9d893301 | bellard | |
14 | 417454b0 | blueswir1 | void check_ieee_exceptions()
|
15 | 417454b0 | blueswir1 | { |
16 | 417454b0 | blueswir1 | T0 = get_float_exception_flags(&env->fp_status); |
17 | 417454b0 | blueswir1 | if (T0)
|
18 | 417454b0 | blueswir1 | { |
19 | 417454b0 | blueswir1 | /* Copy IEEE 754 flags into FSR */
|
20 | 417454b0 | blueswir1 | if (T0 & float_flag_invalid)
|
21 | 417454b0 | blueswir1 | env->fsr |= FSR_NVC; |
22 | 417454b0 | blueswir1 | if (T0 & float_flag_overflow)
|
23 | 417454b0 | blueswir1 | env->fsr |= FSR_OFC; |
24 | 417454b0 | blueswir1 | if (T0 & float_flag_underflow)
|
25 | 417454b0 | blueswir1 | env->fsr |= FSR_UFC; |
26 | 417454b0 | blueswir1 | if (T0 & float_flag_divbyzero)
|
27 | 417454b0 | blueswir1 | env->fsr |= FSR_DZC; |
28 | 417454b0 | blueswir1 | if (T0 & float_flag_inexact)
|
29 | 417454b0 | blueswir1 | env->fsr |= FSR_NXC; |
30 | 417454b0 | blueswir1 | |
31 | 417454b0 | blueswir1 | if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) |
32 | 417454b0 | blueswir1 | { |
33 | 417454b0 | blueswir1 | /* Unmasked exception, generate a trap */
|
34 | 417454b0 | blueswir1 | env->fsr |= FSR_FTT_IEEE_EXCP; |
35 | 417454b0 | blueswir1 | raise_exception(TT_FP_EXCP); |
36 | 417454b0 | blueswir1 | } |
37 | 417454b0 | blueswir1 | else
|
38 | 417454b0 | blueswir1 | { |
39 | 417454b0 | blueswir1 | /* Accumulate exceptions */
|
40 | 417454b0 | blueswir1 | env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
|
41 | 417454b0 | blueswir1 | } |
42 | 417454b0 | blueswir1 | } |
43 | 417454b0 | blueswir1 | } |
44 | 417454b0 | blueswir1 | |
45 | a0c4cb4a | bellard | #ifdef USE_INT_TO_FLOAT_HELPERS
|
46 | a0c4cb4a | bellard | void do_fitos(void) |
47 | a0c4cb4a | bellard | { |
48 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
49 | ec230928 | ths | FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status); |
50 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
51 | a0c4cb4a | bellard | } |
52 | a0c4cb4a | bellard | |
53 | a0c4cb4a | bellard | void do_fitod(void) |
54 | a0c4cb4a | bellard | { |
55 | ec230928 | ths | DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status); |
56 | a0c4cb4a | bellard | } |
57 | a0c4cb4a | bellard | #endif
|
58 | a0c4cb4a | bellard | |
59 | a0c4cb4a | bellard | void do_fabss(void) |
60 | e8af50a3 | bellard | { |
61 | 7a0e1f41 | bellard | FT0 = float32_abs(FT1); |
62 | e8af50a3 | bellard | } |
63 | e8af50a3 | bellard | |
64 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
65 | 3475187d | bellard | void do_fabsd(void) |
66 | 3475187d | bellard | { |
67 | 3475187d | bellard | DT0 = float64_abs(DT1); |
68 | 3475187d | bellard | } |
69 | 3475187d | bellard | #endif
|
70 | 3475187d | bellard | |
71 | a0c4cb4a | bellard | void do_fsqrts(void) |
72 | e8af50a3 | bellard | { |
73 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
74 | 7a0e1f41 | bellard | FT0 = float32_sqrt(FT1, &env->fp_status); |
75 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
76 | e8af50a3 | bellard | } |
77 | e8af50a3 | bellard | |
78 | a0c4cb4a | bellard | void do_fsqrtd(void) |
79 | e8af50a3 | bellard | { |
80 | 417454b0 | blueswir1 | set_float_exception_flags(0, &env->fp_status);
|
81 | 7a0e1f41 | bellard | DT0 = float64_sqrt(DT1, &env->fp_status); |
82 | 417454b0 | blueswir1 | check_ieee_exceptions(); |
83 | e8af50a3 | bellard | } |
84 | e8af50a3 | bellard | |
85 | 417454b0 | blueswir1 | #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
|
86 | 65ce8c2f | bellard | void glue(do_, name) (void) \ |
87 | 65ce8c2f | bellard | { \ |
88 | 65ce8c2f | bellard | env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ |
89 | 65ce8c2f | bellard | switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
|
90 | 65ce8c2f | bellard | case float_relation_unordered: \
|
91 | 65ce8c2f | bellard | T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ |
92 | 417454b0 | blueswir1 | if ((env->fsr & FSR_NVM) || TRAP) { \
|
93 | 65ce8c2f | bellard | env->fsr |= T0; \ |
94 | 417454b0 | blueswir1 | env->fsr |= FSR_NVC; \ |
95 | 417454b0 | blueswir1 | env->fsr |= FSR_FTT_IEEE_EXCP; \ |
96 | 65ce8c2f | bellard | raise_exception(TT_FP_EXCP); \ |
97 | 65ce8c2f | bellard | } else { \
|
98 | 65ce8c2f | bellard | env->fsr |= FSR_NVA; \ |
99 | 65ce8c2f | bellard | } \ |
100 | 65ce8c2f | bellard | break; \
|
101 | 65ce8c2f | bellard | case float_relation_less: \
|
102 | 65ce8c2f | bellard | T0 = FSR_FCC0 << FS; \ |
103 | 65ce8c2f | bellard | break; \
|
104 | 65ce8c2f | bellard | case float_relation_greater: \
|
105 | 65ce8c2f | bellard | T0 = FSR_FCC1 << FS; \ |
106 | 65ce8c2f | bellard | break; \
|
107 | 65ce8c2f | bellard | default: \
|
108 | 65ce8c2f | bellard | T0 = 0; \
|
109 | 65ce8c2f | bellard | break; \
|
110 | 65ce8c2f | bellard | } \ |
111 | 65ce8c2f | bellard | env->fsr |= T0; \ |
112 | e8af50a3 | bellard | } |
113 | e8af50a3 | bellard | |
114 | 417454b0 | blueswir1 | GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0); |
115 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); |
116 | 417454b0 | blueswir1 | |
117 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1); |
118 | 417454b0 | blueswir1 | GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); |
119 | 3475187d | bellard | |
120 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
121 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0); |
122 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); |
123 | 417454b0 | blueswir1 | |
124 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0); |
125 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); |
126 | 417454b0 | blueswir1 | |
127 | 417454b0 | blueswir1 | GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0); |
128 | 417454b0 | blueswir1 | GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); |
129 | 417454b0 | blueswir1 | |
130 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1); |
131 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); |
132 | 3475187d | bellard | |
133 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1); |
134 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); |
135 | 3475187d | bellard | |
136 | 417454b0 | blueswir1 | GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); |
137 | 417454b0 | blueswir1 | GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); |
138 | 3475187d | bellard | #endif
|
139 | 3475187d | bellard | |
140 | 24741ef3 | bellard | #if defined(CONFIG_USER_ONLY)
|
141 | 24741ef3 | bellard | void helper_ld_asi(int asi, int size, int sign) |
142 | 24741ef3 | bellard | { |
143 | 24741ef3 | bellard | } |
144 | 24741ef3 | bellard | |
145 | 24741ef3 | bellard | void helper_st_asi(int asi, int size, int sign) |
146 | 24741ef3 | bellard | { |
147 | 24741ef3 | bellard | } |
148 | 24741ef3 | bellard | #else
|
149 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
150 | a0c4cb4a | bellard | void helper_ld_asi(int asi, int size, int sign) |
151 | e8af50a3 | bellard | { |
152 | 83469015 | bellard | uint32_t ret = 0;
|
153 | e80cfcfc | bellard | |
154 | e80cfcfc | bellard | switch (asi) {
|
155 | 6c36d3fa | blueswir1 | case 2: /* SuperSparc MXCC registers */ |
156 | 6c36d3fa | blueswir1 | break;
|
157 | e8af50a3 | bellard | case 3: /* MMU probe */ |
158 | e80cfcfc | bellard | { |
159 | e80cfcfc | bellard | int mmulev;
|
160 | e80cfcfc | bellard | |
161 | e80cfcfc | bellard | mmulev = (T0 >> 8) & 15; |
162 | e80cfcfc | bellard | if (mmulev > 4) |
163 | e80cfcfc | bellard | ret = 0;
|
164 | e80cfcfc | bellard | else {
|
165 | ee5bbe38 | bellard | ret = mmu_probe(env, T0, mmulev); |
166 | e80cfcfc | bellard | //bswap32s(&ret);
|
167 | e80cfcfc | bellard | } |
168 | e80cfcfc | bellard | #ifdef DEBUG_MMU
|
169 | e80cfcfc | bellard | printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
|
170 | e80cfcfc | bellard | #endif
|
171 | e80cfcfc | bellard | } |
172 | e80cfcfc | bellard | break;
|
173 | e8af50a3 | bellard | case 4: /* read MMU regs */ |
174 | e8af50a3 | bellard | { |
175 | e80cfcfc | bellard | int reg = (T0 >> 8) & 0xf; |
176 | e8af50a3 | bellard | |
177 | e80cfcfc | bellard | ret = env->mmuregs[reg]; |
178 | 55754d9e | bellard | if (reg == 3) /* Fault status cleared on read */ |
179 | 55754d9e | bellard | env->mmuregs[reg] = 0;
|
180 | 55754d9e | bellard | #ifdef DEBUG_MMU
|
181 | 55754d9e | bellard | printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
|
182 | 55754d9e | bellard | #endif
|
183 | e8af50a3 | bellard | } |
184 | e80cfcfc | bellard | break;
|
185 | 6c36d3fa | blueswir1 | case 9: /* Supervisor code access */ |
186 | 6c36d3fa | blueswir1 | switch(size) {
|
187 | 6c36d3fa | blueswir1 | case 1: |
188 | 6c36d3fa | blueswir1 | ret = ldub_code(T0); |
189 | 6c36d3fa | blueswir1 | break;
|
190 | 6c36d3fa | blueswir1 | case 2: |
191 | 6c36d3fa | blueswir1 | ret = lduw_code(T0 & ~1);
|
192 | 6c36d3fa | blueswir1 | break;
|
193 | 6c36d3fa | blueswir1 | default:
|
194 | 6c36d3fa | blueswir1 | case 4: |
195 | 6c36d3fa | blueswir1 | ret = ldl_code(T0 & ~3);
|
196 | 6c36d3fa | blueswir1 | break;
|
197 | 6c36d3fa | blueswir1 | case 8: |
198 | 6c36d3fa | blueswir1 | ret = ldl_code(T0 & ~3);
|
199 | 6c36d3fa | blueswir1 | T0 = ldl_code((T0 + 4) & ~3); |
200 | 6c36d3fa | blueswir1 | break;
|
201 | 6c36d3fa | blueswir1 | } |
202 | 6c36d3fa | blueswir1 | break;
|
203 | 6c36d3fa | blueswir1 | case 0xc: /* I-cache tag */ |
204 | 6c36d3fa | blueswir1 | case 0xd: /* I-cache data */ |
205 | 6c36d3fa | blueswir1 | case 0xe: /* D-cache tag */ |
206 | 6c36d3fa | blueswir1 | case 0xf: /* D-cache data */ |
207 | 6c36d3fa | blueswir1 | break;
|
208 | 6c36d3fa | blueswir1 | case 0x20: /* MMU passthrough */ |
209 | 02aab46a | bellard | switch(size) {
|
210 | 02aab46a | bellard | case 1: |
211 | 02aab46a | bellard | ret = ldub_phys(T0); |
212 | 02aab46a | bellard | break;
|
213 | 02aab46a | bellard | case 2: |
214 | 02aab46a | bellard | ret = lduw_phys(T0 & ~1);
|
215 | 02aab46a | bellard | break;
|
216 | 02aab46a | bellard | default:
|
217 | 02aab46a | bellard | case 4: |
218 | 02aab46a | bellard | ret = ldl_phys(T0 & ~3);
|
219 | 02aab46a | bellard | break;
|
220 | 9e61bde5 | bellard | case 8: |
221 | 9e61bde5 | bellard | ret = ldl_phys(T0 & ~3);
|
222 | 9e61bde5 | bellard | T0 = ldl_phys((T0 + 4) & ~3); |
223 | 9e61bde5 | bellard | break;
|
224 | 02aab46a | bellard | } |
225 | e80cfcfc | bellard | break;
|
226 | 5dcb6b91 | blueswir1 | case 0x2e: /* MMU passthrough, 0xexxxxxxxx */ |
227 | 5dcb6b91 | blueswir1 | case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */ |
228 | 5dcb6b91 | blueswir1 | switch(size) {
|
229 | 5dcb6b91 | blueswir1 | case 1: |
230 | 5dcb6b91 | blueswir1 | ret = ldub_phys((target_phys_addr_t)T0 |
231 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
232 | 5dcb6b91 | blueswir1 | break;
|
233 | 5dcb6b91 | blueswir1 | case 2: |
234 | 5dcb6b91 | blueswir1 | ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
|
235 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
236 | 5dcb6b91 | blueswir1 | break;
|
237 | 5dcb6b91 | blueswir1 | default:
|
238 | 5dcb6b91 | blueswir1 | case 4: |
239 | 5dcb6b91 | blueswir1 | ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
|
240 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
241 | 5dcb6b91 | blueswir1 | break;
|
242 | 5dcb6b91 | blueswir1 | case 8: |
243 | 5dcb6b91 | blueswir1 | ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
|
244 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
245 | 5dcb6b91 | blueswir1 | T0 = ldl_phys((target_phys_addr_t)((T0 + 4) & ~3) |
246 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32)); |
247 | 5dcb6b91 | blueswir1 | break;
|
248 | 5dcb6b91 | blueswir1 | } |
249 | 5dcb6b91 | blueswir1 | break;
|
250 | 5dcb6b91 | blueswir1 | case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ |
251 | e8af50a3 | bellard | default:
|
252 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 0, 0, 1); |
253 | e80cfcfc | bellard | ret = 0;
|
254 | e80cfcfc | bellard | break;
|
255 | e8af50a3 | bellard | } |
256 | e80cfcfc | bellard | T1 = ret; |
257 | e8af50a3 | bellard | } |
258 | e8af50a3 | bellard | |
259 | a0c4cb4a | bellard | void helper_st_asi(int asi, int size, int sign) |
260 | e8af50a3 | bellard | { |
261 | e8af50a3 | bellard | switch(asi) {
|
262 | 6c36d3fa | blueswir1 | case 2: /* SuperSparc MXCC registers */ |
263 | 6c36d3fa | blueswir1 | break;
|
264 | e8af50a3 | bellard | case 3: /* MMU flush */ |
265 | e80cfcfc | bellard | { |
266 | e80cfcfc | bellard | int mmulev;
|
267 | e80cfcfc | bellard | |
268 | e80cfcfc | bellard | mmulev = (T0 >> 8) & 15; |
269 | 55754d9e | bellard | #ifdef DEBUG_MMU
|
270 | 55754d9e | bellard | printf("mmu flush level %d\n", mmulev);
|
271 | 55754d9e | bellard | #endif
|
272 | e80cfcfc | bellard | switch (mmulev) {
|
273 | e80cfcfc | bellard | case 0: // flush page |
274 | 55754d9e | bellard | tlb_flush_page(env, T0 & 0xfffff000);
|
275 | e80cfcfc | bellard | break;
|
276 | e80cfcfc | bellard | case 1: // flush segment (256k) |
277 | e80cfcfc | bellard | case 2: // flush region (16M) |
278 | e80cfcfc | bellard | case 3: // flush context (4G) |
279 | e80cfcfc | bellard | case 4: // flush entire |
280 | 55754d9e | bellard | tlb_flush(env, 1);
|
281 | e80cfcfc | bellard | break;
|
282 | e80cfcfc | bellard | default:
|
283 | e80cfcfc | bellard | break;
|
284 | e80cfcfc | bellard | } |
285 | 55754d9e | bellard | #ifdef DEBUG_MMU
|
286 | ee5bbe38 | bellard | dump_mmu(env); |
287 | 55754d9e | bellard | #endif
|
288 | e80cfcfc | bellard | return;
|
289 | e80cfcfc | bellard | } |
290 | e8af50a3 | bellard | case 4: /* write MMU regs */ |
291 | e8af50a3 | bellard | { |
292 | 83469015 | bellard | int reg = (T0 >> 8) & 0xf; |
293 | 83469015 | bellard | uint32_t oldreg; |
294 | e80cfcfc | bellard | |
295 | e80cfcfc | bellard | oldreg = env->mmuregs[reg]; |
296 | 55754d9e | bellard | switch(reg) {
|
297 | 55754d9e | bellard | case 0: |
298 | e8af50a3 | bellard | env->mmuregs[reg] &= ~(MMU_E | MMU_NF); |
299 | e8af50a3 | bellard | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); |
300 | 6f7e9aec | bellard | // Mappings generated during no-fault mode or MMU
|
301 | 6f7e9aec | bellard | // disabled mode are invalid in normal mode
|
302 | 6f7e9aec | bellard | if (oldreg != env->mmuregs[reg])
|
303 | 55754d9e | bellard | tlb_flush(env, 1);
|
304 | 55754d9e | bellard | break;
|
305 | 55754d9e | bellard | case 2: |
306 | e8af50a3 | bellard | env->mmuregs[reg] = T1; |
307 | 55754d9e | bellard | if (oldreg != env->mmuregs[reg]) {
|
308 | 55754d9e | bellard | /* we flush when the MMU context changes because
|
309 | 55754d9e | bellard | QEMU has no MMU context support */
|
310 | 55754d9e | bellard | tlb_flush(env, 1);
|
311 | 55754d9e | bellard | } |
312 | 55754d9e | bellard | break;
|
313 | 55754d9e | bellard | case 3: |
314 | 55754d9e | bellard | case 4: |
315 | 55754d9e | bellard | break;
|
316 | 55754d9e | bellard | default:
|
317 | 55754d9e | bellard | env->mmuregs[reg] = T1; |
318 | 55754d9e | bellard | break;
|
319 | 55754d9e | bellard | } |
320 | 55754d9e | bellard | #ifdef DEBUG_MMU
|
321 | 55754d9e | bellard | if (oldreg != env->mmuregs[reg]) {
|
322 | 55754d9e | bellard | printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
|
323 | 55754d9e | bellard | } |
324 | ee5bbe38 | bellard | dump_mmu(env); |
325 | 55754d9e | bellard | #endif
|
326 | e8af50a3 | bellard | return;
|
327 | e8af50a3 | bellard | } |
328 | 6c36d3fa | blueswir1 | case 0xc: /* I-cache tag */ |
329 | 6c36d3fa | blueswir1 | case 0xd: /* I-cache data */ |
330 | 6c36d3fa | blueswir1 | case 0xe: /* D-cache tag */ |
331 | 6c36d3fa | blueswir1 | case 0xf: /* D-cache data */ |
332 | 6c36d3fa | blueswir1 | case 0x10: /* I/D-cache flush page */ |
333 | 6c36d3fa | blueswir1 | case 0x11: /* I/D-cache flush segment */ |
334 | 6c36d3fa | blueswir1 | case 0x12: /* I/D-cache flush region */ |
335 | 6c36d3fa | blueswir1 | case 0x13: /* I/D-cache flush context */ |
336 | 6c36d3fa | blueswir1 | case 0x14: /* I/D-cache flush user */ |
337 | 6c36d3fa | blueswir1 | break;
|
338 | e80cfcfc | bellard | case 0x17: /* Block copy, sta access */ |
339 | e80cfcfc | bellard | { |
340 | e80cfcfc | bellard | // value (T1) = src
|
341 | e80cfcfc | bellard | // address (T0) = dst
|
342 | e80cfcfc | bellard | // copy 32 bytes
|
343 | 6c36d3fa | blueswir1 | unsigned int i; |
344 | 6c36d3fa | blueswir1 | uint32_t src = T1 & ~3, dst = T0 & ~3, temp; |
345 | e80cfcfc | bellard | |
346 | 6c36d3fa | blueswir1 | for (i = 0; i < 32; i += 4, src += 4, dst += 4) { |
347 | 6c36d3fa | blueswir1 | temp = ldl_kernel(src); |
348 | 6c36d3fa | blueswir1 | stl_kernel(dst, temp); |
349 | 6c36d3fa | blueswir1 | } |
350 | e80cfcfc | bellard | } |
351 | e80cfcfc | bellard | return;
|
352 | e80cfcfc | bellard | case 0x1f: /* Block fill, stda access */ |
353 | e80cfcfc | bellard | { |
354 | e80cfcfc | bellard | // value (T1, T2)
|
355 | e80cfcfc | bellard | // address (T0) = dst
|
356 | e80cfcfc | bellard | // fill 32 bytes
|
357 | 6c36d3fa | blueswir1 | unsigned int i; |
358 | 6c36d3fa | blueswir1 | uint32_t dst = T0 & 7;
|
359 | 6c36d3fa | blueswir1 | uint64_t val; |
360 | e80cfcfc | bellard | |
361 | 6c36d3fa | blueswir1 | val = (((uint64_t)T1) << 32) | T2;
|
362 | 6c36d3fa | blueswir1 | |
363 | 6c36d3fa | blueswir1 | for (i = 0; i < 32; i += 8, dst += 8) |
364 | 6c36d3fa | blueswir1 | stq_kernel(dst, val); |
365 | e80cfcfc | bellard | } |
366 | e80cfcfc | bellard | return;
|
367 | 6c36d3fa | blueswir1 | case 0x20: /* MMU passthrough */ |
368 | e8af50a3 | bellard | { |
369 | 02aab46a | bellard | switch(size) {
|
370 | 02aab46a | bellard | case 1: |
371 | 02aab46a | bellard | stb_phys(T0, T1); |
372 | 02aab46a | bellard | break;
|
373 | 02aab46a | bellard | case 2: |
374 | 02aab46a | bellard | stw_phys(T0 & ~1, T1);
|
375 | 02aab46a | bellard | break;
|
376 | 02aab46a | bellard | case 4: |
377 | 02aab46a | bellard | default:
|
378 | 02aab46a | bellard | stl_phys(T0 & ~3, T1);
|
379 | 02aab46a | bellard | break;
|
380 | 9e61bde5 | bellard | case 8: |
381 | 9e61bde5 | bellard | stl_phys(T0 & ~3, T1);
|
382 | 9e61bde5 | bellard | stl_phys((T0 + 4) & ~3, T2); |
383 | 9e61bde5 | bellard | break;
|
384 | 02aab46a | bellard | } |
385 | e8af50a3 | bellard | } |
386 | e8af50a3 | bellard | return;
|
387 | 5dcb6b91 | blueswir1 | case 0x2e: /* MMU passthrough, 0xexxxxxxxx */ |
388 | 5dcb6b91 | blueswir1 | case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */ |
389 | 5dcb6b91 | blueswir1 | { |
390 | 5dcb6b91 | blueswir1 | switch(size) {
|
391 | 5dcb6b91 | blueswir1 | case 1: |
392 | 5dcb6b91 | blueswir1 | stb_phys((target_phys_addr_t)T0 |
393 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
394 | 5dcb6b91 | blueswir1 | break;
|
395 | 5dcb6b91 | blueswir1 | case 2: |
396 | 5dcb6b91 | blueswir1 | stw_phys((target_phys_addr_t)(T0 & ~1)
|
397 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
398 | 5dcb6b91 | blueswir1 | break;
|
399 | 5dcb6b91 | blueswir1 | case 4: |
400 | 5dcb6b91 | blueswir1 | default:
|
401 | 5dcb6b91 | blueswir1 | stl_phys((target_phys_addr_t)(T0 & ~3)
|
402 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
403 | 5dcb6b91 | blueswir1 | break;
|
404 | 5dcb6b91 | blueswir1 | case 8: |
405 | 5dcb6b91 | blueswir1 | stl_phys((target_phys_addr_t)(T0 & ~3)
|
406 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
407 | 5dcb6b91 | blueswir1 | stl_phys((target_phys_addr_t)((T0 + 4) & ~3) |
408 | 5dcb6b91 | blueswir1 | | ((target_phys_addr_t)(asi & 0xf) << 32), T1); |
409 | 5dcb6b91 | blueswir1 | break;
|
410 | 5dcb6b91 | blueswir1 | } |
411 | 5dcb6b91 | blueswir1 | } |
412 | 5dcb6b91 | blueswir1 | return;
|
413 | 6c36d3fa | blueswir1 | case 0x31: /* Ross RT620 I-cache flush */ |
414 | 6c36d3fa | blueswir1 | case 0x36: /* I-cache flash clear */ |
415 | 6c36d3fa | blueswir1 | case 0x37: /* D-cache flash clear */ |
416 | 6c36d3fa | blueswir1 | break;
|
417 | 6c36d3fa | blueswir1 | case 9: /* Supervisor code access, XXX */ |
418 | 5dcb6b91 | blueswir1 | case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ |
419 | e8af50a3 | bellard | default:
|
420 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 1, 0, 1); |
421 | e8af50a3 | bellard | return;
|
422 | e8af50a3 | bellard | } |
423 | e8af50a3 | bellard | } |
424 | e8af50a3 | bellard | |
425 | 3475187d | bellard | #else
|
426 | 3475187d | bellard | |
427 | 3475187d | bellard | void helper_ld_asi(int asi, int size, int sign) |
428 | 3475187d | bellard | { |
429 | 83469015 | bellard | uint64_t ret = 0;
|
430 | 3475187d | bellard | |
431 | 3475187d | bellard | if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
432 | 83469015 | bellard | raise_exception(TT_PRIV_ACT); |
433 | 3475187d | bellard | |
434 | 3475187d | bellard | switch (asi) {
|
435 | 3475187d | bellard | case 0x14: // Bypass |
436 | 3475187d | bellard | case 0x15: // Bypass, non-cacheable |
437 | 3475187d | bellard | { |
438 | 02aab46a | bellard | switch(size) {
|
439 | 02aab46a | bellard | case 1: |
440 | 02aab46a | bellard | ret = ldub_phys(T0); |
441 | 02aab46a | bellard | break;
|
442 | 02aab46a | bellard | case 2: |
443 | 02aab46a | bellard | ret = lduw_phys(T0 & ~1);
|
444 | 02aab46a | bellard | break;
|
445 | 02aab46a | bellard | case 4: |
446 | 02aab46a | bellard | ret = ldl_phys(T0 & ~3);
|
447 | 02aab46a | bellard | break;
|
448 | 02aab46a | bellard | default:
|
449 | 02aab46a | bellard | case 8: |
450 | 02aab46a | bellard | ret = ldq_phys(T0 & ~7);
|
451 | 02aab46a | bellard | break;
|
452 | 02aab46a | bellard | } |
453 | 3475187d | bellard | break;
|
454 | 3475187d | bellard | } |
455 | 83469015 | bellard | case 0x04: // Nucleus |
456 | 83469015 | bellard | case 0x0c: // Nucleus Little Endian (LE) |
457 | 83469015 | bellard | case 0x10: // As if user primary |
458 | 83469015 | bellard | case 0x11: // As if user secondary |
459 | 83469015 | bellard | case 0x18: // As if user primary LE |
460 | 83469015 | bellard | case 0x19: // As if user secondary LE |
461 | 3475187d | bellard | case 0x1c: // Bypass LE |
462 | 3475187d | bellard | case 0x1d: // Bypass, non-cacheable LE |
463 | 83469015 | bellard | case 0x24: // Nucleus quad LDD 128 bit atomic |
464 | 83469015 | bellard | case 0x2c: // Nucleus quad LDD 128 bit atomic |
465 | 83469015 | bellard | case 0x4a: // UPA config |
466 | 83469015 | bellard | case 0x82: // Primary no-fault |
467 | 83469015 | bellard | case 0x83: // Secondary no-fault |
468 | 83469015 | bellard | case 0x88: // Primary LE |
469 | 83469015 | bellard | case 0x89: // Secondary LE |
470 | 83469015 | bellard | case 0x8a: // Primary no-fault LE |
471 | 83469015 | bellard | case 0x8b: // Secondary no-fault LE |
472 | 3475187d | bellard | // XXX
|
473 | 3475187d | bellard | break;
|
474 | 3475187d | bellard | case 0x45: // LSU |
475 | 3475187d | bellard | ret = env->lsu; |
476 | 3475187d | bellard | break;
|
477 | 3475187d | bellard | case 0x50: // I-MMU regs |
478 | 3475187d | bellard | { |
479 | 3475187d | bellard | int reg = (T0 >> 3) & 0xf; |
480 | 3475187d | bellard | |
481 | 3475187d | bellard | ret = env->immuregs[reg]; |
482 | 3475187d | bellard | break;
|
483 | 3475187d | bellard | } |
484 | 3475187d | bellard | case 0x51: // I-MMU 8k TSB pointer |
485 | 3475187d | bellard | case 0x52: // I-MMU 64k TSB pointer |
486 | 3475187d | bellard | case 0x55: // I-MMU data access |
487 | 83469015 | bellard | // XXX
|
488 | 3475187d | bellard | break;
|
489 | 83469015 | bellard | case 0x56: // I-MMU tag read |
490 | 83469015 | bellard | { |
491 | 83469015 | bellard | unsigned int i; |
492 | 83469015 | bellard | |
493 | 83469015 | bellard | for (i = 0; i < 64; i++) { |
494 | 83469015 | bellard | // Valid, ctx match, vaddr match
|
495 | 83469015 | bellard | if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && |
496 | 83469015 | bellard | env->itlb_tag[i] == T0) { |
497 | 83469015 | bellard | ret = env->itlb_tag[i]; |
498 | 83469015 | bellard | break;
|
499 | 83469015 | bellard | } |
500 | 83469015 | bellard | } |
501 | 83469015 | bellard | break;
|
502 | 83469015 | bellard | } |
503 | 3475187d | bellard | case 0x58: // D-MMU regs |
504 | 3475187d | bellard | { |
505 | 3475187d | bellard | int reg = (T0 >> 3) & 0xf; |
506 | 3475187d | bellard | |
507 | 3475187d | bellard | ret = env->dmmuregs[reg]; |
508 | 3475187d | bellard | break;
|
509 | 3475187d | bellard | } |
510 | 83469015 | bellard | case 0x5e: // D-MMU tag read |
511 | 83469015 | bellard | { |
512 | 83469015 | bellard | unsigned int i; |
513 | 83469015 | bellard | |
514 | 83469015 | bellard | for (i = 0; i < 64; i++) { |
515 | 83469015 | bellard | // Valid, ctx match, vaddr match
|
516 | 83469015 | bellard | if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && |
517 | 83469015 | bellard | env->dtlb_tag[i] == T0) { |
518 | 83469015 | bellard | ret = env->dtlb_tag[i]; |
519 | 83469015 | bellard | break;
|
520 | 83469015 | bellard | } |
521 | 83469015 | bellard | } |
522 | 83469015 | bellard | break;
|
523 | 83469015 | bellard | } |
524 | 3475187d | bellard | case 0x59: // D-MMU 8k TSB pointer |
525 | 3475187d | bellard | case 0x5a: // D-MMU 64k TSB pointer |
526 | 3475187d | bellard | case 0x5b: // D-MMU data pointer |
527 | 3475187d | bellard | case 0x5d: // D-MMU data access |
528 | 83469015 | bellard | case 0x48: // Interrupt dispatch, RO |
529 | 83469015 | bellard | case 0x49: // Interrupt data receive |
530 | 83469015 | bellard | case 0x7f: // Incoming interrupt vector, RO |
531 | 83469015 | bellard | // XXX
|
532 | 3475187d | bellard | break;
|
533 | 3475187d | bellard | case 0x54: // I-MMU data in, WO |
534 | 3475187d | bellard | case 0x57: // I-MMU demap, WO |
535 | 3475187d | bellard | case 0x5c: // D-MMU data in, WO |
536 | 3475187d | bellard | case 0x5f: // D-MMU demap, WO |
537 | 83469015 | bellard | case 0x77: // Interrupt vector, WO |
538 | 3475187d | bellard | default:
|
539 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 0, 0, 1); |
540 | 3475187d | bellard | ret = 0;
|
541 | 3475187d | bellard | break;
|
542 | 3475187d | bellard | } |
543 | 3475187d | bellard | T1 = ret; |
544 | 3475187d | bellard | } |
545 | 3475187d | bellard | |
546 | 3475187d | bellard | void helper_st_asi(int asi, int size, int sign) |
547 | 3475187d | bellard | { |
548 | 3475187d | bellard | if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
549 | 83469015 | bellard | raise_exception(TT_PRIV_ACT); |
550 | 3475187d | bellard | |
551 | 3475187d | bellard | switch(asi) {
|
552 | 3475187d | bellard | case 0x14: // Bypass |
553 | 3475187d | bellard | case 0x15: // Bypass, non-cacheable |
554 | 3475187d | bellard | { |
555 | 02aab46a | bellard | switch(size) {
|
556 | 02aab46a | bellard | case 1: |
557 | 02aab46a | bellard | stb_phys(T0, T1); |
558 | 02aab46a | bellard | break;
|
559 | 02aab46a | bellard | case 2: |
560 | 02aab46a | bellard | stw_phys(T0 & ~1, T1);
|
561 | 02aab46a | bellard | break;
|
562 | 02aab46a | bellard | case 4: |
563 | 02aab46a | bellard | stl_phys(T0 & ~3, T1);
|
564 | 02aab46a | bellard | break;
|
565 | 02aab46a | bellard | case 8: |
566 | 02aab46a | bellard | default:
|
567 | 02aab46a | bellard | stq_phys(T0 & ~7, T1);
|
568 | 02aab46a | bellard | break;
|
569 | 02aab46a | bellard | } |
570 | 3475187d | bellard | } |
571 | 3475187d | bellard | return;
|
572 | 83469015 | bellard | case 0x04: // Nucleus |
573 | 83469015 | bellard | case 0x0c: // Nucleus Little Endian (LE) |
574 | 83469015 | bellard | case 0x10: // As if user primary |
575 | 83469015 | bellard | case 0x11: // As if user secondary |
576 | 83469015 | bellard | case 0x18: // As if user primary LE |
577 | 83469015 | bellard | case 0x19: // As if user secondary LE |
578 | 3475187d | bellard | case 0x1c: // Bypass LE |
579 | 3475187d | bellard | case 0x1d: // Bypass, non-cacheable LE |
580 | 83469015 | bellard | case 0x24: // Nucleus quad LDD 128 bit atomic |
581 | 83469015 | bellard | case 0x2c: // Nucleus quad LDD 128 bit atomic |
582 | 83469015 | bellard | case 0x4a: // UPA config |
583 | 83469015 | bellard | case 0x88: // Primary LE |
584 | 83469015 | bellard | case 0x89: // Secondary LE |
585 | 3475187d | bellard | // XXX
|
586 | 3475187d | bellard | return;
|
587 | 3475187d | bellard | case 0x45: // LSU |
588 | 3475187d | bellard | { |
589 | 3475187d | bellard | uint64_t oldreg; |
590 | 3475187d | bellard | |
591 | 3475187d | bellard | oldreg = env->lsu; |
592 | 3475187d | bellard | env->lsu = T1 & (DMMU_E | IMMU_E); |
593 | 3475187d | bellard | // Mappings generated during D/I MMU disabled mode are
|
594 | 3475187d | bellard | // invalid in normal mode
|
595 | 83469015 | bellard | if (oldreg != env->lsu) {
|
596 | 83469015 | bellard | #ifdef DEBUG_MMU
|
597 | 26a76461 | bellard | printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); |
598 | 83469015 | bellard | dump_mmu(env); |
599 | 83469015 | bellard | #endif
|
600 | 3475187d | bellard | tlb_flush(env, 1);
|
601 | 83469015 | bellard | } |
602 | 3475187d | bellard | return;
|
603 | 3475187d | bellard | } |
604 | 3475187d | bellard | case 0x50: // I-MMU regs |
605 | 3475187d | bellard | { |
606 | 3475187d | bellard | int reg = (T0 >> 3) & 0xf; |
607 | 3475187d | bellard | uint64_t oldreg; |
608 | 3475187d | bellard | |
609 | 3475187d | bellard | oldreg = env->immuregs[reg]; |
610 | 3475187d | bellard | switch(reg) {
|
611 | 3475187d | bellard | case 0: // RO |
612 | 3475187d | bellard | case 4: |
613 | 3475187d | bellard | return;
|
614 | 3475187d | bellard | case 1: // Not in I-MMU |
615 | 3475187d | bellard | case 2: |
616 | 3475187d | bellard | case 7: |
617 | 3475187d | bellard | case 8: |
618 | 3475187d | bellard | return;
|
619 | 3475187d | bellard | case 3: // SFSR |
620 | 3475187d | bellard | if ((T1 & 1) == 0) |
621 | 3475187d | bellard | T1 = 0; // Clear SFSR |
622 | 3475187d | bellard | break;
|
623 | 3475187d | bellard | case 5: // TSB access |
624 | 3475187d | bellard | case 6: // Tag access |
625 | 3475187d | bellard | default:
|
626 | 3475187d | bellard | break;
|
627 | 3475187d | bellard | } |
628 | 3475187d | bellard | env->immuregs[reg] = T1; |
629 | 3475187d | bellard | #ifdef DEBUG_MMU
|
630 | 3475187d | bellard | if (oldreg != env->immuregs[reg]) {
|
631 | 26a76461 | bellard | printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); |
632 | 3475187d | bellard | } |
633 | ee5bbe38 | bellard | dump_mmu(env); |
634 | 3475187d | bellard | #endif
|
635 | 3475187d | bellard | return;
|
636 | 3475187d | bellard | } |
637 | 3475187d | bellard | case 0x54: // I-MMU data in |
638 | 3475187d | bellard | { |
639 | 3475187d | bellard | unsigned int i; |
640 | 3475187d | bellard | |
641 | 3475187d | bellard | // Try finding an invalid entry
|
642 | 3475187d | bellard | for (i = 0; i < 64; i++) { |
643 | 3475187d | bellard | if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) { |
644 | 3475187d | bellard | env->itlb_tag[i] = env->immuregs[6];
|
645 | 3475187d | bellard | env->itlb_tte[i] = T1; |
646 | 3475187d | bellard | return;
|
647 | 3475187d | bellard | } |
648 | 3475187d | bellard | } |
649 | 3475187d | bellard | // Try finding an unlocked entry
|
650 | 3475187d | bellard | for (i = 0; i < 64; i++) { |
651 | 3475187d | bellard | if ((env->itlb_tte[i] & 0x40) == 0) { |
652 | 3475187d | bellard | env->itlb_tag[i] = env->immuregs[6];
|
653 | 3475187d | bellard | env->itlb_tte[i] = T1; |
654 | 3475187d | bellard | return;
|
655 | 3475187d | bellard | } |
656 | 3475187d | bellard | } |
657 | 3475187d | bellard | // error state?
|
658 | 3475187d | bellard | return;
|
659 | 3475187d | bellard | } |
660 | 3475187d | bellard | case 0x55: // I-MMU data access |
661 | 3475187d | bellard | { |
662 | 3475187d | bellard | unsigned int i = (T0 >> 3) & 0x3f; |
663 | 3475187d | bellard | |
664 | 3475187d | bellard | env->itlb_tag[i] = env->immuregs[6];
|
665 | 3475187d | bellard | env->itlb_tte[i] = T1; |
666 | 3475187d | bellard | return;
|
667 | 3475187d | bellard | } |
668 | 3475187d | bellard | case 0x57: // I-MMU demap |
669 | 83469015 | bellard | // XXX
|
670 | 3475187d | bellard | return;
|
671 | 3475187d | bellard | case 0x58: // D-MMU regs |
672 | 3475187d | bellard | { |
673 | 3475187d | bellard | int reg = (T0 >> 3) & 0xf; |
674 | 3475187d | bellard | uint64_t oldreg; |
675 | 3475187d | bellard | |
676 | 3475187d | bellard | oldreg = env->dmmuregs[reg]; |
677 | 3475187d | bellard | switch(reg) {
|
678 | 3475187d | bellard | case 0: // RO |
679 | 3475187d | bellard | case 4: |
680 | 3475187d | bellard | return;
|
681 | 3475187d | bellard | case 3: // SFSR |
682 | 3475187d | bellard | if ((T1 & 1) == 0) { |
683 | 3475187d | bellard | T1 = 0; // Clear SFSR, Fault address |
684 | 3475187d | bellard | env->dmmuregs[4] = 0; |
685 | 3475187d | bellard | } |
686 | 3475187d | bellard | env->dmmuregs[reg] = T1; |
687 | 3475187d | bellard | break;
|
688 | 3475187d | bellard | case 1: // Primary context |
689 | 3475187d | bellard | case 2: // Secondary context |
690 | 3475187d | bellard | case 5: // TSB access |
691 | 3475187d | bellard | case 6: // Tag access |
692 | 3475187d | bellard | case 7: // Virtual Watchpoint |
693 | 3475187d | bellard | case 8: // Physical Watchpoint |
694 | 3475187d | bellard | default:
|
695 | 3475187d | bellard | break;
|
696 | 3475187d | bellard | } |
697 | 3475187d | bellard | env->dmmuregs[reg] = T1; |
698 | 3475187d | bellard | #ifdef DEBUG_MMU
|
699 | 3475187d | bellard | if (oldreg != env->dmmuregs[reg]) {
|
700 | 26a76461 | bellard | printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); |
701 | 3475187d | bellard | } |
702 | ee5bbe38 | bellard | dump_mmu(env); |
703 | 3475187d | bellard | #endif
|
704 | 3475187d | bellard | return;
|
705 | 3475187d | bellard | } |
706 | 3475187d | bellard | case 0x5c: // D-MMU data in |
707 | 3475187d | bellard | { |
708 | 3475187d | bellard | unsigned int i; |
709 | 3475187d | bellard | |
710 | 3475187d | bellard | // Try finding an invalid entry
|
711 | 3475187d | bellard | for (i = 0; i < 64; i++) { |
712 | 3475187d | bellard | if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) { |
713 | 3475187d | bellard | env->dtlb_tag[i] = env->dmmuregs[6];
|
714 | 3475187d | bellard | env->dtlb_tte[i] = T1; |
715 | 3475187d | bellard | return;
|
716 | 3475187d | bellard | } |
717 | 3475187d | bellard | } |
718 | 3475187d | bellard | // Try finding an unlocked entry
|
719 | 3475187d | bellard | for (i = 0; i < 64; i++) { |
720 | 3475187d | bellard | if ((env->dtlb_tte[i] & 0x40) == 0) { |
721 | 3475187d | bellard | env->dtlb_tag[i] = env->dmmuregs[6];
|
722 | 3475187d | bellard | env->dtlb_tte[i] = T1; |
723 | 3475187d | bellard | return;
|
724 | 3475187d | bellard | } |
725 | 3475187d | bellard | } |
726 | 3475187d | bellard | // error state?
|
727 | 3475187d | bellard | return;
|
728 | 3475187d | bellard | } |
729 | 3475187d | bellard | case 0x5d: // D-MMU data access |
730 | 3475187d | bellard | { |
731 | 3475187d | bellard | unsigned int i = (T0 >> 3) & 0x3f; |
732 | 3475187d | bellard | |
733 | 3475187d | bellard | env->dtlb_tag[i] = env->dmmuregs[6];
|
734 | 3475187d | bellard | env->dtlb_tte[i] = T1; |
735 | 3475187d | bellard | return;
|
736 | 3475187d | bellard | } |
737 | 3475187d | bellard | case 0x5f: // D-MMU demap |
738 | 83469015 | bellard | case 0x49: // Interrupt data receive |
739 | 83469015 | bellard | // XXX
|
740 | 3475187d | bellard | return;
|
741 | 3475187d | bellard | case 0x51: // I-MMU 8k TSB pointer, RO |
742 | 3475187d | bellard | case 0x52: // I-MMU 64k TSB pointer, RO |
743 | 3475187d | bellard | case 0x56: // I-MMU tag read, RO |
744 | 3475187d | bellard | case 0x59: // D-MMU 8k TSB pointer, RO |
745 | 3475187d | bellard | case 0x5a: // D-MMU 64k TSB pointer, RO |
746 | 3475187d | bellard | case 0x5b: // D-MMU data pointer, RO |
747 | 3475187d | bellard | case 0x5e: // D-MMU tag read, RO |
748 | 83469015 | bellard | case 0x48: // Interrupt dispatch, RO |
749 | 83469015 | bellard | case 0x7f: // Incoming interrupt vector, RO |
750 | 83469015 | bellard | case 0x82: // Primary no-fault, RO |
751 | 83469015 | bellard | case 0x83: // Secondary no-fault, RO |
752 | 83469015 | bellard | case 0x8a: // Primary no-fault LE, RO |
753 | 83469015 | bellard | case 0x8b: // Secondary no-fault LE, RO |
754 | 3475187d | bellard | default:
|
755 | 6c36d3fa | blueswir1 | do_unassigned_access(T0, 1, 0, 1); |
756 | 3475187d | bellard | return;
|
757 | 3475187d | bellard | } |
758 | 3475187d | bellard | } |
759 | 3475187d | bellard | #endif
|
760 | 24741ef3 | bellard | #endif /* !CONFIG_USER_ONLY */ |
761 | 3475187d | bellard | |
762 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
763 | a0c4cb4a | bellard | void helper_rett()
|
764 | e8af50a3 | bellard | { |
765 | af7bf89b | bellard | unsigned int cwp; |
766 | af7bf89b | bellard | |
767 | d4218d99 | blueswir1 | if (env->psret == 1) |
768 | d4218d99 | blueswir1 | raise_exception(TT_ILL_INSN); |
769 | d4218d99 | blueswir1 | |
770 | e8af50a3 | bellard | env->psret = 1;
|
771 | e8af50a3 | bellard | cwp = (env->cwp + 1) & (NWINDOWS - 1); |
772 | e8af50a3 | bellard | if (env->wim & (1 << cwp)) { |
773 | e8af50a3 | bellard | raise_exception(TT_WIN_UNF); |
774 | e8af50a3 | bellard | } |
775 | e8af50a3 | bellard | set_cwp(cwp); |
776 | e8af50a3 | bellard | env->psrs = env->psrps; |
777 | e8af50a3 | bellard | } |
778 | 3475187d | bellard | #endif
|
779 | e8af50a3 | bellard | |
780 | 8d5f07fa | bellard | void helper_ldfsr(void) |
781 | e8af50a3 | bellard | { |
782 | 7a0e1f41 | bellard | int rnd_mode;
|
783 | e8af50a3 | bellard | switch (env->fsr & FSR_RD_MASK) {
|
784 | e8af50a3 | bellard | case FSR_RD_NEAREST:
|
785 | 7a0e1f41 | bellard | rnd_mode = float_round_nearest_even; |
786 | e8af50a3 | bellard | break;
|
787 | ed910241 | bellard | default:
|
788 | e8af50a3 | bellard | case FSR_RD_ZERO:
|
789 | 7a0e1f41 | bellard | rnd_mode = float_round_to_zero; |
790 | e8af50a3 | bellard | break;
|
791 | e8af50a3 | bellard | case FSR_RD_POS:
|
792 | 7a0e1f41 | bellard | rnd_mode = float_round_up; |
793 | e8af50a3 | bellard | break;
|
794 | e8af50a3 | bellard | case FSR_RD_NEG:
|
795 | 7a0e1f41 | bellard | rnd_mode = float_round_down; |
796 | e8af50a3 | bellard | break;
|
797 | e8af50a3 | bellard | } |
798 | 7a0e1f41 | bellard | set_float_rounding_mode(rnd_mode, &env->fp_status); |
799 | e8af50a3 | bellard | } |
800 | e80cfcfc | bellard | |
801 | e80cfcfc | bellard | void helper_debug()
|
802 | e80cfcfc | bellard | { |
803 | e80cfcfc | bellard | env->exception_index = EXCP_DEBUG; |
804 | e80cfcfc | bellard | cpu_loop_exit(); |
805 | e80cfcfc | bellard | } |
806 | af7bf89b | bellard | |
807 | 3475187d | bellard | #ifndef TARGET_SPARC64
|
808 | af7bf89b | bellard | void do_wrpsr()
|
809 | af7bf89b | bellard | { |
810 | d4218d99 | blueswir1 | if ((T0 & PSR_CWP) >= NWINDOWS)
|
811 | d4218d99 | blueswir1 | raise_exception(TT_ILL_INSN); |
812 | d4218d99 | blueswir1 | else
|
813 | d4218d99 | blueswir1 | PUT_PSR(env, T0); |
814 | af7bf89b | bellard | } |
815 | af7bf89b | bellard | |
816 | af7bf89b | bellard | void do_rdpsr()
|
817 | af7bf89b | bellard | { |
818 | af7bf89b | bellard | T0 = GET_PSR(env); |
819 | af7bf89b | bellard | } |
820 | 3475187d | bellard | |
821 | 3475187d | bellard | #else
|
822 | 3475187d | bellard | |
823 | 3475187d | bellard | void do_popc()
|
824 | 3475187d | bellard | { |
825 | 3475187d | bellard | T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL); |
826 | 3475187d | bellard | T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL); |
827 | 3475187d | bellard | T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL); |
828 | 3475187d | bellard | T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL); |
829 | 3475187d | bellard | T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL); |
830 | 3475187d | bellard | T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL); |
831 | 3475187d | bellard | } |
832 | 83469015 | bellard | |
833 | 83469015 | bellard | static inline uint64_t *get_gregset(uint64_t pstate) |
834 | 83469015 | bellard | { |
835 | 83469015 | bellard | switch (pstate) {
|
836 | 83469015 | bellard | default:
|
837 | 83469015 | bellard | case 0: |
838 | 83469015 | bellard | return env->bgregs;
|
839 | 83469015 | bellard | case PS_AG:
|
840 | 83469015 | bellard | return env->agregs;
|
841 | 83469015 | bellard | case PS_MG:
|
842 | 83469015 | bellard | return env->mgregs;
|
843 | 83469015 | bellard | case PS_IG:
|
844 | 83469015 | bellard | return env->igregs;
|
845 | 83469015 | bellard | } |
846 | 83469015 | bellard | } |
847 | 83469015 | bellard | |
848 | 83469015 | bellard | void do_wrpstate()
|
849 | 83469015 | bellard | { |
850 | 83469015 | bellard | uint64_t new_pstate, pstate_regs, new_pstate_regs; |
851 | 83469015 | bellard | uint64_t *src, *dst; |
852 | 83469015 | bellard | |
853 | 83469015 | bellard | new_pstate = T0 & 0xf3f;
|
854 | 83469015 | bellard | pstate_regs = env->pstate & 0xc01;
|
855 | 83469015 | bellard | new_pstate_regs = new_pstate & 0xc01;
|
856 | 83469015 | bellard | if (new_pstate_regs != pstate_regs) {
|
857 | 83469015 | bellard | // Switch global register bank
|
858 | 83469015 | bellard | src = get_gregset(new_pstate_regs); |
859 | 83469015 | bellard | dst = get_gregset(pstate_regs); |
860 | 83469015 | bellard | memcpy32(dst, env->gregs); |
861 | 83469015 | bellard | memcpy32(env->gregs, src); |
862 | 83469015 | bellard | } |
863 | 83469015 | bellard | env->pstate = new_pstate; |
864 | 83469015 | bellard | } |
865 | 83469015 | bellard | |
866 | 83469015 | bellard | void do_done(void) |
867 | 83469015 | bellard | { |
868 | 83469015 | bellard | env->tl--; |
869 | 83469015 | bellard | env->pc = env->tnpc[env->tl]; |
870 | 83469015 | bellard | env->npc = env->tnpc[env->tl] + 4;
|
871 | 83469015 | bellard | PUT_CCR(env, env->tstate[env->tl] >> 32);
|
872 | 83469015 | bellard | env->asi = (env->tstate[env->tl] >> 24) & 0xff; |
873 | 83469015 | bellard | env->pstate = (env->tstate[env->tl] >> 8) & 0xfff; |
874 | 17d996e1 | blueswir1 | PUT_CWP64(env, env->tstate[env->tl] & 0xff);
|
875 | 83469015 | bellard | } |
876 | 83469015 | bellard | |
877 | 83469015 | bellard | void do_retry(void) |
878 | 83469015 | bellard | { |
879 | 83469015 | bellard | env->tl--; |
880 | 83469015 | bellard | env->pc = env->tpc[env->tl]; |
881 | 83469015 | bellard | env->npc = env->tnpc[env->tl]; |
882 | 83469015 | bellard | PUT_CCR(env, env->tstate[env->tl] >> 32);
|
883 | 83469015 | bellard | env->asi = (env->tstate[env->tl] >> 24) & 0xff; |
884 | 83469015 | bellard | env->pstate = (env->tstate[env->tl] >> 8) & 0xfff; |
885 | 17d996e1 | blueswir1 | PUT_CWP64(env, env->tstate[env->tl] & 0xff);
|
886 | 83469015 | bellard | } |
887 | 3475187d | bellard | #endif
|
888 | ee5bbe38 | bellard | |
889 | ee5bbe38 | bellard | void set_cwp(int new_cwp) |
890 | ee5bbe38 | bellard | { |
891 | ee5bbe38 | bellard | /* put the modified wrap registers at their proper location */
|
892 | ee5bbe38 | bellard | if (env->cwp == (NWINDOWS - 1)) |
893 | ee5bbe38 | bellard | memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
|
894 | ee5bbe38 | bellard | env->cwp = new_cwp; |
895 | ee5bbe38 | bellard | /* put the wrap registers at their temporary location */
|
896 | ee5bbe38 | bellard | if (new_cwp == (NWINDOWS - 1)) |
897 | ee5bbe38 | bellard | memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
|
898 | ee5bbe38 | bellard | env->regwptr = env->regbase + (new_cwp * 16);
|
899 | ee5bbe38 | bellard | REGWPTR = env->regwptr; |
900 | ee5bbe38 | bellard | } |
901 | ee5bbe38 | bellard | |
902 | ee5bbe38 | bellard | void cpu_set_cwp(CPUState *env1, int new_cwp) |
903 | ee5bbe38 | bellard | { |
904 | ee5bbe38 | bellard | CPUState *saved_env; |
905 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
906 | ee5bbe38 | bellard | target_ulong *saved_regwptr; |
907 | ee5bbe38 | bellard | #endif
|
908 | ee5bbe38 | bellard | |
909 | ee5bbe38 | bellard | saved_env = env; |
910 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
911 | ee5bbe38 | bellard | saved_regwptr = REGWPTR; |
912 | ee5bbe38 | bellard | #endif
|
913 | ee5bbe38 | bellard | env = env1; |
914 | ee5bbe38 | bellard | set_cwp(new_cwp); |
915 | ee5bbe38 | bellard | env = saved_env; |
916 | ee5bbe38 | bellard | #ifdef reg_REGWPTR
|
917 | ee5bbe38 | bellard | REGWPTR = saved_regwptr; |
918 | ee5bbe38 | bellard | #endif
|
919 | ee5bbe38 | bellard | } |
920 | ee5bbe38 | bellard | |
921 | ee5bbe38 | bellard | #ifdef TARGET_SPARC64
|
922 | ee5bbe38 | bellard | void do_interrupt(int intno) |
923 | ee5bbe38 | bellard | { |
924 | ee5bbe38 | bellard | #ifdef DEBUG_PCALL
|
925 | ee5bbe38 | bellard | if (loglevel & CPU_LOG_INT) {
|
926 | ee5bbe38 | bellard | static int count; |
927 | 26a76461 | bellard | fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n", |
928 | ee5bbe38 | bellard | count, intno, |
929 | ee5bbe38 | bellard | env->pc, |
930 | ee5bbe38 | bellard | env->npc, env->regwptr[6]);
|
931 | ee5bbe38 | bellard | cpu_dump_state(env, logfile, fprintf, 0);
|
932 | ee5bbe38 | bellard | #if 0
|
933 | ee5bbe38 | bellard | {
|
934 | ee5bbe38 | bellard | int i;
|
935 | ee5bbe38 | bellard | uint8_t *ptr;
|
936 | ee5bbe38 | bellard | |
937 | ee5bbe38 | bellard | fprintf(logfile, " code=");
|
938 | ee5bbe38 | bellard | ptr = (uint8_t *)env->pc;
|
939 | ee5bbe38 | bellard | for(i = 0; i < 16; i++) {
|
940 | ee5bbe38 | bellard | fprintf(logfile, " %02x", ldub(ptr + i));
|
941 | ee5bbe38 | bellard | }
|
942 | ee5bbe38 | bellard | fprintf(logfile, "\n");
|
943 | ee5bbe38 | bellard | }
|
944 | ee5bbe38 | bellard | #endif
|
945 | ee5bbe38 | bellard | count++; |
946 | ee5bbe38 | bellard | } |
947 | ee5bbe38 | bellard | #endif
|
948 | ee5bbe38 | bellard | #if !defined(CONFIG_USER_ONLY)
|
949 | 83469015 | bellard | if (env->tl == MAXTL) {
|
950 | c68ea704 | bellard | cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
|
951 | ee5bbe38 | bellard | return;
|
952 | ee5bbe38 | bellard | } |
953 | ee5bbe38 | bellard | #endif
|
954 | ee5bbe38 | bellard | env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | |
955 | 17d996e1 | blueswir1 | ((env->pstate & 0xfff) << 8) | GET_CWP64(env); |
956 | ee5bbe38 | bellard | env->tpc[env->tl] = env->pc; |
957 | ee5bbe38 | bellard | env->tnpc[env->tl] = env->npc; |
958 | ee5bbe38 | bellard | env->tt[env->tl] = intno; |
959 | 83469015 | bellard | env->pstate = PS_PEF | PS_PRIV | PS_AG; |
960 | 83469015 | bellard | env->tbr &= ~0x7fffULL;
|
961 | 83469015 | bellard | env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); |
962 | 83469015 | bellard | if (env->tl < MAXTL - 1) { |
963 | 83469015 | bellard | env->tl++; |
964 | 83469015 | bellard | } else {
|
965 | 83469015 | bellard | env->pstate |= PS_RED; |
966 | 83469015 | bellard | if (env->tl != MAXTL)
|
967 | 83469015 | bellard | env->tl++; |
968 | 83469015 | bellard | } |
969 | ee5bbe38 | bellard | env->pc = env->tbr; |
970 | ee5bbe38 | bellard | env->npc = env->pc + 4;
|
971 | ee5bbe38 | bellard | env->exception_index = 0;
|
972 | ee5bbe38 | bellard | } |
973 | ee5bbe38 | bellard | #else
|
974 | ee5bbe38 | bellard | void do_interrupt(int intno) |
975 | ee5bbe38 | bellard | { |
976 | ee5bbe38 | bellard | int cwp;
|
977 | ee5bbe38 | bellard | |
978 | ee5bbe38 | bellard | #ifdef DEBUG_PCALL
|
979 | ee5bbe38 | bellard | if (loglevel & CPU_LOG_INT) {
|
980 | ee5bbe38 | bellard | static int count; |
981 | ee5bbe38 | bellard | fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
|
982 | ee5bbe38 | bellard | count, intno, |
983 | ee5bbe38 | bellard | env->pc, |
984 | ee5bbe38 | bellard | env->npc, env->regwptr[6]);
|
985 | ee5bbe38 | bellard | cpu_dump_state(env, logfile, fprintf, 0);
|
986 | ee5bbe38 | bellard | #if 0
|
987 | ee5bbe38 | bellard | {
|
988 | ee5bbe38 | bellard | int i;
|
989 | ee5bbe38 | bellard | uint8_t *ptr;
|
990 | ee5bbe38 | bellard | |
991 | ee5bbe38 | bellard | fprintf(logfile, " code=");
|
992 | ee5bbe38 | bellard | ptr = (uint8_t *)env->pc;
|
993 | ee5bbe38 | bellard | for(i = 0; i < 16; i++) {
|
994 | ee5bbe38 | bellard | fprintf(logfile, " %02x", ldub(ptr + i));
|
995 | ee5bbe38 | bellard | }
|
996 | ee5bbe38 | bellard | fprintf(logfile, "\n");
|
997 | ee5bbe38 | bellard | }
|
998 | ee5bbe38 | bellard | #endif
|
999 | ee5bbe38 | bellard | count++; |
1000 | ee5bbe38 | bellard | } |
1001 | ee5bbe38 | bellard | #endif
|
1002 | ee5bbe38 | bellard | #if !defined(CONFIG_USER_ONLY)
|
1003 | ee5bbe38 | bellard | if (env->psret == 0) { |
1004 | c68ea704 | bellard | cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
|
1005 | ee5bbe38 | bellard | return;
|
1006 | ee5bbe38 | bellard | } |
1007 | ee5bbe38 | bellard | #endif
|
1008 | ee5bbe38 | bellard | env->psret = 0;
|
1009 | ee5bbe38 | bellard | cwp = (env->cwp - 1) & (NWINDOWS - 1); |
1010 | ee5bbe38 | bellard | set_cwp(cwp); |
1011 | ee5bbe38 | bellard | env->regwptr[9] = env->pc;
|
1012 | ee5bbe38 | bellard | env->regwptr[10] = env->npc;
|
1013 | ee5bbe38 | bellard | env->psrps = env->psrs; |
1014 | ee5bbe38 | bellard | env->psrs = 1;
|
1015 | ee5bbe38 | bellard | env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
|
1016 | ee5bbe38 | bellard | env->pc = env->tbr; |
1017 | ee5bbe38 | bellard | env->npc = env->pc + 4;
|
1018 | ee5bbe38 | bellard | env->exception_index = 0;
|
1019 | ee5bbe38 | bellard | } |
1020 | ee5bbe38 | bellard | #endif
|
1021 | ee5bbe38 | bellard | |
1022 | ee5bbe38 | bellard | #if !defined(CONFIG_USER_ONLY)
|
1023 | ee5bbe38 | bellard | |
1024 | d2889a3e | blueswir1 | static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
1025 | d2889a3e | blueswir1 | void *retaddr);
|
1026 | d2889a3e | blueswir1 | |
1027 | ee5bbe38 | bellard | #define MMUSUFFIX _mmu
|
1028 | d2889a3e | blueswir1 | #define ALIGNED_ONLY
|
1029 | ee5bbe38 | bellard | #define GETPC() (__builtin_return_address(0)) |
1030 | ee5bbe38 | bellard | |
1031 | ee5bbe38 | bellard | #define SHIFT 0 |
1032 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1033 | ee5bbe38 | bellard | |
1034 | ee5bbe38 | bellard | #define SHIFT 1 |
1035 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1036 | ee5bbe38 | bellard | |
1037 | ee5bbe38 | bellard | #define SHIFT 2 |
1038 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1039 | ee5bbe38 | bellard | |
1040 | ee5bbe38 | bellard | #define SHIFT 3 |
1041 | ee5bbe38 | bellard | #include "softmmu_template.h" |
1042 | ee5bbe38 | bellard | |
1043 | d2889a3e | blueswir1 | static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
1044 | d2889a3e | blueswir1 | void *retaddr)
|
1045 | d2889a3e | blueswir1 | { |
1046 | 94554550 | blueswir1 | #ifdef DEBUG_UNALIGNED
|
1047 | 94554550 | blueswir1 | printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
|
1048 | 94554550 | blueswir1 | #endif
|
1049 | 94554550 | blueswir1 | raise_exception(TT_UNALIGNED); |
1050 | d2889a3e | blueswir1 | } |
1051 | ee5bbe38 | bellard | |
1052 | ee5bbe38 | bellard | /* try to fill the TLB and return an exception if error. If retaddr is
|
1053 | ee5bbe38 | bellard | NULL, it means that the function was called in C code (i.e. not
|
1054 | ee5bbe38 | bellard | from generated code or from helper.c) */
|
1055 | ee5bbe38 | bellard | /* XXX: fix it to restore all registers */
|
1056 | ee5bbe38 | bellard | void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) |
1057 | ee5bbe38 | bellard | { |
1058 | ee5bbe38 | bellard | TranslationBlock *tb; |
1059 | ee5bbe38 | bellard | int ret;
|
1060 | ee5bbe38 | bellard | unsigned long pc; |
1061 | ee5bbe38 | bellard | CPUState *saved_env; |
1062 | ee5bbe38 | bellard | |
1063 | ee5bbe38 | bellard | /* XXX: hack to restore env in all cases, even if not called from
|
1064 | ee5bbe38 | bellard | generated code */
|
1065 | ee5bbe38 | bellard | saved_env = env; |
1066 | ee5bbe38 | bellard | env = cpu_single_env; |
1067 | ee5bbe38 | bellard | |
1068 | ee5bbe38 | bellard | ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
|
1069 | ee5bbe38 | bellard | if (ret) {
|
1070 | ee5bbe38 | bellard | if (retaddr) {
|
1071 | ee5bbe38 | bellard | /* now we have a real cpu fault */
|
1072 | ee5bbe38 | bellard | pc = (unsigned long)retaddr; |
1073 | ee5bbe38 | bellard | tb = tb_find_pc(pc); |
1074 | ee5bbe38 | bellard | if (tb) {
|
1075 | ee5bbe38 | bellard | /* the PC is inside the translated code. It means that we have
|
1076 | ee5bbe38 | bellard | a virtual CPU fault */
|
1077 | ee5bbe38 | bellard | cpu_restore_state(tb, env, pc, (void *)T2);
|
1078 | ee5bbe38 | bellard | } |
1079 | ee5bbe38 | bellard | } |
1080 | ee5bbe38 | bellard | cpu_loop_exit(); |
1081 | ee5bbe38 | bellard | } |
1082 | ee5bbe38 | bellard | env = saved_env; |
1083 | ee5bbe38 | bellard | } |
1084 | ee5bbe38 | bellard | |
1085 | ee5bbe38 | bellard | #endif
|
1086 | 6c36d3fa | blueswir1 | |
1087 | 6c36d3fa | blueswir1 | #ifndef TARGET_SPARC64
|
1088 | 5dcb6b91 | blueswir1 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
1089 | 6c36d3fa | blueswir1 | int is_asi)
|
1090 | 6c36d3fa | blueswir1 | { |
1091 | 6c36d3fa | blueswir1 | CPUState *saved_env; |
1092 | 6c36d3fa | blueswir1 | |
1093 | 6c36d3fa | blueswir1 | /* XXX: hack to restore env in all cases, even if not called from
|
1094 | 6c36d3fa | blueswir1 | generated code */
|
1095 | 6c36d3fa | blueswir1 | saved_env = env; |
1096 | 6c36d3fa | blueswir1 | env = cpu_single_env; |
1097 | 6c36d3fa | blueswir1 | if (env->mmuregs[3]) /* Fault status register */ |
1098 | 6c36d3fa | blueswir1 | env->mmuregs[3] = 1; /* overflow (not read before another fault) */ |
1099 | 6c36d3fa | blueswir1 | if (is_asi)
|
1100 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 16; |
1101 | 6c36d3fa | blueswir1 | if (env->psrs)
|
1102 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 5; |
1103 | 6c36d3fa | blueswir1 | if (is_exec)
|
1104 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 6; |
1105 | 6c36d3fa | blueswir1 | if (is_write)
|
1106 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= 1 << 7; |
1107 | 6c36d3fa | blueswir1 | env->mmuregs[3] |= (5 << 2) | 2; |
1108 | 6c36d3fa | blueswir1 | env->mmuregs[4] = addr; /* Fault address register */ |
1109 | 6c36d3fa | blueswir1 | if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { |
1110 | 6c36d3fa | blueswir1 | #ifdef DEBUG_UNASSIGNED
|
1111 | 5dcb6b91 | blueswir1 | printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx |
1112 | 6c36d3fa | blueswir1 | "\n", addr, env->pc);
|
1113 | 6c36d3fa | blueswir1 | #endif
|
1114 | 1b2e93c1 | blueswir1 | if (is_exec)
|
1115 | 1b2e93c1 | blueswir1 | raise_exception(TT_CODE_ACCESS); |
1116 | 1b2e93c1 | blueswir1 | else
|
1117 | 1b2e93c1 | blueswir1 | raise_exception(TT_DATA_ACCESS); |
1118 | 6c36d3fa | blueswir1 | } |
1119 | 6c36d3fa | blueswir1 | env = saved_env; |
1120 | 6c36d3fa | blueswir1 | } |
1121 | 6c36d3fa | blueswir1 | #else
|
1122 | 5dcb6b91 | blueswir1 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
1123 | 6c36d3fa | blueswir1 | int is_asi)
|
1124 | 6c36d3fa | blueswir1 | { |
1125 | 6c36d3fa | blueswir1 | #ifdef DEBUG_UNASSIGNED
|
1126 | 6c36d3fa | blueswir1 | CPUState *saved_env; |
1127 | 6c36d3fa | blueswir1 | |
1128 | 6c36d3fa | blueswir1 | /* XXX: hack to restore env in all cases, even if not called from
|
1129 | 6c36d3fa | blueswir1 | generated code */
|
1130 | 6c36d3fa | blueswir1 | saved_env = env; |
1131 | 6c36d3fa | blueswir1 | env = cpu_single_env; |
1132 | 5dcb6b91 | blueswir1 | printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n", |
1133 | 6c36d3fa | blueswir1 | addr, env->pc); |
1134 | 6c36d3fa | blueswir1 | env = saved_env; |
1135 | 6c36d3fa | blueswir1 | #endif
|
1136 | 1b2e93c1 | blueswir1 | if (is_exec)
|
1137 | 1b2e93c1 | blueswir1 | raise_exception(TT_CODE_ACCESS); |
1138 | 1b2e93c1 | blueswir1 | else
|
1139 | 1b2e93c1 | blueswir1 | raise_exception(TT_DATA_ACCESS); |
1140 | 6c36d3fa | blueswir1 | } |
1141 | 6c36d3fa | blueswir1 | #endif
|
1142 | 20c9f095 | blueswir1 | |
1143 | 20c9f095 | blueswir1 | #ifdef TARGET_SPARC64
|
1144 | 20c9f095 | blueswir1 | void do_tick_set_count(void *opaque, uint64_t count) |
1145 | 20c9f095 | blueswir1 | { |
1146 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1147 | 20c9f095 | blueswir1 | ptimer_set_count(opaque, -count); |
1148 | d8bdf5fa | blueswir1 | #endif
|
1149 | 20c9f095 | blueswir1 | } |
1150 | 20c9f095 | blueswir1 | |
1151 | 20c9f095 | blueswir1 | uint64_t do_tick_get_count(void *opaque)
|
1152 | 20c9f095 | blueswir1 | { |
1153 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1154 | 20c9f095 | blueswir1 | return -ptimer_get_count(opaque);
|
1155 | d8bdf5fa | blueswir1 | #else
|
1156 | d8bdf5fa | blueswir1 | return 0; |
1157 | d8bdf5fa | blueswir1 | #endif
|
1158 | 20c9f095 | blueswir1 | } |
1159 | 20c9f095 | blueswir1 | |
1160 | 20c9f095 | blueswir1 | void do_tick_set_limit(void *opaque, uint64_t limit) |
1161 | 20c9f095 | blueswir1 | { |
1162 | d8bdf5fa | blueswir1 | #if !defined(CONFIG_USER_ONLY)
|
1163 | 20c9f095 | blueswir1 | ptimer_set_limit(opaque, -limit, 0);
|
1164 | d8bdf5fa | blueswir1 | #endif
|
1165 | 20c9f095 | blueswir1 | } |
1166 | 20c9f095 | blueswir1 | #endif |