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