Merge commit 'mst/pci' into staging
[qemu/mdroth.git] / target-alpha / helper.c
blobfcd5841e0129051a49a07380e3eb645966b9770c
1 /*
2 * Alpha emulation cpu helpers for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <stdio.h>
24 #include "cpu.h"
25 #include "exec-all.h"
27 #if defined(CONFIG_USER_ONLY)
29 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
30 int mmu_idx, int is_softmmu)
32 if (rw == 2)
33 env->exception_index = EXCP_ITB_MISS;
34 else
35 env->exception_index = EXCP_DFAULT;
36 env->ipr[IPR_EXC_ADDR] = address;
38 return 1;
41 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
43 return addr;
46 void do_interrupt (CPUState *env)
48 env->exception_index = -1;
51 #else
53 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
55 return -1;
58 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
59 int mmu_idx, int is_softmmu)
61 uint32_t opc;
63 if (rw == 2) {
64 /* Instruction translation buffer miss */
65 env->exception_index = EXCP_ITB_MISS;
66 } else {
67 if (env->ipr[IPR_EXC_ADDR] & 1)
68 env->exception_index = EXCP_DTB_MISS_PAL;
69 else
70 env->exception_index = EXCP_DTB_MISS_NATIVE;
71 opc = (ldl_code(env->pc) >> 21) << 4;
72 if (rw) {
73 opc |= 0x9;
74 } else {
75 opc |= 0x4;
77 env->ipr[IPR_MM_STAT] = opc;
80 return 1;
83 int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
85 uint64_t hwpcb;
86 int ret = 0;
88 hwpcb = env->ipr[IPR_PCBB];
89 switch (iprn) {
90 case IPR_ASN:
91 if (env->features & FEATURE_ASN)
92 *valp = env->ipr[IPR_ASN];
93 else
94 *valp = 0;
95 break;
96 case IPR_ASTEN:
97 *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
98 break;
99 case IPR_ASTSR:
100 *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
101 break;
102 case IPR_DATFX:
103 /* Write only */
104 ret = -1;
105 break;
106 case IPR_ESP:
107 if (env->features & FEATURE_SPS)
108 *valp = env->ipr[IPR_ESP];
109 else
110 *valp = ldq_raw(hwpcb + 8);
111 break;
112 case IPR_FEN:
113 *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
114 break;
115 case IPR_IPIR:
116 /* Write-only */
117 ret = -1;
118 break;
119 case IPR_IPL:
120 *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
121 break;
122 case IPR_KSP:
123 if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
124 ret = -1;
125 } else {
126 if (env->features & FEATURE_SPS)
127 *valp = env->ipr[IPR_KSP];
128 else
129 *valp = ldq_raw(hwpcb + 0);
131 break;
132 case IPR_MCES:
133 *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
134 break;
135 case IPR_PERFMON:
136 /* Implementation specific */
137 *valp = 0;
138 break;
139 case IPR_PCBB:
140 *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
141 break;
142 case IPR_PRBR:
143 *valp = env->ipr[IPR_PRBR];
144 break;
145 case IPR_PTBR:
146 *valp = env->ipr[IPR_PTBR];
147 break;
148 case IPR_SCBB:
149 *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
150 break;
151 case IPR_SIRR:
152 /* Write-only */
153 ret = -1;
154 break;
155 case IPR_SISR:
156 *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
157 case IPR_SSP:
158 if (env->features & FEATURE_SPS)
159 *valp = env->ipr[IPR_SSP];
160 else
161 *valp = ldq_raw(hwpcb + 16);
162 break;
163 case IPR_SYSPTBR:
164 if (env->features & FEATURE_VIRBND)
165 *valp = env->ipr[IPR_SYSPTBR];
166 else
167 ret = -1;
168 break;
169 case IPR_TBCHK:
170 if ((env->features & FEATURE_TBCHK)) {
171 /* XXX: TODO */
172 *valp = 0;
173 ret = -1;
174 } else {
175 ret = -1;
177 break;
178 case IPR_TBIA:
179 /* Write-only */
180 ret = -1;
181 break;
182 case IPR_TBIAP:
183 /* Write-only */
184 ret = -1;
185 break;
186 case IPR_TBIS:
187 /* Write-only */
188 ret = -1;
189 break;
190 case IPR_TBISD:
191 /* Write-only */
192 ret = -1;
193 break;
194 case IPR_TBISI:
195 /* Write-only */
196 ret = -1;
197 break;
198 case IPR_USP:
199 if (env->features & FEATURE_SPS)
200 *valp = env->ipr[IPR_USP];
201 else
202 *valp = ldq_raw(hwpcb + 24);
203 break;
204 case IPR_VIRBND:
205 if (env->features & FEATURE_VIRBND)
206 *valp = env->ipr[IPR_VIRBND];
207 else
208 ret = -1;
209 break;
210 case IPR_VPTB:
211 *valp = env->ipr[IPR_VPTB];
212 break;
213 case IPR_WHAMI:
214 *valp = env->ipr[IPR_WHAMI];
215 break;
216 default:
217 /* Invalid */
218 ret = -1;
219 break;
222 return ret;
225 int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
227 uint64_t hwpcb, tmp64;
228 uint8_t tmp8;
229 int ret = 0;
231 hwpcb = env->ipr[IPR_PCBB];
232 switch (iprn) {
233 case IPR_ASN:
234 /* Read-only */
235 ret = -1;
236 break;
237 case IPR_ASTEN:
238 tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
239 *oldvalp = tmp8;
240 tmp8 &= val & 0xF;
241 tmp8 |= (val >> 4) & 0xF;
242 env->ipr[IPR_ASTEN] &= ~0xF;
243 env->ipr[IPR_ASTEN] |= tmp8;
244 ret = 1;
245 break;
246 case IPR_ASTSR:
247 tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
248 *oldvalp = tmp8;
249 tmp8 &= val & 0xF;
250 tmp8 |= (val >> 4) & 0xF;
251 env->ipr[IPR_ASTSR] &= ~0xF;
252 env->ipr[IPR_ASTSR] |= tmp8;
253 ret = 1;
254 case IPR_DATFX:
255 env->ipr[IPR_DATFX] &= ~0x1;
256 env->ipr[IPR_DATFX] |= val & 1;
257 tmp64 = ldq_raw(hwpcb + 56);
258 tmp64 &= ~0x8000000000000000ULL;
259 tmp64 |= (val & 1) << 63;
260 stq_raw(hwpcb + 56, tmp64);
261 break;
262 case IPR_ESP:
263 if (env->features & FEATURE_SPS)
264 env->ipr[IPR_ESP] = val;
265 else
266 stq_raw(hwpcb + 8, val);
267 break;
268 case IPR_FEN:
269 env->ipr[IPR_FEN] = val & 1;
270 tmp64 = ldq_raw(hwpcb + 56);
271 tmp64 &= ~1;
272 tmp64 |= val & 1;
273 stq_raw(hwpcb + 56, tmp64);
274 break;
275 case IPR_IPIR:
276 /* XXX: TODO: Send IRQ to CPU #ir[16] */
277 break;
278 case IPR_IPL:
279 *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
280 env->ipr[IPR_IPL] &= ~0x1F;
281 env->ipr[IPR_IPL] |= val & 0x1F;
282 /* XXX: may issue an interrupt or ASR _now_ */
283 ret = 1;
284 break;
285 case IPR_KSP:
286 if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
287 ret = -1;
288 } else {
289 if (env->features & FEATURE_SPS)
290 env->ipr[IPR_KSP] = val;
291 else
292 stq_raw(hwpcb + 0, val);
294 break;
295 case IPR_MCES:
296 env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
297 env->ipr[IPR_MCES] |= val & 0x18;
298 break;
299 case IPR_PERFMON:
300 /* Implementation specific */
301 *oldvalp = 0;
302 ret = 1;
303 break;
304 case IPR_PCBB:
305 /* Read-only */
306 ret = -1;
307 break;
308 case IPR_PRBR:
309 env->ipr[IPR_PRBR] = val;
310 break;
311 case IPR_PTBR:
312 /* Read-only */
313 ret = -1;
314 break;
315 case IPR_SCBB:
316 env->ipr[IPR_SCBB] = (uint32_t)val;
317 break;
318 case IPR_SIRR:
319 if (val & 0xF) {
320 env->ipr[IPR_SISR] |= 1 << (val & 0xF);
321 /* XXX: request a software interrupt _now_ */
323 break;
324 case IPR_SISR:
325 /* Read-only */
326 ret = -1;
327 break;
328 case IPR_SSP:
329 if (env->features & FEATURE_SPS)
330 env->ipr[IPR_SSP] = val;
331 else
332 stq_raw(hwpcb + 16, val);
333 break;
334 case IPR_SYSPTBR:
335 if (env->features & FEATURE_VIRBND)
336 env->ipr[IPR_SYSPTBR] = val;
337 else
338 ret = -1;
339 case IPR_TBCHK:
340 /* Read-only */
341 ret = -1;
342 break;
343 case IPR_TBIA:
344 tlb_flush(env, 1);
345 break;
346 case IPR_TBIAP:
347 tlb_flush(env, 1);
348 break;
349 case IPR_TBIS:
350 tlb_flush_page(env, val);
351 break;
352 case IPR_TBISD:
353 tlb_flush_page(env, val);
354 break;
355 case IPR_TBISI:
356 tlb_flush_page(env, val);
357 break;
358 case IPR_USP:
359 if (env->features & FEATURE_SPS)
360 env->ipr[IPR_USP] = val;
361 else
362 stq_raw(hwpcb + 24, val);
363 break;
364 case IPR_VIRBND:
365 if (env->features & FEATURE_VIRBND)
366 env->ipr[IPR_VIRBND] = val;
367 else
368 ret = -1;
369 break;
370 case IPR_VPTB:
371 env->ipr[IPR_VPTB] = val;
372 break;
373 case IPR_WHAMI:
374 /* Read-only */
375 ret = -1;
376 break;
377 default:
378 /* Invalid */
379 ret = -1;
380 break;
383 return ret;
386 void do_interrupt (CPUState *env)
388 int excp;
390 env->ipr[IPR_EXC_ADDR] = env->pc | 1;
391 excp = env->exception_index;
392 env->exception_index = 0;
393 env->error_code = 0;
394 /* XXX: disable interrupts and memory mapping */
395 if (env->ipr[IPR_PAL_BASE] != -1ULL) {
396 /* We use native PALcode */
397 env->pc = env->ipr[IPR_PAL_BASE] + excp;
398 } else {
399 /* We use emulated PALcode */
400 call_pal(env);
401 /* Emulate REI */
402 env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
403 env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
404 /* XXX: re-enable interrupts and memory mapping */
407 #endif
409 void cpu_dump_state (CPUState *env, FILE *f,
410 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
411 int flags)
413 static const char *linux_reg_names[] = {
414 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
415 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
416 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
417 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
419 int i;
421 cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n",
422 env->pc, env->ps);
423 for (i = 0; i < 31; i++) {
424 cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
425 linux_reg_names[i], env->ir[i]);
426 if ((i % 3) == 2)
427 cpu_fprintf(f, "\n");
429 cpu_fprintf(f, "\n");
430 for (i = 0; i < 31; i++) {
431 cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
432 *((uint64_t *)(&env->fir[i])));
433 if ((i % 3) == 2)
434 cpu_fprintf(f, "\n");
436 cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock);