|
|
1.1 root 1: /*
2: * Alpha emulation cpu helpers for qemu.
3: *
4: * Copyright (c) 2007 Jocelyn Mayer
5: *
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.
10: *
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.
15: *
16: * You should have received a copy of the GNU Lesser General Public
1.1.1.3 ! root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19:
20: #include <stdint.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23:
24: #include "cpu.h"
25: #include "exec-all.h"
26:
27: #if defined(CONFIG_USER_ONLY)
28:
29: int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
30: int mmu_idx, int is_softmmu)
31: {
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;
37:
38: return 1;
39: }
40:
41: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
42: {
43: return addr;
44: }
45:
46: void do_interrupt (CPUState *env)
47: {
48: env->exception_index = -1;
49: }
50:
51: #else
52:
53: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
54: {
55: return -1;
56: }
57:
58: int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
59: int mmu_idx, int is_softmmu)
60: {
61: uint32_t opc;
62:
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;
76: }
77: env->ipr[IPR_MM_STAT] = opc;
78: }
79:
80: return 1;
81: }
82:
83: int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
84: {
85: uint64_t hwpcb;
86: int ret = 0;
87:
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);
130: }
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;
176: }
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;
220: }
221:
222: return ret;
223: }
224:
225: int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
226: {
227: uint64_t hwpcb, tmp64;
228: uint8_t tmp8;
229: int ret = 0;
230:
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);
293: }
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_ */
322: }
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;
381: }
382:
383: return ret;
384: }
385:
386: void do_interrupt (CPUState *env)
387: {
388: int excp;
389:
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 */
405: }
406: }
407: #endif
408:
409: void cpu_dump_state (CPUState *env, FILE *f,
410: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
411: int flags)
412: {
1.1.1.2 root 413: static const char *linux_reg_names[] = {
1.1 root 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",
418: };
419: int i;
420:
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");
428: }
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");
435: }
1.1.1.2 root 436: cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock);
1.1 root 437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.