196492Sjake/*- 296492Sjake * Copyright (c) 2002 Jake Burkholder. 396492Sjake * All rights reserved. 496492Sjake * 596492Sjake * Redistribution and use in source and binary forms, with or without 696492Sjake * modification, are permitted provided that the following conditions 796492Sjake * are met: 896492Sjake * 1. Redistributions of source code must retain the above copyright 996492Sjake * notice, this list of conditions and the following disclaimer. 1096492Sjake * 2. Redistributions in binary form must reproduce the above copyright 1196492Sjake * notice, this list of conditions and the following disclaimer in the 1296492Sjake * documentation and/or other materials provided with the distribution. 1396492Sjake * 1496492Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1596492Sjake * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1696492Sjake * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1796492Sjake * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 1896492Sjake * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1996492Sjake * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2096492Sjake * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 2196492Sjake * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2296492Sjake * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2396492Sjake * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2496492Sjake */ 2596492Sjake 2696492Sjake#include <sys/cdefs.h> 2796492Sjake__FBSDID("$FreeBSD$"); 2896492Sjake 2996492Sjake#include <sys/types.h> 3096492Sjake#include <machine/cpufunc.h> 3196492Sjake#include <machine/instr.h> 3296492Sjake 3396492Sjake#include <signal.h> 3496492Sjake 3596492Sjake#include "__sparc_utrap_private.h" 3696492Sjake 3796492Sjakestatic u_long 3896492Sjake__unaligned_load(u_char *p, int size) 3996492Sjake{ 4096492Sjake u_long val; 4196492Sjake int i; 4296492Sjake 4396492Sjake val = 0; 4496492Sjake for (i = 0; i < size; i++) 4596492Sjake val = (val << 8) | p[i]; 4696492Sjake return (val); 4796492Sjake} 4896492Sjake 4996492Sjakestatic void 5096492Sjake__unaligned_store(u_char *p, u_long val, int size) 5196492Sjake{ 5296492Sjake int i; 5396492Sjake 5496492Sjake for (i = 0; i < size; i++) 5596548Sjake p[i] = val >> ((size - i - 1) * 8); 5696492Sjake} 5796492Sjake 5896492Sjakeint 5996492Sjake__unaligned_fixup(struct utrapframe *uf) 6096492Sjake{ 6196492Sjake u_char *addr; 6296492Sjake u_long val; 6396492Sjake u_int insn; 6496492Sjake int sig; 6596492Sjake 6696492Sjake sig = 0; 6796492Sjake addr = (u_char *)uf->uf_sfar; 6896492Sjake insn = *(u_int *)uf->uf_pc; 6996492Sjake flushw(); 7096492Sjake switch (IF_OP(insn)) { 7196492Sjake case IOP_LDST: 7296492Sjake switch (IF_F3_OP3(insn)) { 7396492Sjake case INS3_LDUH: 7496492Sjake val = __unaligned_load(addr, 2); 7596492Sjake __emul_store_reg(uf, IF_F3_RD(insn), val); 7696492Sjake break; 7796492Sjake case INS3_LDUW: 7896492Sjake val = __unaligned_load(addr, 4); 7996492Sjake __emul_store_reg(uf, IF_F3_RD(insn), val); 8096492Sjake break; 8196492Sjake case INS3_LDX: 8296492Sjake val = __unaligned_load(addr, 8); 8396492Sjake __emul_store_reg(uf, IF_F3_RD(insn), val); 8496492Sjake break; 8596492Sjake case INS3_LDSH: 8696492Sjake val = __unaligned_load(addr, 2); 8796492Sjake __emul_store_reg(uf, IF_F3_RD(insn), 8896492Sjake IF_SEXT(val, 16)); 8996492Sjake break; 9096492Sjake case INS3_LDSW: 9196492Sjake val = __unaligned_load(addr, 4); 9296492Sjake __emul_store_reg(uf, IF_F3_RD(insn), 9396492Sjake IF_SEXT(val, 32)); 9496492Sjake break; 9596492Sjake case INS3_STH: 9696492Sjake val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 9796492Sjake __unaligned_store(addr, val, 2); 9896492Sjake break; 9996492Sjake case INS3_STW: 10096492Sjake val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 10196492Sjake __unaligned_store(addr, val, 4); 10296492Sjake break; 10396492Sjake case INS3_STX: 10496492Sjake val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 10596492Sjake __unaligned_store(addr, val, 8); 10696492Sjake break; 10796492Sjake default: 10896492Sjake sig = SIGILL; 10996492Sjake break; 11096492Sjake } 11196492Sjake break; 11296492Sjake default: 11396492Sjake sig = SIGILL; 11496492Sjake break; 11596492Sjake } 11696492Sjake return (sig); 11796492Sjake} 118