case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
pc = env->segs[R_CS].base + env->eip;
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
case EXCP_SWI:
{
/* system call */
- insn = ldl((void *)(env->regs[15] - 4));
- n = insn & 0xffffff;
+ if (env->thumb) {
+ insn = lduw((void *)(env->regs[15] - 2));
+ n = insn & 0xff;
+ } else {
+ insn = ldl((void *)(env->regs[15] - 4));
+ n = insn & 0xffffff;
+ }
+
if (n == ARM_NR_cacheflush) {
arm_cache_flush(env->regs[0], env->regs[1]);
- } else if (n >= ARM_SYSCALL_BASE) {
+ } else if (n == ARM_NR_semihosting
+ || n == ARM_NR_thumb_semihosting) {
+ env->regs[0] = do_arm_semihosting (env);
+ } else if (n >= ARM_SYSCALL_BASE
+ || (env->thumb && n == ARM_THUMB_SYSCALL)) {
/* linux syscall */
- n -= ARM_SYSCALL_BASE;
+ if (env->thumb) {
+ n = env->regs[7];
+ } else {
+ n -= ARM_SYSCALL_BASE;
+ }
env->regs[0] = do_syscall(env,
n,
env->regs[0],
env->regs[2],
env->regs[3],
env->regs[4],
- 0);
+ env->regs[5]);
} else {
goto error;
}
queue_signal(info.si_signo, &info);
}
break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
env->pc = env->npc;
env->npc = env->npc + 4;
break;
+#ifndef TARGET_SPARC64
case TT_WIN_OVF: /* window overflow */
save_window(env);
break;
queue_signal(info.si_signo, &info);
}
break;
+#else
+ // XXX
+#endif
case 0x100: // XXX, why do we get these?
break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */
break;
- case EXCP_DEBUG:
- break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
void usage(void)
{
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
+ "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] program [arguments...]\n"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
"-h print this help\n"
+ "-g wait gdb connection to port %d\n"
"-L path set the elf interpreter prefix (default=%s)\n"
"-s size set the stack size in bytes (default=%ld)\n"
"\n"
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
+ DEFAULT_GDBSTUB_PORT,
interp_prefix,
x86_stack_size,
DEBUG_LOGFILE);
CPUState *env;
int optind;
const char *r;
+ int use_gdbstub = 0;
if (argc <= 1)
usage();
fprintf(stderr, "page size must be a power of two\n");
exit(1);
}
+ } else if (!strcmp(r, "g")) {
+ use_gdbstub = 1;
} else
#ifdef USE_CODE_COPY
if (!strcmp(r, "no-code-copy")) {
env->regs[i] = regs->uregs[i];
}
env->cpsr = regs->uregs[16];
+ ts->stack_base = info->start_stack;
+ ts->heap_base = info->brk;
+ /* This will be filled in on the first SYS_HEAPINFO call. */
+ ts->heap_limit = 0;
}
#elif defined(TARGET_SPARC)
{
#error unsupported target CPU
#endif
+ if (use_gdbstub) {
+ gdbserver_start (DEFAULT_GDBSTUB_PORT);
+ gdb_handlesig(env, 0);
+ }
cpu_loop(env);
/* never exits */
return 0;