]> git.proxmox.com Git - qemu.git/blame - target-alpha/helper.c
target-alpha: All ISA checks to use TB->FLAGS.
[qemu.git] / target-alpha / helper.c
CommitLineData
4c9649a9
JM
1/*
2 * Alpha emulation cpu helpers for qemu.
5fafdf24 3 *
4c9649a9
JM
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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
4c9649a9
JM
18 */
19
20#include <stdint.h>
21#include <stdlib.h>
22#include <stdio.h>
23
24#include "cpu.h"
25#include "exec-all.h"
ba0e276d
RH
26#include "softfloat.h"
27
28uint64_t cpu_alpha_load_fpcr (CPUState *env)
29{
8443effb
RH
30 uint64_t r = 0;
31 uint8_t t;
32
33 t = env->fpcr_exc_status;
34 if (t) {
35 r = FPCR_SUM;
36 if (t & float_flag_invalid) {
37 r |= FPCR_INV;
38 }
39 if (t & float_flag_divbyzero) {
40 r |= FPCR_DZE;
41 }
42 if (t & float_flag_overflow) {
43 r |= FPCR_OVF;
44 }
45 if (t & float_flag_underflow) {
46 r |= FPCR_UNF;
47 }
48 if (t & float_flag_inexact) {
49 r |= FPCR_INE;
50 }
51 }
52
53 t = env->fpcr_exc_mask;
54 if (t & float_flag_invalid) {
55 r |= FPCR_INVD;
56 }
57 if (t & float_flag_divbyzero) {
58 r |= FPCR_DZED;
59 }
60 if (t & float_flag_overflow) {
61 r |= FPCR_OVFD;
62 }
63 if (t & float_flag_underflow) {
64 r |= FPCR_UNFD;
65 }
66 if (t & float_flag_inexact) {
67 r |= FPCR_INED;
68 }
69
70 switch (env->fpcr_dyn_round) {
ba0e276d 71 case float_round_nearest_even:
8443effb 72 r |= FPCR_DYN_NORMAL;
ba0e276d
RH
73 break;
74 case float_round_down:
8443effb 75 r |= FPCR_DYN_MINUS;
ba0e276d
RH
76 break;
77 case float_round_up:
8443effb 78 r |= FPCR_DYN_PLUS;
ba0e276d
RH
79 break;
80 case float_round_to_zero:
8443effb 81 r |= FPCR_DYN_CHOPPED;
ba0e276d
RH
82 break;
83 }
8443effb
RH
84
85 if (env->fpcr_dnz) {
86 r |= FPCR_DNZ;
87 }
88 if (env->fpcr_dnod) {
89 r |= FPCR_DNOD;
90 }
91 if (env->fpcr_undz) {
92 r |= FPCR_UNDZ;
93 }
94
95 return r;
ba0e276d
RH
96}
97
98void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
99{
8443effb
RH
100 uint8_t t;
101
102 t = 0;
103 if (val & FPCR_INV) {
104 t |= float_flag_invalid;
105 }
106 if (val & FPCR_DZE) {
107 t |= float_flag_divbyzero;
108 }
109 if (val & FPCR_OVF) {
110 t |= float_flag_overflow;
111 }
112 if (val & FPCR_UNF) {
113 t |= float_flag_underflow;
114 }
115 if (val & FPCR_INE) {
116 t |= float_flag_inexact;
117 }
118 env->fpcr_exc_status = t;
119
120 t = 0;
121 if (val & FPCR_INVD) {
122 t |= float_flag_invalid;
123 }
124 if (val & FPCR_DZED) {
125 t |= float_flag_divbyzero;
126 }
127 if (val & FPCR_OVFD) {
128 t |= float_flag_overflow;
129 }
130 if (val & FPCR_UNFD) {
131 t |= float_flag_underflow;
132 }
133 if (val & FPCR_INED) {
134 t |= float_flag_inexact;
135 }
136 env->fpcr_exc_mask = t;
137
138 switch (val & FPCR_DYN_MASK) {
139 case FPCR_DYN_CHOPPED:
140 t = float_round_to_zero;
ba0e276d 141 break;
8443effb
RH
142 case FPCR_DYN_MINUS:
143 t = float_round_down;
ba0e276d 144 break;
8443effb
RH
145 case FPCR_DYN_NORMAL:
146 t = float_round_nearest_even;
ba0e276d 147 break;
8443effb
RH
148 case FPCR_DYN_PLUS:
149 t = float_round_up;
ba0e276d
RH
150 break;
151 }
8443effb
RH
152 env->fpcr_dyn_round = t;
153
154 env->fpcr_flush_to_zero
155 = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
156
157 env->fpcr_dnz = (val & FPCR_DNZ) != 0;
158 env->fpcr_dnod = (val & FPCR_DNOD) != 0;
159 env->fpcr_undz = (val & FPCR_UNDZ) != 0;
ba0e276d 160}
4c9649a9 161
5fafdf24 162#if defined(CONFIG_USER_ONLY)
4c9649a9 163int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 164 int mmu_idx, int is_softmmu)
4c9649a9 165{
07b6c13b 166 env->exception_index = EXCP_MMFAULT;
129d8aa5 167 env->trap_arg0 = address;
4c9649a9
JM
168 return 1;
169}
4c9649a9 170#else
21d2beaa
RH
171void swap_shadow_regs(CPUState *env)
172{
173 uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
174
175 i0 = env->ir[8];
176 i1 = env->ir[9];
177 i2 = env->ir[10];
178 i3 = env->ir[11];
179 i4 = env->ir[12];
180 i5 = env->ir[13];
181 i6 = env->ir[14];
182 i7 = env->ir[25];
183
184 env->ir[8] = env->shadow[0];
185 env->ir[9] = env->shadow[1];
186 env->ir[10] = env->shadow[2];
187 env->ir[11] = env->shadow[3];
188 env->ir[12] = env->shadow[4];
189 env->ir[13] = env->shadow[5];
190 env->ir[14] = env->shadow[6];
191 env->ir[25] = env->shadow[7];
192
193 env->shadow[0] = i0;
194 env->shadow[1] = i1;
195 env->shadow[2] = i2;
196 env->shadow[3] = i3;
197 env->shadow[4] = i4;
198 env->shadow[5] = i5;
199 env->shadow[6] = i6;
200 env->shadow[7] = i7;
201}
202
c227f099 203target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
4c9649a9
JM
204{
205 return -1;
206}
207
208int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
6ebbf390 209 int mmu_idx, int is_softmmu)
4c9649a9 210{
129d8aa5 211 return 0;
4c9649a9 212}
3a6fa678 213#endif /* USER_ONLY */
4c9649a9
JM
214
215void do_interrupt (CPUState *env)
216{
3a6fa678
RH
217 int i = env->exception_index;
218
219 if (qemu_loglevel_mask(CPU_LOG_INT)) {
220 static int count;
221 const char *name = "<unknown>";
222
223 switch (i) {
224 case EXCP_RESET:
225 name = "reset";
226 break;
227 case EXCP_MCHK:
228 name = "mchk";
229 break;
230 case EXCP_SMP_INTERRUPT:
231 name = "smp_interrupt";
232 break;
233 case EXCP_CLK_INTERRUPT:
234 name = "clk_interrupt";
235 break;
236 case EXCP_DEV_INTERRUPT:
237 name = "dev_interrupt";
238 break;
239 case EXCP_MMFAULT:
240 name = "mmfault";
241 break;
242 case EXCP_UNALIGN:
243 name = "unalign";
244 break;
245 case EXCP_OPCDEC:
246 name = "opcdec";
247 break;
248 case EXCP_ARITH:
249 name = "arith";
250 break;
251 case EXCP_FEN:
252 name = "fen";
253 break;
254 case EXCP_CALL_PAL:
255 name = "call_pal";
256 break;
257 case EXCP_STL_C:
258 name = "stl_c";
259 break;
260 case EXCP_STQ_C:
261 name = "stq_c";
262 break;
263 }
264 qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n",
265 ++count, name, env->error_code, env->pc, env->ir[IR_SP]);
266 }
267
268 env->exception_index = -1;
269
270#if !defined(CONFIG_USER_ONLY)
271 switch (i) {
272 case EXCP_RESET:
273 i = 0x0000;
274 break;
275 case EXCP_MCHK:
276 i = 0x0080;
277 break;
278 case EXCP_SMP_INTERRUPT:
279 i = 0x0100;
280 break;
281 case EXCP_CLK_INTERRUPT:
282 i = 0x0180;
283 break;
284 case EXCP_DEV_INTERRUPT:
285 i = 0x0200;
286 break;
287 case EXCP_MMFAULT:
288 i = 0x0280;
289 break;
290 case EXCP_UNALIGN:
291 i = 0x0300;
292 break;
293 case EXCP_OPCDEC:
294 i = 0x0380;
295 break;
296 case EXCP_ARITH:
297 i = 0x0400;
298 break;
299 case EXCP_FEN:
300 i = 0x0480;
301 break;
302 case EXCP_CALL_PAL:
303 i = env->error_code;
304 /* There are 64 entry points for both privileged and unprivileged,
305 with bit 0x80 indicating unprivileged. Each entry point gets
306 64 bytes to do its job. */
307 if (i & 0x80) {
308 i = 0x2000 + (i - 0x80) * 64;
309 } else {
310 i = 0x1000 + i * 64;
311 }
312 break;
313 default:
314 cpu_abort(env, "Unhandled CPU exception");
315 }
316
317 /* Remember where the exception happened. Emulate real hardware in
318 that the low bit of the PC indicates PALmode. */
319 env->exc_addr = env->pc | env->pal_mode;
320
321 /* Continue execution at the PALcode entry point. */
322 env->pc = env->palbr + i;
323
324 /* Switch to PALmode. */
21d2beaa
RH
325 if (!env->pal_mode) {
326 env->pal_mode = 1;
327 swap_shadow_regs(env);
328 }
3a6fa678 329#endif /* !USER_ONLY */
4c9649a9 330}
4c9649a9 331
9a78eead 332void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
4c9649a9
JM
333 int flags)
334{
b55266b5 335 static const char *linux_reg_names[] = {
4c9649a9
JM
336 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
337 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
338 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
339 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
340 };
341 int i;
342
129d8aa5 343 cpu_fprintf(f, " PC " TARGET_FMT_lx " PS %02x\n",
4c9649a9
JM
344 env->pc, env->ps);
345 for (i = 0; i < 31; i++) {
346 cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
347 linux_reg_names[i], env->ir[i]);
348 if ((i % 3) == 2)
349 cpu_fprintf(f, "\n");
350 }
6910b8f6
RH
351
352 cpu_fprintf(f, "lock_a " TARGET_FMT_lx " lock_v " TARGET_FMT_lx "\n",
353 env->lock_addr, env->lock_value);
354
4c9649a9
JM
355 for (i = 0; i < 31; i++) {
356 cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
357 *((uint64_t *)(&env->fir[i])));
358 if ((i % 3) == 2)
359 cpu_fprintf(f, "\n");
360 }
6910b8f6 361 cpu_fprintf(f, "\n");
4c9649a9 362}