diff options
-rw-r--r-- | lib/libc/sparc64/sys/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libc/sparc64/sys/__sparc_utrap.c | 1 | ||||
-rw-r--r-- | lib/libc/sparc64/sys/__sparc_utrap_align.c | 117 | ||||
-rw-r--r-- | lib/libc/sparc64/sys/__sparc_utrap_private.h | 1 | ||||
-rw-r--r-- | lib/libc/sparc64/sys/__sparc_utrap_setup.c | 2 |
5 files changed, 120 insertions, 2 deletions
diff --git a/lib/libc/sparc64/sys/Makefile.inc b/lib/libc/sparc64/sys/Makefile.inc index be99221..feb9cb6 100644 --- a/lib/libc/sparc64/sys/Makefile.inc +++ b/lib/libc/sparc64/sys/Makefile.inc @@ -2,6 +2,7 @@ SRCS+= __sparc_sigtramp_setup.c \ __sparc_utrap.c \ + __sparc_utrap_align.c \ __sparc_utrap_emul.c \ __sparc_utrap_fp_disabled.S \ __sparc_utrap_gen.S \ diff --git a/lib/libc/sparc64/sys/__sparc_utrap.c b/lib/libc/sparc64/sys/__sparc_utrap.c index d51d89a..e7c503f 100644 --- a/lib/libc/sparc64/sys/__sparc_utrap.c +++ b/lib/libc/sparc64/sys/__sparc_utrap.c @@ -91,6 +91,7 @@ __sparc_utrap(struct utrapframe *uf) sig = __emul_insn(uf); break; case UT_MEM_ADDRESS_NOT_ALIGNED: + sig = __unaligned_fixup(uf); break; default: break; diff --git a/lib/libc/sparc64/sys/__sparc_utrap_align.c b/lib/libc/sparc64/sys/__sparc_utrap_align.c new file mode 100644 index 0000000..a66266e --- /dev/null +++ b/lib/libc/sparc64/sys/__sparc_utrap_align.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2002 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <machine/cpufunc.h> +#include <machine/instr.h> + +#include <signal.h> + +#include "__sparc_utrap_private.h" + +static u_long +__unaligned_load(u_char *p, int size) +{ + u_long val; + int i; + + val = 0; + for (i = 0; i < size; i++) + val = (val << 8) | p[i]; + return (val); +} + +static void +__unaligned_store(u_char *p, u_long val, int size) +{ + int i; + + for (i = 0; i < size; i++) + p[i] = val >> (i * 8); +} + +int +__unaligned_fixup(struct utrapframe *uf) +{ + u_char *addr; + u_long val; + u_int insn; + int sig; + + sig = 0; + addr = (u_char *)uf->uf_sfar; + insn = *(u_int *)uf->uf_pc; + flushw(); + switch (IF_OP(insn)) { + case IOP_LDST: + switch (IF_F3_OP3(insn)) { + case INS3_LDUH: + val = __unaligned_load(addr, 2); + __emul_store_reg(uf, IF_F3_RD(insn), val); + break; + case INS3_LDUW: + val = __unaligned_load(addr, 4); + __emul_store_reg(uf, IF_F3_RD(insn), val); + break; + case INS3_LDX: + val = __unaligned_load(addr, 8); + __emul_store_reg(uf, IF_F3_RD(insn), val); + break; + case INS3_LDSH: + val = __unaligned_load(addr, 2); + __emul_store_reg(uf, IF_F3_RD(insn), + IF_SEXT(val, 16)); + break; + case INS3_LDSW: + val = __unaligned_load(addr, 4); + __emul_store_reg(uf, IF_F3_RD(insn), + IF_SEXT(val, 32)); + break; + case INS3_STH: + val = __emul_fetch_reg(uf, IF_F3_RD(insn)); + __unaligned_store(addr, val, 2); + break; + case INS3_STW: + val = __emul_fetch_reg(uf, IF_F3_RD(insn)); + __unaligned_store(addr, val, 4); + break; + case INS3_STX: + val = __emul_fetch_reg(uf, IF_F3_RD(insn)); + __unaligned_store(addr, val, 8); + break; + default: + sig = SIGILL; + break; + } + break; + default: + sig = SIGILL; + break; + } + return (sig); +} diff --git a/lib/libc/sparc64/sys/__sparc_utrap_private.h b/lib/libc/sparc64/sys/__sparc_utrap_private.h index 798ed70..8b9ae9e 100644 --- a/lib/libc/sparc64/sys/__sparc_utrap_private.h +++ b/lib/libc/sparc64/sys/__sparc_utrap_private.h @@ -55,6 +55,7 @@ u_long __emul_fetch_reg(struct utrapframe *uf, int reg); void __emul_store_reg(struct utrapframe *uf, int reg, u_long val); u_long __emul_f3_op2(struct utrapframe *uf, u_int insn); u_long __emul_f3_memop_addr(struct utrapframe *uf, u_int insn); +int __unaligned_fixup(struct utrapframe *uf); void __sparc_utrap(struct utrapframe *); diff --git a/lib/libc/sparc64/sys/__sparc_utrap_setup.c b/lib/libc/sparc64/sys/__sparc_utrap_setup.c index e39de99..1c8ce30 100644 --- a/lib/libc/sparc64/sys/__sparc_utrap_setup.c +++ b/lib/libc/sparc64/sys/__sparc_utrap_setup.c @@ -41,9 +41,7 @@ static const struct sparc_utrap_args ua[] = { { UT_FP_EXCEPTION_IEEE_754, __sparc_utrap_gen, NULL, NULL, NULL }, { UT_FP_EXCEPTION_OTHER, __sparc_utrap_gen, NULL, NULL, NULL }, { UT_ILLEGAL_INSTRUCTION, __sparc_utrap_gen, NULL, NULL, NULL }, -#if 0 { UT_MEM_ADDRESS_NOT_ALIGNED, __sparc_utrap_gen, NULL, NULL, NULL }, -#endif }; static const struct sparc_utrap_install_args uia[] = { |