4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "qemu-common.h"
23 #include "cpu_loop-common.h"
27 # ifdef TARGET_ABI_MIPSO32
28 # define MIPS_SYSCALL_NUMBER_UNUSED -1
29 static const int8_t mips_syscall_args
[] = {
30 #include "syscall-args-o32.c.inc"
40 static int do_break(CPUMIPSState
*env
, target_siginfo_t
*info
,
48 info
->si_signo
= TARGET_SIGFPE
;
50 info
->si_code
= (code
== BRK_OVERFLOW
) ? FPE_INTOVF
: FPE_INTDIV
;
51 queue_signal(env
, info
->si_signo
, QEMU_SI_FAULT
, &*info
);
55 info
->si_signo
= TARGET_SIGTRAP
;
57 queue_signal(env
, info
->si_signo
, QEMU_SI_FAULT
, &*info
);
65 void cpu_loop(CPUMIPSState
*env
)
67 CPUState
*cs
= env_cpu(env
);
68 target_siginfo_t info
;
71 # ifdef TARGET_ABI_MIPSO32
72 unsigned int syscall_num
;
77 trapnr
= cpu_exec(cs
);
79 process_queued_cpu_work(cs
);
83 env
->active_tc
.PC
+= 4;
84 # ifdef TARGET_ABI_MIPSO32
85 syscall_num
= env
->active_tc
.gpr
[2] - 4000;
86 if (syscall_num
>= sizeof(mips_syscall_args
)) {
87 /* syscall_num is larger that any defined for MIPS O32 */
89 } else if (mips_syscall_args
[syscall_num
] ==
90 MIPS_SYSCALL_NUMBER_UNUSED
) {
91 /* syscall_num belongs to the range not defined for MIPS O32 */
94 /* syscall_num is valid */
97 abi_ulong arg5
= 0, arg6
= 0, arg7
= 0, arg8
= 0;
99 nb_args
= mips_syscall_args
[syscall_num
];
100 sp_reg
= env
->active_tc
.gpr
[29];
102 /* these arguments are taken from the stack */
104 if ((ret
= get_user_ual(arg8
, sp_reg
+ 28)) != 0) {
108 if ((ret
= get_user_ual(arg7
, sp_reg
+ 24)) != 0) {
112 if ((ret
= get_user_ual(arg6
, sp_reg
+ 20)) != 0) {
116 if ((ret
= get_user_ual(arg5
, sp_reg
+ 16)) != 0) {
122 ret
= do_syscall(env
, env
->active_tc
.gpr
[2],
123 env
->active_tc
.gpr
[4],
124 env
->active_tc
.gpr
[5],
125 env
->active_tc
.gpr
[6],
126 env
->active_tc
.gpr
[7],
127 arg5
, arg6
, arg7
, arg8
);
131 ret
= do_syscall(env
, env
->active_tc
.gpr
[2],
132 env
->active_tc
.gpr
[4], env
->active_tc
.gpr
[5],
133 env
->active_tc
.gpr
[6], env
->active_tc
.gpr
[7],
134 env
->active_tc
.gpr
[8], env
->active_tc
.gpr
[9],
135 env
->active_tc
.gpr
[10], env
->active_tc
.gpr
[11]);
137 if (ret
== -TARGET_ERESTARTSYS
) {
138 env
->active_tc
.PC
-= 4;
141 if (ret
== -TARGET_QEMU_ESIGRETURN
) {
142 /* Returning from a successful sigreturn syscall.
143 Avoid clobbering register state. */
146 if ((abi_ulong
)ret
>= (abi_ulong
)-1133) {
147 env
->active_tc
.gpr
[7] = 1; /* error flag */
150 env
->active_tc
.gpr
[7] = 0; /* error flag */
152 env
->active_tc
.gpr
[2] = ret
;
158 info
.si_signo
= TARGET_SIGSEGV
;
160 /* XXX: check env->error_code */
161 info
.si_code
= TARGET_SEGV_MAPERR
;
162 info
._sifields
._sigfault
._addr
= env
->CP0_BadVAddr
;
163 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
167 info
.si_signo
= TARGET_SIGILL
;
170 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
173 /* just indicate that signals should be handled asap */
176 info
.si_signo
= TARGET_SIGTRAP
;
178 info
.si_code
= TARGET_TRAP_BRKPT
;
179 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
182 info
.si_signo
= TARGET_SIGILL
;
184 info
.si_code
= TARGET_ILL_ILLOPC
;
185 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
188 info
.si_signo
= TARGET_SIGFPE
;
190 info
.si_code
= TARGET_FPE_FLTUNK
;
191 if (GET_FP_CAUSE(env
->active_fpu
.fcr31
) & FP_INVALID
) {
192 info
.si_code
= TARGET_FPE_FLTINV
;
193 } else if (GET_FP_CAUSE(env
->active_fpu
.fcr31
) & FP_DIV0
) {
194 info
.si_code
= TARGET_FPE_FLTDIV
;
195 } else if (GET_FP_CAUSE(env
->active_fpu
.fcr31
) & FP_OVERFLOW
) {
196 info
.si_code
= TARGET_FPE_FLTOVF
;
197 } else if (GET_FP_CAUSE(env
->active_fpu
.fcr31
) & FP_UNDERFLOW
) {
198 info
.si_code
= TARGET_FPE_FLTUND
;
199 } else if (GET_FP_CAUSE(env
->active_fpu
.fcr31
) & FP_INEXACT
) {
200 info
.si_code
= TARGET_FPE_FLTRES
;
202 queue_signal(env
, info
.si_signo
, QEMU_SI_FAULT
, &info
);
204 /* The code below was inspired by the MIPS Linux kernel trap
205 * handling code in arch/mips/kernel/traps.c.
209 abi_ulong trap_instr
;
212 if (env
->hflags
& MIPS_HFLAG_M16
) {
213 if (env
->insn_flags
& ASE_MICROMIPS
) {
215 ret
= get_user_u16(trap_instr
, env
->active_tc
.PC
);
220 if ((trap_instr
>> 10) == 0x11) {
221 /* 16-bit instruction */
222 code
= trap_instr
& 0xf;
224 /* 32-bit instruction */
227 ret
= get_user_u16(instr_lo
,
228 env
->active_tc
.PC
+ 2);
232 trap_instr
= (trap_instr
<< 16) | instr_lo
;
233 code
= ((trap_instr
>> 6) & ((1 << 20) - 1));
234 /* Unfortunately, microMIPS also suffers from
235 the old assembler bug... */
236 if (code
>= (1 << 10)) {
242 ret
= get_user_u16(trap_instr
, env
->active_tc
.PC
);
246 code
= (trap_instr
>> 6) & 0x3f;
249 ret
= get_user_u32(trap_instr
, env
->active_tc
.PC
);
254 /* As described in the original Linux kernel code, the
255 * below checks on 'code' are to work around an old
258 code
= ((trap_instr
>> 6) & ((1 << 20) - 1));
259 if (code
>= (1 << 10)) {
264 if (do_break(env
, &info
, code
) != 0) {
271 abi_ulong trap_instr
;
272 unsigned int code
= 0;
274 if (env
->hflags
& MIPS_HFLAG_M16
) {
278 ret
= get_user_u16(instr
[0], env
->active_tc
.PC
) ||
279 get_user_u16(instr
[1], env
->active_tc
.PC
+ 2);
281 trap_instr
= (instr
[0] << 16) | instr
[1];
283 ret
= get_user_u32(trap_instr
, env
->active_tc
.PC
);
290 /* The immediate versions don't provide a code. */
291 if (!(trap_instr
& 0xFC000000)) {
292 if (env
->hflags
& MIPS_HFLAG_M16
) {
294 code
= ((trap_instr
>> 12) & ((1 << 4) - 1));
296 code
= ((trap_instr
>> 6) & ((1 << 10) - 1));
300 if (do_break(env
, &info
, code
) != 0) {
306 cpu_exec_step_atomic(cs
);
310 EXCP_DUMP(env
, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr
);
313 process_pending_signals(env
);
317 void target_cpu_copy_regs(CPUArchState
*env
, struct target_pt_regs
*regs
)
319 CPUState
*cpu
= env_cpu(env
);
320 TaskState
*ts
= cpu
->opaque
;
321 struct image_info
*info
= ts
->info
;
332 static const struct mode_req fpu_reqs
[] = {
333 [MIPS_ABI_FP_ANY
] = { true, true, true, true, true },
334 [MIPS_ABI_FP_DOUBLE
] = { false, false, false, true, true },
335 [MIPS_ABI_FP_SINGLE
] = { true, false, false, false, false },
336 [MIPS_ABI_FP_SOFT
] = { false, true, false, false, false },
337 [MIPS_ABI_FP_OLD_64
] = { false, false, false, false, false },
338 [MIPS_ABI_FP_XX
] = { false, false, true, true, true },
339 [MIPS_ABI_FP_64
] = { false, false, true, false, false },
340 [MIPS_ABI_FP_64A
] = { false, false, true, false, true }
344 * Mode requirements when .MIPS.abiflags is not present in the ELF.
345 * Not present means that everything is acceptable except FR1.
347 static struct mode_req none_req
= { true, true, false, true, true };
349 struct mode_req prog_req
;
350 struct mode_req interp_req
;
352 for(i
= 0; i
< 32; i
++) {
353 env
->active_tc
.gpr
[i
] = regs
->regs
[i
];
355 env
->active_tc
.PC
= regs
->cp0_epc
& ~(target_ulong
)1;
356 if (regs
->cp0_epc
& 1) {
357 env
->hflags
|= MIPS_HFLAG_M16
;
360 #ifdef TARGET_ABI_MIPSO32
361 # define MAX_FP_ABI MIPS_ABI_FP_64A
363 # define MAX_FP_ABI MIPS_ABI_FP_SOFT
365 if ((info
->fp_abi
> MAX_FP_ABI
&& info
->fp_abi
!= MIPS_ABI_FP_UNKNOWN
)
366 || (info
->interp_fp_abi
> MAX_FP_ABI
&&
367 info
->interp_fp_abi
!= MIPS_ABI_FP_UNKNOWN
)) {
368 fprintf(stderr
, "qemu: Unexpected FPU mode\n");
372 prog_req
= (info
->fp_abi
== MIPS_ABI_FP_UNKNOWN
) ? none_req
373 : fpu_reqs
[info
->fp_abi
];
374 interp_req
= (info
->interp_fp_abi
== MIPS_ABI_FP_UNKNOWN
) ? none_req
375 : fpu_reqs
[info
->interp_fp_abi
];
377 prog_req
.single
&= interp_req
.single
;
378 prog_req
.soft
&= interp_req
.soft
;
379 prog_req
.fr1
&= interp_req
.fr1
;
380 prog_req
.frdefault
&= interp_req
.frdefault
;
381 prog_req
.fre
&= interp_req
.fre
;
383 bool cpu_has_mips_r2_r6
= env
->insn_flags
& ISA_MIPS32R2
||
384 env
->insn_flags
& ISA_MIPS64R2
||
385 env
->insn_flags
& ISA_MIPS32R6
||
386 env
->insn_flags
& ISA_MIPS64R6
;
388 if (prog_req
.fre
&& !prog_req
.frdefault
&& !prog_req
.fr1
) {
389 env
->CP0_Config5
|= (1 << CP0C5_FRE
);
390 if (env
->active_fpu
.fcr0
& (1 << FCR0_FREP
)) {
391 env
->hflags
|= MIPS_HFLAG_FRE
;
393 } else if ((prog_req
.fr1
&& prog_req
.frdefault
) ||
394 (prog_req
.single
&& !prog_req
.frdefault
)) {
395 if ((env
->active_fpu
.fcr0
& (1 << FCR0_F64
)
396 && cpu_has_mips_r2_r6
) || prog_req
.fr1
) {
397 env
->CP0_Status
|= (1 << CP0St_FR
);
398 env
->hflags
|= MIPS_HFLAG_F64
;
400 } else if (!prog_req
.fre
&& !prog_req
.frdefault
&&
401 !prog_req
.fr1
&& !prog_req
.single
&& !prog_req
.soft
) {
402 fprintf(stderr
, "qemu: Can't find a matching FPU mode\n");
406 if (env
->insn_flags
& ISA_NANOMIPS32
) {
409 if (((info
->elf_flags
& EF_MIPS_NAN2008
) != 0) !=
410 ((env
->active_fpu
.fcr31
& (1 << FCR31_NAN2008
)) != 0)) {
411 if ((env
->active_fpu
.fcr31_rw_bitmask
&
412 (1 << FCR31_NAN2008
)) == 0) {
413 fprintf(stderr
, "ELF binary's NaN mode not supported by CPU\n");
416 if ((info
->elf_flags
& EF_MIPS_NAN2008
) != 0) {
417 env
->active_fpu
.fcr31
|= (1 << FCR31_NAN2008
);
419 env
->active_fpu
.fcr31
&= ~(1 << FCR31_NAN2008
);
421 restore_snan_bit_mode(env
);