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/>.
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
)
33 env
->exception_index
= EXCP_ITB_MISS
;
35 env
->exception_index
= EXCP_DFAULT
;
36 env
->ipr
[IPR_EXC_ADDR
] = address
;
41 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
46 void do_interrupt (CPUState
*env
)
48 env
->exception_index
= -1;
53 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
58 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
59 int mmu_idx
, int is_softmmu
)
64 /* Instruction translation buffer miss */
65 env
->exception_index
= EXCP_ITB_MISS
;
67 if (env
->ipr
[IPR_EXC_ADDR
] & 1)
68 env
->exception_index
= EXCP_DTB_MISS_PAL
;
70 env
->exception_index
= EXCP_DTB_MISS_NATIVE
;
71 opc
= (ldl_code(env
->pc
) >> 21) << 4;
77 env
->ipr
[IPR_MM_STAT
] = opc
;
83 int cpu_alpha_mfpr (CPUState
*env
, int iprn
, uint64_t *valp
)
88 hwpcb
= env
->ipr
[IPR_PCBB
];
91 if (env
->features
& FEATURE_ASN
)
92 *valp
= env
->ipr
[IPR_ASN
];
97 *valp
= ((int64_t)(env
->ipr
[IPR_ASTEN
] << 60)) >> 60;
100 *valp
= ((int64_t)(env
->ipr
[IPR_ASTSR
] << 60)) >> 60;
107 if (env
->features
& FEATURE_SPS
)
108 *valp
= env
->ipr
[IPR_ESP
];
110 *valp
= ldq_raw(hwpcb
+ 8);
113 *valp
= ((int64_t)(env
->ipr
[IPR_FEN
] << 63)) >> 63;
120 *valp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
123 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
126 if (env
->features
& FEATURE_SPS
)
127 *valp
= env
->ipr
[IPR_KSP
];
129 *valp
= ldq_raw(hwpcb
+ 0);
133 *valp
= ((int64_t)(env
->ipr
[IPR_MCES
] << 59)) >> 59;
136 /* Implementation specific */
140 *valp
= ((int64_t)env
->ipr
[IPR_PCBB
] << 16) >> 16;
143 *valp
= env
->ipr
[IPR_PRBR
];
146 *valp
= env
->ipr
[IPR_PTBR
];
149 *valp
= (int64_t)((int32_t)env
->ipr
[IPR_SCBB
]);
156 *valp
= (int64_t)((int16_t)env
->ipr
[IPR_SISR
]);
158 if (env
->features
& FEATURE_SPS
)
159 *valp
= env
->ipr
[IPR_SSP
];
161 *valp
= ldq_raw(hwpcb
+ 16);
164 if (env
->features
& FEATURE_VIRBND
)
165 *valp
= env
->ipr
[IPR_SYSPTBR
];
170 if ((env
->features
& FEATURE_TBCHK
)) {
199 if (env
->features
& FEATURE_SPS
)
200 *valp
= env
->ipr
[IPR_USP
];
202 *valp
= ldq_raw(hwpcb
+ 24);
205 if (env
->features
& FEATURE_VIRBND
)
206 *valp
= env
->ipr
[IPR_VIRBND
];
211 *valp
= env
->ipr
[IPR_VPTB
];
214 *valp
= env
->ipr
[IPR_WHAMI
];
225 int cpu_alpha_mtpr (CPUState
*env
, int iprn
, uint64_t val
, uint64_t *oldvalp
)
227 uint64_t hwpcb
, tmp64
;
231 hwpcb
= env
->ipr
[IPR_PCBB
];
238 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTEN
] << 4)) >> 4;
241 tmp8
|= (val
>> 4) & 0xF;
242 env
->ipr
[IPR_ASTEN
] &= ~0xF;
243 env
->ipr
[IPR_ASTEN
] |= tmp8
;
247 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTSR
] << 4)) >> 4;
250 tmp8
|= (val
>> 4) & 0xF;
251 env
->ipr
[IPR_ASTSR
] &= ~0xF;
252 env
->ipr
[IPR_ASTSR
] |= tmp8
;
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
);
263 if (env
->features
& FEATURE_SPS
)
264 env
->ipr
[IPR_ESP
] = val
;
266 stq_raw(hwpcb
+ 8, val
);
269 env
->ipr
[IPR_FEN
] = val
& 1;
270 tmp64
= ldq_raw(hwpcb
+ 56);
273 stq_raw(hwpcb
+ 56, tmp64
);
276 /* XXX: TODO: Send IRQ to CPU #ir[16] */
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_ */
286 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
289 if (env
->features
& FEATURE_SPS
)
290 env
->ipr
[IPR_KSP
] = val
;
292 stq_raw(hwpcb
+ 0, val
);
296 env
->ipr
[IPR_MCES
] &= ~((val
& 0x7) | 0x18);
297 env
->ipr
[IPR_MCES
] |= val
& 0x18;
300 /* Implementation specific */
309 env
->ipr
[IPR_PRBR
] = val
;
316 env
->ipr
[IPR_SCBB
] = (uint32_t)val
;
320 env
->ipr
[IPR_SISR
] |= 1 << (val
& 0xF);
321 /* XXX: request a software interrupt _now_ */
329 if (env
->features
& FEATURE_SPS
)
330 env
->ipr
[IPR_SSP
] = val
;
332 stq_raw(hwpcb
+ 16, val
);
335 if (env
->features
& FEATURE_VIRBND
)
336 env
->ipr
[IPR_SYSPTBR
] = val
;
350 tlb_flush_page(env
, val
);
353 tlb_flush_page(env
, val
);
356 tlb_flush_page(env
, val
);
359 if (env
->features
& FEATURE_SPS
)
360 env
->ipr
[IPR_USP
] = val
;
362 stq_raw(hwpcb
+ 24, val
);
365 if (env
->features
& FEATURE_VIRBND
)
366 env
->ipr
[IPR_VIRBND
] = val
;
371 env
->ipr
[IPR_VPTB
] = val
;
386 void do_interrupt (CPUState
*env
)
390 env
->ipr
[IPR_EXC_ADDR
] = env
->pc
| 1;
391 excp
= env
->exception_index
;
392 env
->exception_index
= 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
;
399 /* We use emulated PALcode */
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 */
409 void cpu_dump_state (CPUState
*env
, FILE *f
,
410 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
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",
421 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS " TARGET_FMT_lx
"\n",
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
]);
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
])));
434 cpu_fprintf(f
, "\n");
436 cpu_fprintf(f
, "\nlock " TARGET_FMT_lx
"\n", env
->lock
);