__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