Handle SWI's from Thumb code.

Note: this may need further work.  For the momement we unconditionally
convert a Thumb SWI insn into an ARM SWI with the operation code
zero-extended to 24 bits.  However, this should really be a property
of the emulation (how do we know that all emulated systems would want
to work this way?), but that would mean pushing all the handling down
into each of the emulators.
This commit is contained in:
rearnsha 2004-08-21 11:57:36 +00:00
parent 4cdf758fde
commit 6c37261ede
1 changed files with 58 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: syscall.c,v 1.24 2003/11/14 19:03:17 scw Exp $ */
/* $NetBSD: syscall.c,v 1.25 2004/08/21 11:57:36 rearnsha Exp $ */
/*-
* Copyright (c) 2000, 2003 The NetBSD Foundation, Inc.
@ -82,7 +82,7 @@
#include <sys/param.h>
__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.24 2003/11/14 19:03:17 scw Exp $");
__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.25 2004/08/21 11:57:36 rearnsha Exp $");
#include <sys/device.h>
#include <sys/errno.h>
@ -134,6 +134,7 @@ swi_handler(trapframe_t *frame)
frame->tf_pc += INSN_SIZE;
#endif
#ifndef THUMB_CODE
/*
* Make sure the program counter is correctly aligned so we
* don't take an alignment fault trying to read the opcode.
@ -156,13 +157,24 @@ swi_handler(trapframe_t *frame)
userret(l);
return;
}
#endif
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit) {
/* Map a Thumb SWI onto the bottom 256 ARM SWIs. */
insn = fusword((void *)(frame->tf_pc - THUMB_INSN_SIZE));
insn = (insn & 0x00ff) | 0xef000000;
}
else
#endif
{
/* XXX fuword? */
#ifdef __PROG32
insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE);
#else
insn = *(u_int32_t *)((frame->tf_r15 & R15_PC) - INSN_SIZE);
#endif
}
l->l_addr->u_pcb.pcb_tf = frame;
@ -250,7 +262,14 @@ syscall_plain(struct trapframe *frame, struct lwp *l, u_int32_t insn)
ksi.ksi_signo = SIGILL;
/* XXX get an ILL_ILLSYSCALL assigned */
ksi.ksi_code = 0;
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc - INSN_SIZE);
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
THUMB_INSN_SIZE);
else
#endif
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
INSN_SIZE);
ksi.ksi_trap = insn;
trapsignal(l, &ksi);
break;
@ -268,6 +287,12 @@ syscall_plain(struct trapframe *frame, struct lwp *l, u_int32_t insn)
ksi.ksi_signo = SIGILL;
/* XXX get an ILL_ILLSYSCALL assigned */
ksi.ksi_code = 0;
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
THUMB_INSN_SIZE);
else
#endif
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc - INSN_SIZE);
ksi.ksi_trap = insn;
trapsignal(l, &ksi);
@ -327,6 +352,11 @@ syscall_plain(struct trapframe *frame, struct lwp *l, u_int32_t insn)
/*
* Reconstruct the pc to point at the swi.
*/
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
frame->tf_pc -= THUMB_INSN_SIZE;
else
#endif
frame->tf_pc -= INSN_SIZE;
break;
@ -378,7 +408,14 @@ syscall_fancy(struct trapframe *frame, struct lwp *l, u_int32_t insn)
ksi.ksi_signo = SIGILL;
/* XXX get an ILL_ILLSYSCALL assigned */
ksi.ksi_code = 0;
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc - INSN_SIZE);
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
THUMB_INSN_SIZE);
else
#endif
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
INSN_SIZE);
ksi.ksi_trap = insn;
trapsignal(l, &ksi);
break;
@ -396,6 +433,12 @@ syscall_fancy(struct trapframe *frame, struct lwp *l, u_int32_t insn)
ksi.ksi_signo = SIGILL;
/* XXX get an ILL_ILLSYSCALL assigned */
ksi.ksi_code = 0;
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc -
THUMB_INSN_SIZE);
else
#endif
ksi.ksi_addr = (u_int32_t *)(frame->tf_pc - INSN_SIZE);
ksi.ksi_trap = insn;
trapsignal(l, &ksi);
@ -458,6 +501,11 @@ syscall_fancy(struct trapframe *frame, struct lwp *l, u_int32_t insn)
/*
* Reconstruct the pc to point at the swi.
*/
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit)
frame->tf_pc -= THUMB_INSN_SIZE;
else
#endif
frame->tf_pc -= INSN_SIZE;
break;