]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libc/sparc64/sys/__sparc_utrap_align.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libc / sparc64 / sys / __sparc_utrap_align.c
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
37 static 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
49 static 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
58 int
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 }