1/*- 2 * Copyright (c) 2002 Jake Burkholder. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 23 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD$"); 28 29#include <sys/types.h> 30#include <machine/cpufunc.h> 31#include <machine/instr.h> 32 33#include <signal.h> 34 35#include "__sparc_utrap_private.h" 36 37static u_long 38__unaligned_load(u_char *p, int size) 39{ 40 u_long val; 41 int i; 42 43 val = 0; 44 for (i = 0; i < size; i++) 45 val = (val << 8) | p[i]; 46 return (val); 47} 48 49static void 50__unaligned_store(u_char *p, u_long val, int size) 51{ 52 int i; 53 54 for (i = 0; i < size; i++) 55 p[i] = val >> ((size - i - 1) * 8); 56} 57 58int 59__unaligned_fixup(struct utrapframe *uf) 60{ 61 u_char *addr; 62 u_long val; 63 u_int insn; 64 int sig; 65 66 sig = 0; 67 addr = (u_char *)uf->uf_sfar; 68 insn = *(u_int *)uf->uf_pc; 69 flushw(); 70 switch (IF_OP(insn)) { 71 case IOP_LDST: 72 switch (IF_F3_OP3(insn)) { 73 case INS3_LDUH: 74 val = __unaligned_load(addr, 2); 75 __emul_store_reg(uf, IF_F3_RD(insn), val); 76 break; 77 case INS3_LDUW: 78 val = __unaligned_load(addr, 4); 79 __emul_store_reg(uf, IF_F3_RD(insn), val); 80 break; 81 case INS3_LDX: 82 val = __unaligned_load(addr, 8); 83 __emul_store_reg(uf, IF_F3_RD(insn), val); 84 break; 85 case INS3_LDSH: 86 val = __unaligned_load(addr, 2); 87 __emul_store_reg(uf, IF_F3_RD(insn), 88 IF_SEXT(val, 16)); 89 break; 90 case INS3_LDSW: 91 val = __unaligned_load(addr, 4); 92 __emul_store_reg(uf, IF_F3_RD(insn), 93 IF_SEXT(val, 32)); 94 break; 95 case INS3_STH: 96 val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 97 __unaligned_store(addr, val, 2); 98 break; 99 case INS3_STW: 100 val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 101 __unaligned_store(addr, val, 4); 102 break; 103 case INS3_STX: 104 val = __emul_fetch_reg(uf, IF_F3_RD(insn)); 105 __unaligned_store(addr, val, 8); 106 break; 107 default: 108 sig = SIGILL; 109 break; 110 } 111 break; 112 default: 113 sig = SIGILL; 114 break; 115 } 116 return (sig); 117} 118