Rename the unhelpfully named mips_emul_lwc0() and mips_emul_swc0() to mips_emul_ll() and mips_emul_sc(); make these static to mips_emul.c.diff -r1.118 -r1.119 src/sys/arch/mips/include/locore.h
(simonb)
--- src/sys/arch/mips/include/locore.h 2021/05/12 03:53:37 1.118
+++ src/sys/arch/mips/include/locore.h 2021/05/27 15:00:02 1.119
@@ -1,923 +1,921 @@ | @@ -1,923 +1,921 @@ | |||
1 | /* $NetBSD: locore.h,v 1.118 2021/05/12 03:53:37 simonb Exp $ */ | 1 | /* $NetBSD: locore.h,v 1.119 2021/05/27 15:00:02 simonb Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * This file should not be included by MI code!!! | 4 | * This file should not be included by MI code!!! | |
5 | */ | 5 | */ | |
6 | 6 | |||
7 | /* | 7 | /* | |
8 | * Copyright 1996 The Board of Trustees of The Leland Stanford | 8 | * Copyright 1996 The Board of Trustees of The Leland Stanford | |
9 | * Junior University. All Rights Reserved. | 9 | * Junior University. All Rights Reserved. | |
10 | * | 10 | * | |
11 | * Permission to use, copy, modify, and distribute this | 11 | * Permission to use, copy, modify, and distribute this | |
12 | * software and its documentation for any purpose and without | 12 | * software and its documentation for any purpose and without | |
13 | * fee is hereby granted, provided that the above copyright | 13 | * fee is hereby granted, provided that the above copyright | |
14 | * notice appear in all copies. Stanford University | 14 | * notice appear in all copies. Stanford University | |
15 | * makes no representations about the suitability of this | 15 | * makes no representations about the suitability of this | |
16 | * software for any purpose. It is provided "as is" without | 16 | * software for any purpose. It is provided "as is" without | |
17 | * express or implied warranty. | 17 | * express or implied warranty. | |
18 | */ | 18 | */ | |
19 | 19 | |||
20 | /* | 20 | /* | |
21 | * Jump table for MIPS CPU locore functions that are implemented | 21 | * Jump table for MIPS CPU locore functions that are implemented | |
22 | * differently on different generations, or instruction-level | 22 | * differently on different generations, or instruction-level | |
23 | * architecture (ISA) level, the Mips family. | 23 | * architecture (ISA) level, the Mips family. | |
24 | * | 24 | * | |
25 | * We currently provide support for MIPS I and MIPS III. | 25 | * We currently provide support for MIPS I and MIPS III. | |
26 | */ | 26 | */ | |
27 | 27 | |||
28 | #ifndef _MIPS_LOCORE_H | 28 | #ifndef _MIPS_LOCORE_H | |
29 | #define _MIPS_LOCORE_H | 29 | #define _MIPS_LOCORE_H | |
30 | 30 | |||
31 | #if !defined(_MODULE) && defined(_KERNEL_OPT) | 31 | #if !defined(_MODULE) && defined(_KERNEL_OPT) | |
32 | #include "opt_cputype.h" | 32 | #include "opt_cputype.h" | |
33 | #endif | 33 | #endif | |
34 | 34 | |||
35 | #ifndef __ASSEMBLER__ | 35 | #ifndef __ASSEMBLER__ | |
36 | 36 | |||
37 | #include <sys/cpu.h> | 37 | #include <sys/cpu.h> | |
38 | 38 | |||
39 | #include <mips/mutex.h> | 39 | #include <mips/mutex.h> | |
40 | #include <mips/cpuregs.h> | 40 | #include <mips/cpuregs.h> | |
41 | #include <mips/reg.h> | 41 | #include <mips/reg.h> | |
42 | 42 | |||
43 | #ifndef __BSD_PTENTRY_T__ | 43 | #ifndef __BSD_PTENTRY_T__ | |
44 | #define __BSD_PTENTRY_T__ | 44 | #define __BSD_PTENTRY_T__ | |
45 | typedef uint32_t pt_entry_t; | 45 | typedef uint32_t pt_entry_t; | |
46 | #define PRIxPTE PRIx32 | 46 | #define PRIxPTE PRIx32 | |
47 | #endif | 47 | #endif | |
48 | 48 | |||
49 | #include <uvm/pmap/tlb.h> | 49 | #include <uvm/pmap/tlb.h> | |
50 | #endif /* !__ASSEMBLER__ */ | 50 | #endif /* !__ASSEMBLER__ */ | |
51 | 51 | |||
52 | #ifdef _KERNEL | 52 | #ifdef _KERNEL | |
53 | 53 | |||
54 | #if defined(_MODULE) || defined(_STANDALONE) | 54 | #if defined(_MODULE) || defined(_STANDALONE) | |
55 | /* Assume all CPU architectures are valid for modules and standlone progs */ | 55 | /* Assume all CPU architectures are valid for modules and standlone progs */ | |
56 | #if !defined(__mips_n32) && !defined(__mips_n64) | 56 | #if !defined(__mips_n32) && !defined(__mips_n64) | |
57 | #define MIPS1 1 | 57 | #define MIPS1 1 | |
58 | #endif | 58 | #endif | |
59 | #define MIPS3 1 | 59 | #define MIPS3 1 | |
60 | #define MIPS4 1 | 60 | #define MIPS4 1 | |
61 | #if !defined(__mips_n32) && !defined(__mips_n64) | 61 | #if !defined(__mips_n32) && !defined(__mips_n64) | |
62 | #define MIPS32 1 | 62 | #define MIPS32 1 | |
63 | #define MIPS32R2 1 | 63 | #define MIPS32R2 1 | |
64 | #endif | 64 | #endif | |
65 | #define MIPS64 1 | 65 | #define MIPS64 1 | |
66 | #define MIPS64R2 1 | 66 | #define MIPS64R2 1 | |
67 | #endif /* _MODULE || _STANDALONE */ | 67 | #endif /* _MODULE || _STANDALONE */ | |
68 | 68 | |||
69 | #if (MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) == 0 | 69 | #if (MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) == 0 | |
70 | #error at least one of MIPS1, MIPS3, MIPS4, MIPS32, MIPS32R2, MIPS64, or MIPS64R2 must be specified | 70 | #error at least one of MIPS1, MIPS3, MIPS4, MIPS32, MIPS32R2, MIPS64, or MIPS64R2 must be specified | |
71 | #endif | 71 | #endif | |
72 | 72 | |||
73 | /* Shortcut for MIPS3 or above defined */ | 73 | /* Shortcut for MIPS3 or above defined */ | |
74 | #if defined(MIPS3) || defined(MIPS4) \ | 74 | #if defined(MIPS3) || defined(MIPS4) \ | |
75 | || defined(MIPS32) || defined(MIPS32R2) \ | 75 | || defined(MIPS32) || defined(MIPS32R2) \ | |
76 | || defined(MIPS64) || defined(MIPS64R2) | 76 | || defined(MIPS64) || defined(MIPS64R2) | |
77 | 77 | |||
78 | #define MIPS3_PLUS 1 | 78 | #define MIPS3_PLUS 1 | |
79 | #if !defined(MIPS32) && !defined(MIPS32R2) | 79 | #if !defined(MIPS32) && !defined(MIPS32R2) | |
80 | #define MIPS3_64BIT 1 | 80 | #define MIPS3_64BIT 1 | |
81 | #endif | 81 | #endif | |
82 | #if !defined(MIPS3) && !defined(MIPS4) | 82 | #if !defined(MIPS3) && !defined(MIPS4) | |
83 | #define MIPSNN 1 | 83 | #define MIPSNN 1 | |
84 | #endif | 84 | #endif | |
85 | #if defined(MIPS32R2) || defined(MIPS64R2) | 85 | #if defined(MIPS32R2) || defined(MIPS64R2) | |
86 | #define MIPSNNR2 1 | 86 | #define MIPSNNR2 1 | |
87 | #endif | 87 | #endif | |
88 | #else | 88 | #else | |
89 | #undef MIPS3_PLUS | 89 | #undef MIPS3_PLUS | |
90 | #endif | 90 | #endif | |
91 | 91 | |||
92 | #if defined(MIPS1) && (ENABLE_MIPS_8KB_PAGE + ENABLE_MIPS_16KB_PAGE) > 0 | 92 | #if defined(MIPS1) && (ENABLE_MIPS_8KB_PAGE + ENABLE_MIPS_16KB_PAGE) > 0 | |
93 | #error MIPS1 only supports a 4kB page size. | 93 | #error MIPS1 only supports a 4kB page size. | |
94 | #endif | 94 | #endif | |
95 | 95 | |||
96 | /* XXX some .S files look for MIPS3_PLUS */ | 96 | /* XXX some .S files look for MIPS3_PLUS */ | |
97 | #ifndef __ASSEMBLER__ | 97 | #ifndef __ASSEMBLER__ | |
98 | #ifdef _KERNEL | 98 | #ifdef _KERNEL | |
99 | 99 | |||
100 | /* XXX simonb | 100 | /* XXX simonb | |
101 | * Should the following be in a cpu_info type structure? | 101 | * Should the following be in a cpu_info type structure? | |
102 | * And how many of these are per-cpu vs. per-system? (Ie, | 102 | * And how many of these are per-cpu vs. per-system? (Ie, | |
103 | * we can assume that all cpus have the same mmu-type, but | 103 | * we can assume that all cpus have the same mmu-type, but | |
104 | * maybe not that all cpus run at the same clock speed. | 104 | * maybe not that all cpus run at the same clock speed. | |
105 | * Some SGI's apparently support R12k and R14k in the same | 105 | * Some SGI's apparently support R12k and R14k in the same | |
106 | * box.) | 106 | * box.) | |
107 | */ | 107 | */ | |
108 | struct mips_options { | 108 | struct mips_options { | |
109 | const struct pridtab *mips_cpu; | 109 | const struct pridtab *mips_cpu; | |
110 | 110 | |||
111 | u_int mips_cpu_arch; | 111 | u_int mips_cpu_arch; | |
112 | u_int mips_cpu_mhz; /* CPU speed in MHz, estimated by mc_cpuspeed(). */ | 112 | u_int mips_cpu_mhz; /* CPU speed in MHz, estimated by mc_cpuspeed(). */ | |
113 | u_int mips_cpu_flags; | 113 | u_int mips_cpu_flags; | |
114 | u_int mips_num_tlb_entries; | 114 | u_int mips_num_tlb_entries; | |
115 | mips_prid_t mips_cpu_id; | 115 | mips_prid_t mips_cpu_id; | |
116 | mips_prid_t mips_fpu_id; | 116 | mips_prid_t mips_fpu_id; | |
117 | bool mips_has_r4k_mmu; | 117 | bool mips_has_r4k_mmu; | |
118 | bool mips_has_llsc; | 118 | bool mips_has_llsc; | |
119 | u_int mips3_pg_shift; | 119 | u_int mips3_pg_shift; | |
120 | u_int mips3_pg_cached; | 120 | u_int mips3_pg_cached; | |
121 | u_int mips3_cca_devmem; | 121 | u_int mips3_cca_devmem; | |
122 | #ifdef MIPS3_PLUS | 122 | #ifdef MIPS3_PLUS | |
123 | #ifndef __mips_o32 | 123 | #ifndef __mips_o32 | |
124 | uint64_t mips3_xkphys_cached; | 124 | uint64_t mips3_xkphys_cached; | |
125 | #endif | 125 | #endif | |
126 | uint64_t mips3_tlb_vpn_mask; | 126 | uint64_t mips3_tlb_vpn_mask; | |
127 | uint64_t mips3_tlb_pfn_mask; | 127 | uint64_t mips3_tlb_pfn_mask; | |
128 | uint32_t mips3_tlb_pg_mask; | 128 | uint32_t mips3_tlb_pg_mask; | |
129 | #endif | 129 | #endif | |
130 | }; | 130 | }; | |
131 | 131 | |||
132 | #endif /* !__ASSEMBLER__ */ | 132 | #endif /* !__ASSEMBLER__ */ | |
133 | 133 | |||
134 | /* | 134 | /* | |
135 | * Macros to find the CPU architecture we're on at run-time, | 135 | * Macros to find the CPU architecture we're on at run-time, | |
136 | * or if possible, at compile-time. | 136 | * or if possible, at compile-time. | |
137 | */ | 137 | */ | |
138 | 138 | |||
139 | #define CPU_ARCH_MIPSx 0 /* XXX unknown */ | 139 | #define CPU_ARCH_MIPSx 0 /* XXX unknown */ | |
140 | #define CPU_ARCH_MIPS1 (1 << 0) | 140 | #define CPU_ARCH_MIPS1 (1 << 0) | |
141 | #define CPU_ARCH_MIPS2 (1 << 1) | 141 | #define CPU_ARCH_MIPS2 (1 << 1) | |
142 | #define CPU_ARCH_MIPS3 (1 << 2) | 142 | #define CPU_ARCH_MIPS3 (1 << 2) | |
143 | #define CPU_ARCH_MIPS4 (1 << 3) | 143 | #define CPU_ARCH_MIPS4 (1 << 3) | |
144 | #define CPU_ARCH_MIPS5 (1 << 4) | 144 | #define CPU_ARCH_MIPS5 (1 << 4) | |
145 | #define CPU_ARCH_MIPS32 (1 << 5) | 145 | #define CPU_ARCH_MIPS32 (1 << 5) | |
146 | #define CPU_ARCH_MIPS64 (1 << 6) | 146 | #define CPU_ARCH_MIPS64 (1 << 6) | |
147 | #define CPU_ARCH_MIPS32R2 (1 << 7) | 147 | #define CPU_ARCH_MIPS32R2 (1 << 7) | |
148 | #define CPU_ARCH_MIPS64R2 (1 << 8) | 148 | #define CPU_ARCH_MIPS64R2 (1 << 8) | |
149 | 149 | |||
150 | #define CPU_MIPS_R4K_MMU 0x00001 | 150 | #define CPU_MIPS_R4K_MMU 0x00001 | |
151 | #define CPU_MIPS_NO_LLSC 0x00002 | 151 | #define CPU_MIPS_NO_LLSC 0x00002 | |
152 | #define CPU_MIPS_CAUSE_IV 0x00004 | 152 | #define CPU_MIPS_CAUSE_IV 0x00004 | |
153 | #define CPU_MIPS_HAVE_SPECIAL_CCA 0x00008 /* Defaults to '3' if not set. */ | 153 | #define CPU_MIPS_HAVE_SPECIAL_CCA 0x00008 /* Defaults to '3' if not set. */ | |
154 | #define CPU_MIPS_CACHED_CCA_MASK 0x00070 | 154 | #define CPU_MIPS_CACHED_CCA_MASK 0x00070 | |
155 | #define CPU_MIPS_CACHED_CCA_SHIFT 4 | 155 | #define CPU_MIPS_CACHED_CCA_SHIFT 4 | |
156 | #define CPU_MIPS_DOUBLE_COUNT 0x00080 /* 1 cp0 count == 2 clock cycles */ | 156 | #define CPU_MIPS_DOUBLE_COUNT 0x00080 /* 1 cp0 count == 2 clock cycles */ | |
157 | #define CPU_MIPS_USE_WAIT 0x00100 /* Use "wait"-based cpu_idle() */ | 157 | #define CPU_MIPS_USE_WAIT 0x00100 /* Use "wait"-based cpu_idle() */ | |
158 | #define CPU_MIPS_NO_WAIT 0x00200 /* Inverse of previous, for mips32/64 */ | 158 | #define CPU_MIPS_NO_WAIT 0x00200 /* Inverse of previous, for mips32/64 */ | |
159 | #define CPU_MIPS_D_CACHE_COHERENT 0x00400 /* D-cache is fully coherent */ | 159 | #define CPU_MIPS_D_CACHE_COHERENT 0x00400 /* D-cache is fully coherent */ | |
160 | #define CPU_MIPS_I_D_CACHE_COHERENT 0x00800 /* I-cache funcs don't need to flush the D-cache */ | 160 | #define CPU_MIPS_I_D_CACHE_COHERENT 0x00800 /* I-cache funcs don't need to flush the D-cache */ | |
161 | #define CPU_MIPS_NO_LLADDR 0x01000 | 161 | #define CPU_MIPS_NO_LLADDR 0x01000 | |
162 | #define CPU_MIPS_HAVE_MxCR 0x02000 /* have mfcr, mtcr insns */ | 162 | #define CPU_MIPS_HAVE_MxCR 0x02000 /* have mfcr, mtcr insns */ | |
163 | #define CPU_MIPS_LOONGSON2 0x04000 | 163 | #define CPU_MIPS_LOONGSON2 0x04000 | |
164 | #define MIPS_NOT_SUPP 0x08000 | 164 | #define MIPS_NOT_SUPP 0x08000 | |
165 | #define CPU_MIPS_HAVE_DSP 0x10000 | 165 | #define CPU_MIPS_HAVE_DSP 0x10000 | |
166 | #define CPU_MIPS_HAVE_USERLOCAL 0x20000 | 166 | #define CPU_MIPS_HAVE_USERLOCAL 0x20000 | |
167 | 167 | |||
168 | #endif /* !_LOCORE */ | 168 | #endif /* !_LOCORE */ | |
169 | 169 | |||
170 | #if ((MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) == 1) || defined(_LOCORE) | 170 | #if ((MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) == 1) || defined(_LOCORE) | |
171 | 171 | |||
172 | #if defined(MIPS1) | 172 | #if defined(MIPS1) | |
173 | 173 | |||
174 | # define CPUISMIPS3 0 | 174 | # define CPUISMIPS3 0 | |
175 | # define CPUIS64BITS 0 | 175 | # define CPUIS64BITS 0 | |
176 | # define CPUISMIPS32 0 | 176 | # define CPUISMIPS32 0 | |
177 | # define CPUISMIPS32R2 0 | 177 | # define CPUISMIPS32R2 0 | |
178 | # define CPUISMIPS64 0 | 178 | # define CPUISMIPS64 0 | |
179 | # define CPUISMIPS64R2 0 | 179 | # define CPUISMIPS64R2 0 | |
180 | # define CPUISMIPSNN 0 | 180 | # define CPUISMIPSNN 0 | |
181 | # define CPUISMIPSNNR2 0 | 181 | # define CPUISMIPSNNR2 0 | |
182 | # define MIPS_HAS_R4K_MMU 0 | 182 | # define MIPS_HAS_R4K_MMU 0 | |
183 | # define MIPS_HAS_CLOCK 0 | 183 | # define MIPS_HAS_CLOCK 0 | |
184 | # define MIPS_HAS_LLSC 0 | 184 | # define MIPS_HAS_LLSC 0 | |
185 | # define MIPS_HAS_LLADDR 0 | 185 | # define MIPS_HAS_LLADDR 0 | |
186 | # define MIPS_HAS_LMMI 0 | 186 | # define MIPS_HAS_LMMI 0 | |
187 | # define MIPS_HAS_DSP 0 | 187 | # define MIPS_HAS_DSP 0 | |
188 | # define MIPS_HAS_USERLOCAL 0 | 188 | # define MIPS_HAS_USERLOCAL 0 | |
189 | 189 | |||
190 | #elif defined(MIPS3) || defined(MIPS4) | 190 | #elif defined(MIPS3) || defined(MIPS4) | |
191 | 191 | |||
192 | # define CPUISMIPS3 1 | 192 | # define CPUISMIPS3 1 | |
193 | # define CPUIS64BITS 1 | 193 | # define CPUIS64BITS 1 | |
194 | # define CPUISMIPS32 0 | 194 | # define CPUISMIPS32 0 | |
195 | # define CPUISMIPS32R2 0 | 195 | # define CPUISMIPS32R2 0 | |
196 | # define CPUISMIPS64 0 | 196 | # define CPUISMIPS64 0 | |
197 | # define CPUISMIPS64R2 0 | 197 | # define CPUISMIPS64R2 0 | |
198 | # define CPUISMIPSNN 0 | 198 | # define CPUISMIPSNN 0 | |
199 | # define CPUISMIPSNNR2 0 | 199 | # define CPUISMIPSNNR2 0 | |
200 | # define MIPS_HAS_R4K_MMU 1 | 200 | # define MIPS_HAS_R4K_MMU 1 | |
201 | # define MIPS_HAS_CLOCK 1 | 201 | # define MIPS_HAS_CLOCK 1 | |
202 | # if defined(_LOCORE) | 202 | # if defined(_LOCORE) | |
203 | # if !defined(MIPS3_4100) | 203 | # if !defined(MIPS3_4100) | |
204 | # define MIPS_HAS_LLSC 1 | 204 | # define MIPS_HAS_LLSC 1 | |
205 | # else | 205 | # else | |
206 | # define MIPS_HAS_LLSC 0 | 206 | # define MIPS_HAS_LLSC 0 | |
207 | # endif | 207 | # endif | |
208 | # else /* _LOCORE */ | 208 | # else /* _LOCORE */ | |
209 | # define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | 209 | # define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | |
210 | # endif /* _LOCORE */ | 210 | # endif /* _LOCORE */ | |
211 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 211 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
212 | # if defined(MIPS3_LOONGSON2) | 212 | # if defined(MIPS3_LOONGSON2) | |
213 | # define MIPS_HAS_LMMI ((mips_options.mips_cpu_flags & CPU_MIPS_LOONGSON2) != 0) | 213 | # define MIPS_HAS_LMMI ((mips_options.mips_cpu_flags & CPU_MIPS_LOONGSON2) != 0) | |
214 | # else | 214 | # else | |
215 | # define MIPS_HAS_LMMI 0 | 215 | # define MIPS_HAS_LMMI 0 | |
216 | # endif | 216 | # endif | |
217 | # define MIPS_HAS_DSP 0 | 217 | # define MIPS_HAS_DSP 0 | |
218 | # define MIPS_HAS_USERLOCAL 0 | 218 | # define MIPS_HAS_USERLOCAL 0 | |
219 | 219 | |||
220 | #elif defined(MIPS32) | 220 | #elif defined(MIPS32) | |
221 | 221 | |||
222 | # define CPUISMIPS3 1 | 222 | # define CPUISMIPS3 1 | |
223 | # define CPUIS64BITS 0 | 223 | # define CPUIS64BITS 0 | |
224 | # define CPUISMIPS32 1 | 224 | # define CPUISMIPS32 1 | |
225 | # define CPUISMIPS32R2 0 | 225 | # define CPUISMIPS32R2 0 | |
226 | # define CPUISMIPS64 0 | 226 | # define CPUISMIPS64 0 | |
227 | # define CPUISMIPS64R2 0 | 227 | # define CPUISMIPS64R2 0 | |
228 | # define CPUISMIPSNN 1 | 228 | # define CPUISMIPSNN 1 | |
229 | # define CPUISMIPSNNR2 0 | 229 | # define CPUISMIPSNNR2 0 | |
230 | # define MIPS_HAS_R4K_MMU 1 | 230 | # define MIPS_HAS_R4K_MMU 1 | |
231 | # define MIPS_HAS_CLOCK 1 | 231 | # define MIPS_HAS_CLOCK 1 | |
232 | # define MIPS_HAS_LLSC 1 | 232 | # define MIPS_HAS_LLSC 1 | |
233 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 233 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
234 | # define MIPS_HAS_LMMI 0 | 234 | # define MIPS_HAS_LMMI 0 | |
235 | # define MIPS_HAS_DSP 0 | 235 | # define MIPS_HAS_DSP 0 | |
236 | # define MIPS_HAS_USERLOCAL 0 | 236 | # define MIPS_HAS_USERLOCAL 0 | |
237 | 237 | |||
238 | #elif defined(MIPS32R2) | 238 | #elif defined(MIPS32R2) | |
239 | 239 | |||
240 | # define CPUISMIPS3 1 | 240 | # define CPUISMIPS3 1 | |
241 | # define CPUIS64BITS 0 | 241 | # define CPUIS64BITS 0 | |
242 | # define CPUISMIPS32 0 | 242 | # define CPUISMIPS32 0 | |
243 | # define CPUISMIPS32R2 1 | 243 | # define CPUISMIPS32R2 1 | |
244 | # define CPUISMIPS64 0 | 244 | # define CPUISMIPS64 0 | |
245 | # define CPUISMIPS64R2 0 | 245 | # define CPUISMIPS64R2 0 | |
246 | # define CPUISMIPSNN 1 | 246 | # define CPUISMIPSNN 1 | |
247 | # define CPUISMIPSNNR2 1 | 247 | # define CPUISMIPSNNR2 1 | |
248 | # define MIPS_HAS_R4K_MMU 1 | 248 | # define MIPS_HAS_R4K_MMU 1 | |
249 | # define MIPS_HAS_CLOCK 1 | 249 | # define MIPS_HAS_CLOCK 1 | |
250 | # define MIPS_HAS_LLSC 1 | 250 | # define MIPS_HAS_LLSC 1 | |
251 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 251 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
252 | # define MIPS_HAS_LMMI 0 | 252 | # define MIPS_HAS_LMMI 0 | |
253 | # define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | 253 | # define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | |
254 | # define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | 254 | # define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | |
255 | 255 | |||
256 | #elif defined(MIPS64) | 256 | #elif defined(MIPS64) | |
257 | 257 | |||
258 | # define CPUISMIPS3 1 | 258 | # define CPUISMIPS3 1 | |
259 | # define CPUIS64BITS 1 | 259 | # define CPUIS64BITS 1 | |
260 | # define CPUISMIPS32 0 | 260 | # define CPUISMIPS32 0 | |
261 | # define CPUISMIPS32R2 0 | 261 | # define CPUISMIPS32R2 0 | |
262 | # define CPUISMIPS64 1 | 262 | # define CPUISMIPS64 1 | |
263 | # define CPUISMIPS64R2 0 | 263 | # define CPUISMIPS64R2 0 | |
264 | # define CPUISMIPSNN 1 | 264 | # define CPUISMIPSNN 1 | |
265 | # define CPUISMIPSNNR2 0 | 265 | # define CPUISMIPSNNR2 0 | |
266 | # define MIPS_HAS_R4K_MMU 1 | 266 | # define MIPS_HAS_R4K_MMU 1 | |
267 | # define MIPS_HAS_CLOCK 1 | 267 | # define MIPS_HAS_CLOCK 1 | |
268 | # define MIPS_HAS_LLSC 1 | 268 | # define MIPS_HAS_LLSC 1 | |
269 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 269 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
270 | # define MIPS_HAS_LMMI 0 | 270 | # define MIPS_HAS_LMMI 0 | |
271 | # define MIPS_HAS_DSP 0 | 271 | # define MIPS_HAS_DSP 0 | |
272 | # define MIPS_HAS_USERLOCAL 0 | 272 | # define MIPS_HAS_USERLOCAL 0 | |
273 | 273 | |||
274 | #elif defined(MIPS64R2) | 274 | #elif defined(MIPS64R2) | |
275 | 275 | |||
276 | # define CPUISMIPS3 1 | 276 | # define CPUISMIPS3 1 | |
277 | # define CPUIS64BITS 1 | 277 | # define CPUIS64BITS 1 | |
278 | # define CPUISMIPS32 0 | 278 | # define CPUISMIPS32 0 | |
279 | # define CPUISMIPS32R2 0 | 279 | # define CPUISMIPS32R2 0 | |
280 | # define CPUISMIPS64 0 | 280 | # define CPUISMIPS64 0 | |
281 | # define CPUISMIPS64R2 1 | 281 | # define CPUISMIPS64R2 1 | |
282 | # define CPUISMIPSNN 1 | 282 | # define CPUISMIPSNN 1 | |
283 | # define CPUISMIPSNNR2 1 | 283 | # define CPUISMIPSNNR2 1 | |
284 | # define MIPS_HAS_R4K_MMU 1 | 284 | # define MIPS_HAS_R4K_MMU 1 | |
285 | # define MIPS_HAS_CLOCK 1 | 285 | # define MIPS_HAS_CLOCK 1 | |
286 | # define MIPS_HAS_LLSC 1 | 286 | # define MIPS_HAS_LLSC 1 | |
287 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 287 | # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
288 | # define MIPS_HAS_LMMI 0 | 288 | # define MIPS_HAS_LMMI 0 | |
289 | # define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | 289 | # define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | |
290 | # define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | 290 | # define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | |
291 | 291 | |||
292 | #endif | 292 | #endif | |
293 | 293 | |||
294 | #else /* run-time test */ | 294 | #else /* run-time test */ | |
295 | 295 | |||
296 | #ifdef MIPS1 | 296 | #ifdef MIPS1 | |
297 | #define MIPS_HAS_R4K_MMU (mips_options.mips_has_r4k_mmu) | 297 | #define MIPS_HAS_R4K_MMU (mips_options.mips_has_r4k_mmu) | |
298 | #define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | 298 | #define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | |
299 | #else | 299 | #else | |
300 | #define MIPS_HAS_R4K_MMU 1 | 300 | #define MIPS_HAS_R4K_MMU 1 | |
301 | #if !defined(MIPS3_4100) | 301 | #if !defined(MIPS3_4100) | |
302 | #define MIPS_HAS_LLSC 1 | 302 | #define MIPS_HAS_LLSC 1 | |
303 | #else | 303 | #else | |
304 | #define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | 304 | #define MIPS_HAS_LLSC (mips_options.mips_has_llsc) | |
305 | #endif | 305 | #endif | |
306 | #endif | 306 | #endif | |
307 | #define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | 307 | #define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) | |
308 | #define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | 308 | #define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) | |
309 | #define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | 309 | #define MIPS_HAS_USERLOCAL (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_USERLOCAL) | |
310 | 310 | |||
311 | /* This test is ... rather bogus */ | 311 | /* This test is ... rather bogus */ | |
312 | #define CPUISMIPS3 ((mips_options.mips_cpu_arch & \ | 312 | #define CPUISMIPS3 ((mips_options.mips_cpu_arch & \ | |
313 | (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0) | 313 | (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0) | |
314 | 314 | |||
315 | /* And these aren't much better while the previous test exists as is... */ | 315 | /* And these aren't much better while the previous test exists as is... */ | |
316 | #define CPUISMIPS4 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS4) != 0) | 316 | #define CPUISMIPS4 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS4) != 0) | |
317 | #define CPUISMIPS5 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS5) != 0) | 317 | #define CPUISMIPS5 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS5) != 0) | |
318 | #define CPUISMIPS32 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS32) != 0) | 318 | #define CPUISMIPS32 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS32) != 0) | |
319 | #define CPUISMIPS32R2 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS32R2) != 0) | 319 | #define CPUISMIPS32R2 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS32R2) != 0) | |
320 | #define CPUISMIPS64 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS64) != 0) | 320 | #define CPUISMIPS64 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS64) != 0) | |
321 | #define CPUISMIPS64R2 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS64R2) != 0) | 321 | #define CPUISMIPS64R2 ((mips_options.mips_cpu_arch & CPU_ARCH_MIPS64R2) != 0) | |
322 | #define CPUISMIPSNN ((mips_options.mips_cpu_arch & \ | 322 | #define CPUISMIPSNN ((mips_options.mips_cpu_arch & \ | |
323 | (CPU_ARCH_MIPS32 | CPU_ARCH_MIPS32R2 | CPU_ARCH_MIPS64 | CPU_ARCH_MIPS64R2)) != 0) | 323 | (CPU_ARCH_MIPS32 | CPU_ARCH_MIPS32R2 | CPU_ARCH_MIPS64 | CPU_ARCH_MIPS64R2)) != 0) | |
324 | #define CPUISMIPSNNR2 ((mips_options.mips_cpu_arch & \ | 324 | #define CPUISMIPSNNR2 ((mips_options.mips_cpu_arch & \ | |
325 | (CPU_ARCH_MIPS32R2 | CPU_ARCH_MIPS64R2)) != 0) | 325 | (CPU_ARCH_MIPS32R2 | CPU_ARCH_MIPS64R2)) != 0) | |
326 | #define CPUIS64BITS ((mips_options.mips_cpu_arch & \ | 326 | #define CPUIS64BITS ((mips_options.mips_cpu_arch & \ | |
327 | (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS64 | CPU_ARCH_MIPS64R2)) != 0) | 327 | (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS64 | CPU_ARCH_MIPS64R2)) != 0) | |
328 | 328 | |||
329 | #define MIPS_HAS_CLOCK (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) | 329 | #define MIPS_HAS_CLOCK (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) | |
330 | 330 | |||
331 | #endif /* run-time test */ | 331 | #endif /* run-time test */ | |
332 | 332 | |||
333 | #ifndef __ASSEMBLER__ | 333 | #ifndef __ASSEMBLER__ | |
334 | 334 | |||
335 | struct tlbmask; | 335 | struct tlbmask; | |
336 | struct trapframe; | 336 | struct trapframe; | |
337 | 337 | |||
338 | void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *); | 338 | void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *); | |
339 | void ast(void); | 339 | void ast(void); | |
340 | 340 | |||
341 | void mips_fpu_trap(vaddr_t, struct trapframe *); | 341 | void mips_fpu_trap(vaddr_t, struct trapframe *); | |
342 | void mips_fpu_intr(vaddr_t, struct trapframe *); | 342 | void mips_fpu_intr(vaddr_t, struct trapframe *); | |
343 | 343 | |||
344 | vaddr_t mips_emul_branch(struct trapframe *, vaddr_t, uint32_t, bool); | 344 | vaddr_t mips_emul_branch(struct trapframe *, vaddr_t, uint32_t, bool); | |
345 | void mips_emul_inst(uint32_t, uint32_t, vaddr_t, struct trapframe *); | 345 | void mips_emul_inst(uint32_t, uint32_t, vaddr_t, struct trapframe *); | |
346 | 346 | |||
347 | void mips_emul_fp(uint32_t, struct trapframe *, uint32_t); | 347 | void mips_emul_fp(uint32_t, struct trapframe *, uint32_t); | |
348 | void mips_emul_branchdelayslot(uint32_t, struct trapframe *, uint32_t); | 348 | void mips_emul_branchdelayslot(uint32_t, struct trapframe *, uint32_t); | |
349 | 349 | |||
350 | void mips_emul_lwc0(uint32_t, struct trapframe *, uint32_t); | |||
351 | void mips_emul_swc0(uint32_t, struct trapframe *, uint32_t); | |||
352 | void mips_emul_special(uint32_t, struct trapframe *, uint32_t); | 350 | void mips_emul_special(uint32_t, struct trapframe *, uint32_t); | |
353 | void mips_emul_special3(uint32_t, struct trapframe *, uint32_t); | 351 | void mips_emul_special3(uint32_t, struct trapframe *, uint32_t); | |
354 | 352 | |||
355 | void mips_emul_lwc1(uint32_t, struct trapframe *, uint32_t); | 353 | void mips_emul_lwc1(uint32_t, struct trapframe *, uint32_t); | |
356 | void mips_emul_swc1(uint32_t, struct trapframe *, uint32_t); | 354 | void mips_emul_swc1(uint32_t, struct trapframe *, uint32_t); | |
357 | void mips_emul_ldc1(uint32_t, struct trapframe *, uint32_t); | 355 | void mips_emul_ldc1(uint32_t, struct trapframe *, uint32_t); | |
358 | void mips_emul_sdc1(uint32_t, struct trapframe *, uint32_t); | 356 | void mips_emul_sdc1(uint32_t, struct trapframe *, uint32_t); | |
359 | 357 | |||
360 | void mips_emul_lb(uint32_t, struct trapframe *, uint32_t); | 358 | void mips_emul_lb(uint32_t, struct trapframe *, uint32_t); | |
361 | void mips_emul_lbu(uint32_t, struct trapframe *, uint32_t); | 359 | void mips_emul_lbu(uint32_t, struct trapframe *, uint32_t); | |
362 | void mips_emul_lh(uint32_t, struct trapframe *, uint32_t); | 360 | void mips_emul_lh(uint32_t, struct trapframe *, uint32_t); | |
363 | void mips_emul_lhu(uint32_t, struct trapframe *, uint32_t); | 361 | void mips_emul_lhu(uint32_t, struct trapframe *, uint32_t); | |
364 | void mips_emul_lw(uint32_t, struct trapframe *, uint32_t); | 362 | void mips_emul_lw(uint32_t, struct trapframe *, uint32_t); | |
365 | void mips_emul_lwl(uint32_t, struct trapframe *, uint32_t); | 363 | void mips_emul_lwl(uint32_t, struct trapframe *, uint32_t); | |
366 | void mips_emul_lwr(uint32_t, struct trapframe *, uint32_t); | 364 | void mips_emul_lwr(uint32_t, struct trapframe *, uint32_t); | |
367 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | 365 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | |
368 | void mips_emul_lwu(uint32_t, struct trapframe *, uint32_t); | 366 | void mips_emul_lwu(uint32_t, struct trapframe *, uint32_t); | |
369 | void mips_emul_ld(uint32_t, struct trapframe *, uint32_t); | 367 | void mips_emul_ld(uint32_t, struct trapframe *, uint32_t); | |
370 | void mips_emul_ldl(uint32_t, struct trapframe *, uint32_t); | 368 | void mips_emul_ldl(uint32_t, struct trapframe *, uint32_t); | |
371 | void mips_emul_ldr(uint32_t, struct trapframe *, uint32_t); | 369 | void mips_emul_ldr(uint32_t, struct trapframe *, uint32_t); | |
372 | #endif | 370 | #endif | |
373 | void mips_emul_sb(uint32_t, struct trapframe *, uint32_t); | 371 | void mips_emul_sb(uint32_t, struct trapframe *, uint32_t); | |
374 | void mips_emul_sh(uint32_t, struct trapframe *, uint32_t); | 372 | void mips_emul_sh(uint32_t, struct trapframe *, uint32_t); | |
375 | void mips_emul_sw(uint32_t, struct trapframe *, uint32_t); | 373 | void mips_emul_sw(uint32_t, struct trapframe *, uint32_t); | |
376 | void mips_emul_swl(uint32_t, struct trapframe *, uint32_t); | 374 | void mips_emul_swl(uint32_t, struct trapframe *, uint32_t); | |
377 | void mips_emul_swr(uint32_t, struct trapframe *, uint32_t); | 375 | void mips_emul_swr(uint32_t, struct trapframe *, uint32_t); | |
378 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | 376 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | |
379 | void mips_emul_sd(uint32_t, struct trapframe *, uint32_t); | 377 | void mips_emul_sd(uint32_t, struct trapframe *, uint32_t); | |
380 | void mips_emul_sdl(uint32_t, struct trapframe *, uint32_t); | 378 | void mips_emul_sdl(uint32_t, struct trapframe *, uint32_t); | |
381 | void mips_emul_sdr(uint32_t, struct trapframe *, uint32_t); | 379 | void mips_emul_sdr(uint32_t, struct trapframe *, uint32_t); | |
382 | #endif | 380 | #endif | |
383 | 381 | |||
384 | uint32_t mips_cp0_cause_read(void); | 382 | uint32_t mips_cp0_cause_read(void); | |
385 | void mips_cp0_cause_write(uint32_t); | 383 | void mips_cp0_cause_write(uint32_t); | |
386 | uint32_t mips_cp0_status_read(void); | 384 | uint32_t mips_cp0_status_read(void); | |
387 | void mips_cp0_status_write(uint32_t); | 385 | void mips_cp0_status_write(uint32_t); | |
388 | 386 | |||
389 | void softint_process(uint32_t); | 387 | void softint_process(uint32_t); | |
390 | void softint_fast_dispatch(struct lwp *, int); | 388 | void softint_fast_dispatch(struct lwp *, int); | |
391 | 389 | |||
392 | /* | 390 | /* | |
393 | * Convert an address to an offset used in a MIPS jump instruction. The offset | 391 | * Convert an address to an offset used in a MIPS jump instruction. The offset | |
394 | * contains the low 28 bits (allowing a jump to anywhere within the same 256MB | 392 | * contains the low 28 bits (allowing a jump to anywhere within the same 256MB | |
395 | * segment of address space) of the address but since mips instructions are | 393 | * segment of address space) of the address but since mips instructions are | |
396 | * always on a 4 byte boundary the low 2 bits are always zero so the 28 bits | 394 | * always on a 4 byte boundary the low 2 bits are always zero so the 28 bits | |
397 | * get shifted right by 2 bits leaving us with a 26 bit result. To make the | 395 | * get shifted right by 2 bits leaving us with a 26 bit result. To make the | |
398 | * offset, we shift left to clear the upper four bits and then right by 6. | 396 | * offset, we shift left to clear the upper four bits and then right by 6. | |
399 | */ | 397 | */ | |
400 | #define fixup_addr2offset(x) ((((uint32_t)(uintptr_t)(x)) << 4) >> 6) | 398 | #define fixup_addr2offset(x) ((((uint32_t)(uintptr_t)(x)) << 4) >> 6) | |
401 | typedef bool (*mips_fixup_callback_t)(int32_t, uint32_t [2], void *); | 399 | typedef bool (*mips_fixup_callback_t)(int32_t, uint32_t [2], void *); | |
402 | struct mips_jump_fixup_info { | 400 | struct mips_jump_fixup_info { | |
403 | uint32_t jfi_stub; | 401 | uint32_t jfi_stub; | |
404 | uint32_t jfi_real; | 402 | uint32_t jfi_real; | |
405 | }; | 403 | }; | |
406 | 404 | |||
407 | void fixup_splcalls(void); /* splstubs.c */ | 405 | void fixup_splcalls(void); /* splstubs.c */ | |
408 | bool mips_fixup_exceptions(mips_fixup_callback_t, void *); | 406 | bool mips_fixup_exceptions(mips_fixup_callback_t, void *); | |
409 | bool mips_fixup_zero_relative(int32_t, uint32_t [2], void *); | 407 | bool mips_fixup_zero_relative(int32_t, uint32_t [2], void *); | |
410 | intptr_t | 408 | intptr_t | |
411 | mips_fixup_addr(const uint32_t *); | 409 | mips_fixup_addr(const uint32_t *); | |
412 | void mips_fixup_stubs(uint32_t *, uint32_t *); | 410 | void mips_fixup_stubs(uint32_t *, uint32_t *); | |
413 | 411 | |||
414 | /* | 412 | /* | |
415 | * Define these stubs... | 413 | * Define these stubs... | |
416 | */ | 414 | */ | |
417 | void mips_cpu_switch_resume(struct lwp *); | 415 | void mips_cpu_switch_resume(struct lwp *); | |
418 | void wbflush(void); | 416 | void wbflush(void); | |
419 | 417 | |||
420 | #ifdef MIPS1 | 418 | #ifdef MIPS1 | |
421 | void mips1_tlb_invalidate_all(void); | 419 | void mips1_tlb_invalidate_all(void); | |
422 | 420 | |||
423 | uint32_t tx3900_cp0_config_read(void); | 421 | uint32_t tx3900_cp0_config_read(void); | |
424 | #endif | 422 | #endif | |
425 | 423 | |||
426 | #ifdef MIPS3_PLUS | 424 | #ifdef MIPS3_PLUS | |
427 | uint32_t mips3_cp0_compare_read(void); | 425 | uint32_t mips3_cp0_compare_read(void); | |
428 | void mips3_cp0_compare_write(uint32_t); | 426 | void mips3_cp0_compare_write(uint32_t); | |
429 | 427 | |||
430 | uint32_t mips3_cp0_config_read(void); | 428 | uint32_t mips3_cp0_config_read(void); | |
431 | void mips3_cp0_config_write(uint32_t); | 429 | void mips3_cp0_config_write(uint32_t); | |
432 | 430 | |||
433 | #ifdef MIPSNN | 431 | #ifdef MIPSNN | |
434 | uint32_t mipsNN_cp0_config1_read(void); | 432 | uint32_t mipsNN_cp0_config1_read(void); | |
435 | void mipsNN_cp0_config1_write(uint32_t); | 433 | void mipsNN_cp0_config1_write(uint32_t); | |
436 | uint32_t mipsNN_cp0_config2_read(void); | 434 | uint32_t mipsNN_cp0_config2_read(void); | |
437 | uint32_t mipsNN_cp0_config3_read(void); | 435 | uint32_t mipsNN_cp0_config3_read(void); | |
438 | uint32_t mipsNN_cp0_config4_read(void); | 436 | uint32_t mipsNN_cp0_config4_read(void); | |
439 | uint32_t mipsNN_cp0_config5_read(void); | 437 | uint32_t mipsNN_cp0_config5_read(void); | |
440 | uint32_t mipsNN_cp0_config6_read(void); | 438 | uint32_t mipsNN_cp0_config6_read(void); | |
441 | uint32_t mipsNN_cp0_config7_read(void); | 439 | uint32_t mipsNN_cp0_config7_read(void); | |
442 | 440 | |||
443 | intptr_t mipsNN_cp0_watchlo_read(u_int); | 441 | intptr_t mipsNN_cp0_watchlo_read(u_int); | |
444 | void mipsNN_cp0_watchlo_write(u_int, intptr_t); | 442 | void mipsNN_cp0_watchlo_write(u_int, intptr_t); | |
445 | uint32_t mipsNN_cp0_watchhi_read(u_int); | 443 | uint32_t mipsNN_cp0_watchhi_read(u_int); | |
446 | void mipsNN_cp0_watchhi_write(u_int, uint32_t); | 444 | void mipsNN_cp0_watchhi_write(u_int, uint32_t); | |
447 | 445 | |||
448 | int32_t mipsNN_cp0_ebase_read(void); | 446 | int32_t mipsNN_cp0_ebase_read(void); | |
449 | void mipsNN_cp0_ebase_write(int32_t); | 447 | void mipsNN_cp0_ebase_write(int32_t); | |
450 | 448 | |||
451 | uint32_t mipsNN_cp0_rdhwr_cpunum(void); | 449 | uint32_t mipsNN_cp0_rdhwr_cpunum(void); | |
452 | 450 | |||
453 | #ifdef MIPSNNR2 | 451 | #ifdef MIPSNNR2 | |
454 | void mipsNN_cp0_hwrena_write(uint32_t); | 452 | void mipsNN_cp0_hwrena_write(uint32_t); | |
455 | void mipsNN_cp0_userlocal_write(void *); | 453 | void mipsNN_cp0_userlocal_write(void *); | |
456 | #endif | 454 | #endif | |
457 | #endif /* MIPSNN */ | 455 | #endif /* MIPSNN */ | |
458 | 456 | |||
459 | uint32_t mips3_cp0_count_read(void); | 457 | uint32_t mips3_cp0_count_read(void); | |
460 | void mips3_cp0_count_write(uint32_t); | 458 | void mips3_cp0_count_write(uint32_t); | |
461 | 459 | |||
462 | uint32_t mips3_cp0_wired_read(void); | 460 | uint32_t mips3_cp0_wired_read(void); | |
463 | void mips3_cp0_wired_write(uint32_t); | 461 | void mips3_cp0_wired_write(uint32_t); | |
464 | void mips3_cp0_pg_mask_write(uint32_t); | 462 | void mips3_cp0_pg_mask_write(uint32_t); | |
465 | 463 | |||
466 | #endif /* MIPS3_PLUS */ | 464 | #endif /* MIPS3_PLUS */ | |
467 | 465 | |||
468 | /* 64-bit address space accessor for n32, n64 ABI */ | 466 | /* 64-bit address space accessor for n32, n64 ABI */ | |
469 | /* 32-bit address space accessor for o32 ABI */ | 467 | /* 32-bit address space accessor for o32 ABI */ | |
470 | static inline uint8_t mips_lbu(register_t addr) __unused; | 468 | static inline uint8_t mips_lbu(register_t addr) __unused; | |
471 | static inline void mips_sb(register_t addr, uint8_t val) __unused; | 469 | static inline void mips_sb(register_t addr, uint8_t val) __unused; | |
472 | static inline uint16_t mips_lhu(register_t addr) __unused; | 470 | static inline uint16_t mips_lhu(register_t addr) __unused; | |
473 | static inline void mips_sh(register_t addr, uint16_t val) __unused; | 471 | static inline void mips_sh(register_t addr, uint16_t val) __unused; | |
474 | static inline uint32_t mips_lwu(register_t addr) __unused; | 472 | static inline uint32_t mips_lwu(register_t addr) __unused; | |
475 | static inline void mips_sw(register_t addr, uint32_t val) __unused; | 473 | static inline void mips_sw(register_t addr, uint32_t val) __unused; | |
476 | #ifdef MIPS3_64BIT | 474 | #ifdef MIPS3_64BIT | |
477 | #if defined(__mips_o32) | 475 | #if defined(__mips_o32) | |
478 | uint64_t mips3_ld(register_t addr); | 476 | uint64_t mips3_ld(register_t addr); | |
479 | void mips3_sd(register_t addr, uint64_t val); | 477 | void mips3_sd(register_t addr, uint64_t val); | |
480 | #else | 478 | #else | |
481 | static inline uint64_t mips3_ld(register_t addr) __unused; | 479 | static inline uint64_t mips3_ld(register_t addr) __unused; | |
482 | static inline void mips3_sd(register_t addr, uint64_t val) __unused; | 480 | static inline void mips3_sd(register_t addr, uint64_t val) __unused; | |
483 | #endif | 481 | #endif | |
484 | #endif | 482 | #endif | |
485 | 483 | |||
486 | static inline uint8_t | 484 | static inline uint8_t | |
487 | mips_lbu(register_t addr) | 485 | mips_lbu(register_t addr) | |
488 | { | 486 | { | |
489 | uint8_t rv; | 487 | uint8_t rv; | |
490 | #if defined(__mips_n32) | 488 | #if defined(__mips_n32) | |
491 | __asm volatile("lbu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | 489 | __asm volatile("lbu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | |
492 | #else | 490 | #else | |
493 | rv = *(const volatile uint8_t *)addr; | 491 | rv = *(const volatile uint8_t *)addr; | |
494 | #endif | 492 | #endif | |
495 | return rv; | 493 | return rv; | |
496 | } | 494 | } | |
497 | 495 | |||
498 | static inline uint16_t | 496 | static inline uint16_t | |
499 | mips_lhu(register_t addr) | 497 | mips_lhu(register_t addr) | |
500 | { | 498 | { | |
501 | uint16_t rv; | 499 | uint16_t rv; | |
502 | #if defined(__mips_n32) | 500 | #if defined(__mips_n32) | |
503 | __asm volatile("lhu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | 501 | __asm volatile("lhu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | |
504 | #else | 502 | #else | |
505 | rv = *(const volatile uint16_t *)addr; | 503 | rv = *(const volatile uint16_t *)addr; | |
506 | #endif | 504 | #endif | |
507 | return rv; | 505 | return rv; | |
508 | } | 506 | } | |
509 | 507 | |||
510 | static inline uint32_t | 508 | static inline uint32_t | |
511 | mips_lwu(register_t addr) | 509 | mips_lwu(register_t addr) | |
512 | { | 510 | { | |
513 | uint32_t rv; | 511 | uint32_t rv; | |
514 | #if defined(__mips_n32) | 512 | #if defined(__mips_n32) | |
515 | __asm volatile("lwu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | 513 | __asm volatile("lwu\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | |
516 | #else | 514 | #else | |
517 | rv = *(const volatile uint32_t *)addr; | 515 | rv = *(const volatile uint32_t *)addr; | |
518 | #endif | 516 | #endif | |
519 | return (rv); | 517 | return (rv); | |
520 | } | 518 | } | |
521 | 519 | |||
522 | #if defined(MIPS3_64BIT) && !defined(__mips_o32) | 520 | #if defined(MIPS3_64BIT) && !defined(__mips_o32) | |
523 | static inline uint64_t | 521 | static inline uint64_t | |
524 | mips3_ld(register_t addr) | 522 | mips3_ld(register_t addr) | |
525 | { | 523 | { | |
526 | uint64_t rv; | 524 | uint64_t rv; | |
527 | #if defined(__mips_n32) | 525 | #if defined(__mips_n32) | |
528 | __asm volatile("ld\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | 526 | __asm volatile("ld\t%0, 0(%1)" : "=r"(rv) : "d"(addr)); | |
529 | #elif defined(_LP64) | 527 | #elif defined(_LP64) | |
530 | rv = *(const volatile uint64_t *)addr; | 528 | rv = *(const volatile uint64_t *)addr; | |
531 | #else | 529 | #else | |
532 | #error unknown ABI | 530 | #error unknown ABI | |
533 | #endif | 531 | #endif | |
534 | return (rv); | 532 | return (rv); | |
535 | } | 533 | } | |
536 | #endif /* MIPS3_64BIT && !__mips_o32 */ | 534 | #endif /* MIPS3_64BIT && !__mips_o32 */ | |
537 | 535 | |||
538 | static inline void | 536 | static inline void | |
539 | mips_sb(register_t addr, uint8_t val) | 537 | mips_sb(register_t addr, uint8_t val) | |
540 | { | 538 | { | |
541 | #if defined(__mips_n32) | 539 | #if defined(__mips_n32) | |
542 | __asm volatile("sb\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | 540 | __asm volatile("sb\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | |
543 | #else | 541 | #else | |
544 | *(volatile uint8_t *)addr = val; | 542 | *(volatile uint8_t *)addr = val; | |
545 | #endif | 543 | #endif | |
546 | } | 544 | } | |
547 | 545 | |||
548 | static inline void | 546 | static inline void | |
549 | mips_sh(register_t addr, uint16_t val) | 547 | mips_sh(register_t addr, uint16_t val) | |
550 | { | 548 | { | |
551 | #if defined(__mips_n32) | 549 | #if defined(__mips_n32) | |
552 | __asm volatile("sh\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | 550 | __asm volatile("sh\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | |
553 | #else | 551 | #else | |
554 | *(volatile uint16_t *)addr = val; | 552 | *(volatile uint16_t *)addr = val; | |
555 | #endif | 553 | #endif | |
556 | } | 554 | } | |
557 | 555 | |||
558 | static inline void | 556 | static inline void | |
559 | mips_sw(register_t addr, uint32_t val) | 557 | mips_sw(register_t addr, uint32_t val) | |
560 | { | 558 | { | |
561 | #if defined(__mips_n32) | 559 | #if defined(__mips_n32) | |
562 | __asm volatile("sw\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | 560 | __asm volatile("sw\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | |
563 | #else | 561 | #else | |
564 | *(volatile uint32_t *)addr = val; | 562 | *(volatile uint32_t *)addr = val; | |
565 | #endif | 563 | #endif | |
566 | } | 564 | } | |
567 | 565 | |||
568 | #if defined(MIPS3_64BIT) && !defined(__mips_o32) | 566 | #if defined(MIPS3_64BIT) && !defined(__mips_o32) | |
569 | static inline void | 567 | static inline void | |
570 | mips3_sd(register_t addr, uint64_t val) | 568 | mips3_sd(register_t addr, uint64_t val) | |
571 | { | 569 | { | |
572 | #if defined(__mips_n32) | 570 | #if defined(__mips_n32) | |
573 | __asm volatile("sd\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | 571 | __asm volatile("sd\t%1, 0(%0)" :: "d"(addr), "r"(val) : "memory"); | |
574 | #else | 572 | #else | |
575 | *(volatile uint64_t *)addr = val; | 573 | *(volatile uint64_t *)addr = val; | |
576 | #endif | 574 | #endif | |
577 | } | 575 | } | |
578 | #endif /* MIPS3_64BIT && !__mips_o32 */ | 576 | #endif /* MIPS3_64BIT && !__mips_o32 */ | |
579 | 577 | |||
580 | /* | 578 | /* | |
581 | * A vector with an entry for each mips-ISA-level dependent | 579 | * A vector with an entry for each mips-ISA-level dependent | |
582 | * locore function, and macros which jump through it. | 580 | * locore function, and macros which jump through it. | |
583 | */ | 581 | */ | |
584 | typedef struct { | 582 | typedef struct { | |
585 | void (*ljv_cpu_switch_resume)(struct lwp *); | 583 | void (*ljv_cpu_switch_resume)(struct lwp *); | |
586 | intptr_t ljv_lwp_trampoline; | 584 | intptr_t ljv_lwp_trampoline; | |
587 | void (*ljv_wbflush)(void); | 585 | void (*ljv_wbflush)(void); | |
588 | tlb_asid_t (*ljv_tlb_get_asid)(void); | 586 | tlb_asid_t (*ljv_tlb_get_asid)(void); | |
589 | void (*ljv_tlb_set_asid)(tlb_asid_t pid); | 587 | void (*ljv_tlb_set_asid)(tlb_asid_t pid); | |
590 | void (*ljv_tlb_invalidate_asids)(tlb_asid_t, tlb_asid_t); | 588 | void (*ljv_tlb_invalidate_asids)(tlb_asid_t, tlb_asid_t); | |
591 | void (*ljv_tlb_invalidate_addr)(vaddr_t, tlb_asid_t); | 589 | void (*ljv_tlb_invalidate_addr)(vaddr_t, tlb_asid_t); | |
592 | void (*ljv_tlb_invalidate_globals)(void); | 590 | void (*ljv_tlb_invalidate_globals)(void); | |
593 | void (*ljv_tlb_invalidate_all)(void); | 591 | void (*ljv_tlb_invalidate_all)(void); | |
594 | u_int (*ljv_tlb_record_asids)(u_long *, tlb_asid_t); | 592 | u_int (*ljv_tlb_record_asids)(u_long *, tlb_asid_t); | |
595 | int (*ljv_tlb_update_addr)(vaddr_t, tlb_asid_t, pt_entry_t, bool); | 593 | int (*ljv_tlb_update_addr)(vaddr_t, tlb_asid_t, pt_entry_t, bool); | |
596 | void (*ljv_tlb_read_entry)(size_t, struct tlbmask *); | 594 | void (*ljv_tlb_read_entry)(size_t, struct tlbmask *); | |
597 | void (*ljv_tlb_write_entry)(size_t, const struct tlbmask *); | 595 | void (*ljv_tlb_write_entry)(size_t, const struct tlbmask *); | |
598 | } mips_locore_jumpvec_t; | 596 | } mips_locore_jumpvec_t; | |
599 | 597 | |||
600 | typedef struct { | 598 | typedef struct { | |
601 | u_int (*lav_atomic_cas_uint)(volatile u_int *, u_int, u_int); | 599 | u_int (*lav_atomic_cas_uint)(volatile u_int *, u_int, u_int); | |
602 | u_long (*lav_atomic_cas_ulong)(volatile u_long *, u_long, u_long); | 600 | u_long (*lav_atomic_cas_ulong)(volatile u_long *, u_long, u_long); | |
603 | int (*lav_ucas_32)(volatile uint32_t *, uint32_t, uint32_t, | 601 | int (*lav_ucas_32)(volatile uint32_t *, uint32_t, uint32_t, | |
604 | uint32_t *); | 602 | uint32_t *); | |
605 | int (*lav_ucas_64)(volatile uint64_t *, uint64_t, uint64_t, | 603 | int (*lav_ucas_64)(volatile uint64_t *, uint64_t, uint64_t, | |
606 | uint64_t *); | 604 | uint64_t *); | |
607 | void (*lav_mutex_enter)(kmutex_t *); | 605 | void (*lav_mutex_enter)(kmutex_t *); | |
608 | void (*lav_mutex_exit)(kmutex_t *); | 606 | void (*lav_mutex_exit)(kmutex_t *); | |
609 | void (*lav_mutex_spin_enter)(kmutex_t *); | 607 | void (*lav_mutex_spin_enter)(kmutex_t *); | |
610 | void (*lav_mutex_spin_exit)(kmutex_t *); | 608 | void (*lav_mutex_spin_exit)(kmutex_t *); | |
611 | } mips_locore_atomicvec_t; | 609 | } mips_locore_atomicvec_t; | |
612 | 610 | |||
613 | void mips_set_wbflush(void (*)(void)); | 611 | void mips_set_wbflush(void (*)(void)); | |
614 | void mips_wait_idle(void); | 612 | void mips_wait_idle(void); | |
615 | 613 | |||
616 | void stacktrace(void); | 614 | void stacktrace(void); | |
617 | void logstacktrace(void); | 615 | void logstacktrace(void); | |
618 | 616 | |||
619 | struct cpu_info; | 617 | struct cpu_info; | |
620 | struct splsw; | 618 | struct splsw; | |
621 | 619 | |||
622 | struct locoresw { | 620 | struct locoresw { | |
623 | void (*lsw_wbflush)(void); | 621 | void (*lsw_wbflush)(void); | |
624 | void (*lsw_cpu_idle)(void); | 622 | void (*lsw_cpu_idle)(void); | |
625 | int (*lsw_send_ipi)(struct cpu_info *, int); | 623 | int (*lsw_send_ipi)(struct cpu_info *, int); | |
626 | void (*lsw_cpu_offline_md)(void); | 624 | void (*lsw_cpu_offline_md)(void); | |
627 | void (*lsw_cpu_init)(struct cpu_info *); | 625 | void (*lsw_cpu_init)(struct cpu_info *); | |
628 | void (*lsw_cpu_run)(struct cpu_info *); | 626 | void (*lsw_cpu_run)(struct cpu_info *); | |
629 | int (*lsw_bus_error)(unsigned int); | 627 | int (*lsw_bus_error)(unsigned int); | |
630 | }; | 628 | }; | |
631 | 629 | |||
632 | struct mips_vmfreelist { | 630 | struct mips_vmfreelist { | |
633 | paddr_t fl_start; | 631 | paddr_t fl_start; | |
634 | paddr_t fl_end; | 632 | paddr_t fl_end; | |
635 | int fl_freelist; | 633 | int fl_freelist; | |
636 | }; | 634 | }; | |
637 | 635 | |||
638 | struct cpu_info * | 636 | struct cpu_info * | |
639 | cpu_info_alloc(struct pmap_tlb_info *, cpuid_t, cpuid_t, cpuid_t, | 637 | cpu_info_alloc(struct pmap_tlb_info *, cpuid_t, cpuid_t, cpuid_t, | |
640 | cpuid_t); | 638 | cpuid_t); | |
641 | void cpu_attach_common(device_t, struct cpu_info *); | 639 | void cpu_attach_common(device_t, struct cpu_info *); | |
642 | void cpu_startup_common(void); | 640 | void cpu_startup_common(void); | |
643 | 641 | |||
644 | #ifdef MULTIPROCESSOR | 642 | #ifdef MULTIPROCESSOR | |
645 | void cpu_hatch(struct cpu_info *ci); | 643 | void cpu_hatch(struct cpu_info *ci); | |
646 | void cpu_trampoline(void); | 644 | void cpu_trampoline(void); | |
647 | void cpu_halt(void); | 645 | void cpu_halt(void); | |
648 | void cpu_halt_others(void); | 646 | void cpu_halt_others(void); | |
649 | void cpu_pause(struct reg *); | 647 | void cpu_pause(struct reg *); | |
650 | void cpu_pause_others(void); | 648 | void cpu_pause_others(void); | |
651 | void cpu_resume(cpuid_t); | 649 | void cpu_resume(cpuid_t); | |
652 | void cpu_resume_others(void); | 650 | void cpu_resume_others(void); | |
653 | bool cpu_is_paused(cpuid_t); | 651 | bool cpu_is_paused(cpuid_t); | |
654 | void cpu_debug_dump(void); | 652 | void cpu_debug_dump(void); | |
655 | 653 | |||
656 | extern kcpuset_t *cpus_running; | 654 | extern kcpuset_t *cpus_running; | |
657 | extern kcpuset_t *cpus_hatched; | 655 | extern kcpuset_t *cpus_hatched; | |
658 | extern kcpuset_t *cpus_paused; | 656 | extern kcpuset_t *cpus_paused; | |
659 | extern kcpuset_t *cpus_resumed; | 657 | extern kcpuset_t *cpus_resumed; | |
660 | extern kcpuset_t *cpus_halted; | 658 | extern kcpuset_t *cpus_halted; | |
661 | #endif | 659 | #endif | |
662 | 660 | |||
663 | /* copy.S */ | 661 | /* copy.S */ | |
664 | uint32_t mips_ufetch32(const void *); | 662 | uint32_t mips_ufetch32(const void *); | |
665 | int mips_ustore32_isync(void *, uint32_t); | 663 | int mips_ustore32_isync(void *, uint32_t); | |
666 | 664 | |||
667 | int32_t kfetch_32(volatile uint32_t *, uint32_t); | 665 | int32_t kfetch_32(volatile uint32_t *, uint32_t); | |
668 | 666 | |||
669 | /* trap.c */ | 667 | /* trap.c */ | |
670 | void netintr(void); | 668 | void netintr(void); | |
671 | 669 | |||
672 | /* mips_dsp.c */ | 670 | /* mips_dsp.c */ | |
673 | void dsp_init(void); | 671 | void dsp_init(void); | |
674 | void dsp_discard(lwp_t *); | 672 | void dsp_discard(lwp_t *); | |
675 | void dsp_load(void); | 673 | void dsp_load(void); | |
676 | void dsp_save(lwp_t *); | 674 | void dsp_save(lwp_t *); | |
677 | bool dsp_used_p(const lwp_t *); | 675 | bool dsp_used_p(const lwp_t *); | |
678 | extern const pcu_ops_t mips_dsp_ops; | 676 | extern const pcu_ops_t mips_dsp_ops; | |
679 | 677 | |||
680 | /* mips_fpu.c */ | 678 | /* mips_fpu.c */ | |
681 | void fpu_init(void); | 679 | void fpu_init(void); | |
682 | void fpu_discard(lwp_t *); | 680 | void fpu_discard(lwp_t *); | |
683 | void fpu_load(void); | 681 | void fpu_load(void); | |
684 | void fpu_save(lwp_t *); | 682 | void fpu_save(lwp_t *); | |
685 | bool fpu_used_p(const lwp_t *); | 683 | bool fpu_used_p(const lwp_t *); | |
686 | extern const pcu_ops_t mips_fpu_ops; | 684 | extern const pcu_ops_t mips_fpu_ops; | |
687 | 685 | |||
688 | /* mips_machdep.c */ | 686 | /* mips_machdep.c */ | |
689 | void dumpsys(void); | 687 | void dumpsys(void); | |
690 | int savectx(struct pcb *); | 688 | int savectx(struct pcb *); | |
691 | void cpu_identify(device_t); | 689 | void cpu_identify(device_t); | |
692 | 690 | |||
693 | /* locore*.S */ | 691 | /* locore*.S */ | |
694 | int badaddr(void *, size_t); | 692 | int badaddr(void *, size_t); | |
695 | int badaddr64(uint64_t, size_t); | 693 | int badaddr64(uint64_t, size_t); | |
696 | 694 | |||
697 | /* vm_machdep.c */ | 695 | /* vm_machdep.c */ | |
698 | int ioaccess(vaddr_t, paddr_t, vsize_t); | 696 | int ioaccess(vaddr_t, paddr_t, vsize_t); | |
699 | int iounaccess(vaddr_t, vsize_t); | 697 | int iounaccess(vaddr_t, vsize_t); | |
700 | 698 | |||
701 | /* | 699 | /* | |
702 | * The "active" locore-function vector, and | 700 | * The "active" locore-function vector, and | |
703 | */ | 701 | */ | |
704 | extern const mips_locore_atomicvec_t mips_llsc_locore_atomicvec; | 702 | extern const mips_locore_atomicvec_t mips_llsc_locore_atomicvec; | |
705 | 703 | |||
706 | extern mips_locore_atomicvec_t mips_locore_atomicvec; | 704 | extern mips_locore_atomicvec_t mips_locore_atomicvec; | |
707 | extern mips_locore_jumpvec_t mips_locore_jumpvec; | 705 | extern mips_locore_jumpvec_t mips_locore_jumpvec; | |
708 | extern struct locoresw mips_locoresw; | 706 | extern struct locoresw mips_locoresw; | |
709 | 707 | |||
710 | extern int mips_poolpage_vmfreelist; /* freelist to allocate poolpages */ | 708 | extern int mips_poolpage_vmfreelist; /* freelist to allocate poolpages */ | |
711 | extern struct mips_options mips_options; | 709 | extern struct mips_options mips_options; | |
712 | 710 | |||
713 | struct splsw; | 711 | struct splsw; | |
714 | struct mips_vmfreelist; | 712 | struct mips_vmfreelist; | |
715 | struct phys_ram_seg; | 713 | struct phys_ram_seg; | |
716 | 714 | |||
717 | void mips64r2_vector_init(const struct splsw *); | 715 | void mips64r2_vector_init(const struct splsw *); | |
718 | void mips_vector_init(const struct splsw *, bool); | 716 | void mips_vector_init(const struct splsw *, bool); | |
719 | void mips_init_msgbuf(void); | 717 | void mips_init_msgbuf(void); | |
720 | void mips_init_lwp0_uarea(void); | 718 | void mips_init_lwp0_uarea(void); | |
721 | void mips_page_physload(vaddr_t, vaddr_t, | 719 | void mips_page_physload(vaddr_t, vaddr_t, | |
722 | const struct phys_ram_seg *, size_t, | 720 | const struct phys_ram_seg *, size_t, | |
723 | const struct mips_vmfreelist *, size_t); | 721 | const struct mips_vmfreelist *, size_t); | |
724 | 722 | |||
725 | 723 | |||
726 | /* | 724 | /* | |
727 | * CPU identification, from PRID register. | 725 | * CPU identification, from PRID register. | |
728 | */ | 726 | */ | |
729 | #define MIPS_PRID_REV(x) (((x) >> 0) & 0x00ff) | 727 | #define MIPS_PRID_REV(x) (((x) >> 0) & 0x00ff) | |
730 | #define MIPS_PRID_IMPL(x) (((x) >> 8) & 0x00ff) | 728 | #define MIPS_PRID_IMPL(x) (((x) >> 8) & 0x00ff) | |
731 | 729 | |||
732 | /* pre-MIPS32/64 */ | 730 | /* pre-MIPS32/64 */ | |
733 | #define MIPS_PRID_RSVD(x) (((x) >> 16) & 0xffff) | 731 | #define MIPS_PRID_RSVD(x) (((x) >> 16) & 0xffff) | |
734 | #define MIPS_PRID_REV_MIN(x) ((MIPS_PRID_REV(x) >> 0) & 0x0f) | 732 | #define MIPS_PRID_REV_MIN(x) ((MIPS_PRID_REV(x) >> 0) & 0x0f) | |
735 | #define MIPS_PRID_REV_MAJ(x) ((MIPS_PRID_REV(x) >> 4) & 0x0f) | 733 | #define MIPS_PRID_REV_MAJ(x) ((MIPS_PRID_REV(x) >> 4) & 0x0f) | |
736 | 734 | |||
737 | /* MIPS32/64 */ | 735 | /* MIPS32/64 */ | |
738 | #define MIPS_PRID_CID(x) (((x) >> 16) & 0x00ff) /* Company ID */ | 736 | #define MIPS_PRID_CID(x) (((x) >> 16) & 0x00ff) /* Company ID */ | |
739 | #define MIPS_PRID_CID_PREHISTORIC 0x00 /* Not MIPS32/64 */ | 737 | #define MIPS_PRID_CID_PREHISTORIC 0x00 /* Not MIPS32/64 */ | |
740 | #define MIPS_PRID_CID_MTI 0x01 /* MIPS Technologies, Inc. */ | 738 | #define MIPS_PRID_CID_MTI 0x01 /* MIPS Technologies, Inc. */ | |
741 | #define MIPS_PRID_CID_BROADCOM 0x02 /* Broadcom */ | 739 | #define MIPS_PRID_CID_BROADCOM 0x02 /* Broadcom */ | |
742 | #define MIPS_PRID_CID_ALCHEMY 0x03 /* Alchemy Semiconductor */ | 740 | #define MIPS_PRID_CID_ALCHEMY 0x03 /* Alchemy Semiconductor */ | |
743 | #define MIPS_PRID_CID_SIBYTE 0x04 /* SiByte */ | 741 | #define MIPS_PRID_CID_SIBYTE 0x04 /* SiByte */ | |
744 | #define MIPS_PRID_CID_SANDCRAFT 0x05 /* SandCraft */ | 742 | #define MIPS_PRID_CID_SANDCRAFT 0x05 /* SandCraft */ | |
745 | #define MIPS_PRID_CID_PHILIPS 0x06 /* Philips */ | 743 | #define MIPS_PRID_CID_PHILIPS 0x06 /* Philips */ | |
746 | #define MIPS_PRID_CID_TOSHIBA 0x07 /* Toshiba */ | 744 | #define MIPS_PRID_CID_TOSHIBA 0x07 /* Toshiba */ | |
747 | #define MIPS_PRID_CID_MICROSOFT 0x07 /* Microsoft also, sigh */ | 745 | #define MIPS_PRID_CID_MICROSOFT 0x07 /* Microsoft also, sigh */ | |
748 | #define MIPS_PRID_CID_LSI 0x08 /* LSI */ | 746 | #define MIPS_PRID_CID_LSI 0x08 /* LSI */ | |
749 | /* 0x09 unannounced */ | 747 | /* 0x09 unannounced */ | |
750 | /* 0x0a unannounced */ | 748 | /* 0x0a unannounced */ | |
751 | #define MIPS_PRID_CID_LEXRA 0x0b /* Lexra */ | 749 | #define MIPS_PRID_CID_LEXRA 0x0b /* Lexra */ | |
752 | #define MIPS_PRID_CID_RMI 0x0c /* RMI / NetLogic */ | 750 | #define MIPS_PRID_CID_RMI 0x0c /* RMI / NetLogic */ | |
753 | #define MIPS_PRID_CID_CAVIUM 0x0d /* Cavium */ | 751 | #define MIPS_PRID_CID_CAVIUM 0x0d /* Cavium */ | |
754 | #define MIPS_PRID_CID_INGENIC 0xe1 | 752 | #define MIPS_PRID_CID_INGENIC 0xe1 | |
755 | #define MIPS_PRID_COPTS(x) (((x) >> 24) & 0x00ff) /* Company Options */ | 753 | #define MIPS_PRID_COPTS(x) (((x) >> 24) & 0x00ff) /* Company Options */ | |
756 | 754 | |||
757 | /* | 755 | /* | |
758 | * Global variables used to communicate CPU type, and parameters | 756 | * Global variables used to communicate CPU type, and parameters | |
759 | * such as cache size, from locore to higher-level code (e.g., pmap). | 757 | * such as cache size, from locore to higher-level code (e.g., pmap). | |
760 | */ | 758 | */ | |
761 | void mips_pagecopy(register_t dst, register_t src); | 759 | void mips_pagecopy(register_t dst, register_t src); | |
762 | void mips_pagezero(register_t dst); | 760 | void mips_pagezero(register_t dst); | |
763 | 761 | |||
764 | #ifdef __HAVE_MIPS_MACHDEP_CACHE_CONFIG | 762 | #ifdef __HAVE_MIPS_MACHDEP_CACHE_CONFIG | |
765 | void mips_machdep_cache_config(void); | 763 | void mips_machdep_cache_config(void); | |
766 | #endif | 764 | #endif | |
767 | 765 | |||
768 | /* | 766 | /* | |
769 | * trapframe argument passed to trap() | 767 | * trapframe argument passed to trap() | |
770 | */ | 768 | */ | |
771 | 769 | |||
772 | #if 0 | 770 | #if 0 | |
773 | #define TF_AST 0 /* really zero */ | 771 | #define TF_AST 0 /* really zero */ | |
774 | #define TF_V0 _R_V0 | 772 | #define TF_V0 _R_V0 | |
775 | #define TF_V1 _R_V1 | 773 | #define TF_V1 _R_V1 | |
776 | #define TF_A0 _R_A0 | 774 | #define TF_A0 _R_A0 | |
777 | #define TF_A1 _R_A1 | 775 | #define TF_A1 _R_A1 | |
778 | #define TF_A2 _R_A2 | 776 | #define TF_A2 _R_A2 | |
779 | #define TF_A3 _R_A3 | 777 | #define TF_A3 _R_A3 | |
780 | #define TF_T0 _R_T0 | 778 | #define TF_T0 _R_T0 | |
781 | #define TF_T1 _R_T1 | 779 | #define TF_T1 _R_T1 | |
782 | #define TF_T2 _R_T2 | 780 | #define TF_T2 _R_T2 | |
783 | #define TF_T3 _R_T3 | 781 | #define TF_T3 _R_T3 | |
784 | 782 | |||
785 | #if defined(__mips_n32) || defined(__mips_n64) | 783 | #if defined(__mips_n32) || defined(__mips_n64) | |
786 | #define TF_A4 _R_A4 | 784 | #define TF_A4 _R_A4 | |
787 | #define TF_A5 _R_A5 | 785 | #define TF_A5 _R_A5 | |
788 | #define TF_A6 _R_A6 | 786 | #define TF_A6 _R_A6 | |
789 | #define TF_A7 _R_A7 | 787 | #define TF_A7 _R_A7 | |
790 | #else | 788 | #else | |
791 | #define TF_T4 _R_T4 | 789 | #define TF_T4 _R_T4 | |
792 | #define TF_T5 _R_T5 | 790 | #define TF_T5 _R_T5 | |
793 | #define TF_T6 _R_T6 | 791 | #define TF_T6 _R_T6 | |
794 | #define TF_T7 _R_T7 | 792 | #define TF_T7 _R_T7 | |
795 | #endif /* __mips_n32 || __mips_n64 */ | 793 | #endif /* __mips_n32 || __mips_n64 */ | |
796 | 794 | |||
797 | #define TF_TA0 _R_TA0 | 795 | #define TF_TA0 _R_TA0 | |
798 | #define TF_TA1 _R_TA1 | 796 | #define TF_TA1 _R_TA1 | |
799 | #define TF_TA2 _R_TA2 | 797 | #define TF_TA2 _R_TA2 | |
800 | #define TF_TA3 _R_TA3 | 798 | #define TF_TA3 _R_TA3 | |
801 | 799 | |||
802 | #define TF_T8 _R_T8 | 800 | #define TF_T8 _R_T8 | |
803 | #define TF_T9 _R_T9 | 801 | #define TF_T9 _R_T9 | |
804 | 802 | |||
805 | #define TF_RA _R_RA | 803 | #define TF_RA _R_RA | |
806 | #define TF_SR _R_SR | 804 | #define TF_SR _R_SR | |
807 | #define TF_MULLO _R_MULLO | 805 | #define TF_MULLO _R_MULLO | |
808 | #define TF_MULHI _R_MULHI | 806 | #define TF_MULHI _R_MULHI | |
809 | #define TF_EPC _R_PC /* may be changed by trap() call */ | 807 | #define TF_EPC _R_PC /* may be changed by trap() call */ | |
810 | 808 | |||
811 | #define TF_NREGS (sizeof(struct reg) / sizeof(mips_reg_t)) | 809 | #define TF_NREGS (sizeof(struct reg) / sizeof(mips_reg_t)) | |
812 | #endif | 810 | #endif | |
813 | 811 | |||
814 | struct trapframe { | 812 | struct trapframe { | |
815 | struct reg tf_registers; | 813 | struct reg tf_registers; | |
816 | #define tf_regs tf_registers.r_regs | 814 | #define tf_regs tf_registers.r_regs | |
817 | uint32_t tf_ppl; /* previous priority level */ | 815 | uint32_t tf_ppl; /* previous priority level */ | |
818 | mips_reg_t tf_pad; /* for 8 byte aligned */ | 816 | mips_reg_t tf_pad; /* for 8 byte aligned */ | |
819 | }; | 817 | }; | |
820 | 818 | |||
821 | CTASSERT(sizeof(struct trapframe) % (4*sizeof(mips_reg_t)) == 0); | 819 | CTASSERT(sizeof(struct trapframe) % (4*sizeof(mips_reg_t)) == 0); | |
822 | 820 | |||
823 | /* | 821 | /* | |
824 | * Stack frame for kernel traps. four args passed in registers. | 822 | * Stack frame for kernel traps. four args passed in registers. | |
825 | * A trapframe is pointed to by the 5th arg, and a dummy sixth argument | 823 | * A trapframe is pointed to by the 5th arg, and a dummy sixth argument | |
826 | * is used to avoid alignment problems | 824 | * is used to avoid alignment problems | |
827 | */ | 825 | */ | |
828 | 826 | |||
829 | struct kernframe { | 827 | struct kernframe { | |
830 | #if defined(__mips_o32) || defined(__mips_o64) | 828 | #if defined(__mips_o32) || defined(__mips_o64) | |
831 | register_t cf_args[4 + 1]; | 829 | register_t cf_args[4 + 1]; | |
832 | #if defined(__mips_o32) | 830 | #if defined(__mips_o32) | |
833 | register_t cf_pad; /* (for 8 byte alignment) */ | 831 | register_t cf_pad; /* (for 8 byte alignment) */ | |
834 | #endif | 832 | #endif | |
835 | #endif | 833 | #endif | |
836 | #if defined(__mips_n32) || defined(__mips_n64) | 834 | #if defined(__mips_n32) || defined(__mips_n64) | |
837 | register_t cf_pad[2]; /* for 16 byte alignment */ | 835 | register_t cf_pad[2]; /* for 16 byte alignment */ | |
838 | #endif | 836 | #endif | |
839 | register_t cf_sp; | 837 | register_t cf_sp; | |
840 | register_t cf_ra; | 838 | register_t cf_ra; | |
841 | struct trapframe cf_frame; | 839 | struct trapframe cf_frame; | |
842 | }; | 840 | }; | |
843 | 841 | |||
844 | CTASSERT(sizeof(struct kernframe) % (2*sizeof(mips_reg_t)) == 0); | 842 | CTASSERT(sizeof(struct kernframe) % (2*sizeof(mips_reg_t)) == 0); | |
845 | 843 | |||
846 | /* | 844 | /* | |
847 | * PRocessor IDentity TABle | 845 | * PRocessor IDentity TABle | |
848 | */ | 846 | */ | |
849 | 847 | |||
850 | struct pridtab { | 848 | struct pridtab { | |
851 | int cpu_cid; | 849 | int cpu_cid; | |
852 | int cpu_pid; | 850 | int cpu_pid; | |
853 | int cpu_rev; /* -1 == wildcard */ | 851 | int cpu_rev; /* -1 == wildcard */ | |
854 | int cpu_copts; /* -1 == wildcard */ | 852 | int cpu_copts; /* -1 == wildcard */ | |
855 | int cpu_isa; /* -1 == probed (mips32/mips64) */ | 853 | int cpu_isa; /* -1 == probed (mips32/mips64) */ | |
856 | int cpu_ntlb; /* -1 == unknown, 0 == probed */ | 854 | int cpu_ntlb; /* -1 == unknown, 0 == probed */ | |
857 | int cpu_flags; | 855 | int cpu_flags; | |
858 | u_int cpu_cp0flags; /* presence of some cp0 regs */ | 856 | u_int cpu_cp0flags; /* presence of some cp0 regs */ | |
859 | u_int cpu_cidflags; /* company-specific flags */ | 857 | u_int cpu_cidflags; /* company-specific flags */ | |
860 | const char *cpu_name; | 858 | const char *cpu_name; | |
861 | }; | 859 | }; | |
862 | 860 | |||
863 | /* | 861 | /* | |
864 | * bitfield defines for cpu_cp0flags | 862 | * bitfield defines for cpu_cp0flags | |
865 | */ | 863 | */ | |
866 | #define MIPS_CP0FL_USE __BIT(0) /* use these flags */ | 864 | #define MIPS_CP0FL_USE __BIT(0) /* use these flags */ | |
867 | #define MIPS_CP0FL_ECC __BIT(1) | 865 | #define MIPS_CP0FL_ECC __BIT(1) | |
868 | #define MIPS_CP0FL_CACHE_ERR __BIT(2) | 866 | #define MIPS_CP0FL_CACHE_ERR __BIT(2) | |
869 | #define MIPS_CP0FL_EIRR __BIT(3) | 867 | #define MIPS_CP0FL_EIRR __BIT(3) | |
870 | #define MIPS_CP0FL_EIMR __BIT(4) | 868 | #define MIPS_CP0FL_EIMR __BIT(4) | |
871 | #define MIPS_CP0FL_EBASE __BIT(5) /* XXX probeable - shouldn't be hard coded */ | 869 | #define MIPS_CP0FL_EBASE __BIT(5) /* XXX probeable - shouldn't be hard coded */ | |
872 | #define MIPS_CP0FL_CONFIG __BIT(6) /* XXX defined - doesn't need to be hard coded */ | 870 | #define MIPS_CP0FL_CONFIG __BIT(6) /* XXX defined - doesn't need to be hard coded */ | |
873 | #define MIPS_CP0FL_CONFIG1 __BIT(7) /* XXX probeable - shouldn't be hard coded */ | 871 | #define MIPS_CP0FL_CONFIG1 __BIT(7) /* XXX probeable - shouldn't be hard coded */ | |
874 | #define MIPS_CP0FL_CONFIG2 __BIT(8) /* XXX probeable - shouldn't be hard coded */ | 872 | #define MIPS_CP0FL_CONFIG2 __BIT(8) /* XXX probeable - shouldn't be hard coded */ | |
875 | #define MIPS_CP0FL_CONFIG3 __BIT(9) /* XXX probeable - shouldn't be hard coded */ | 873 | #define MIPS_CP0FL_CONFIG3 __BIT(9) /* XXX probeable - shouldn't be hard coded */ | |
876 | #define MIPS_CP0FL_CONFIG4 __BIT(10) /* XXX probeable - shouldn't be hard coded */ | 874 | #define MIPS_CP0FL_CONFIG4 __BIT(10) /* XXX probeable - shouldn't be hard coded */ | |
877 | #define MIPS_CP0FL_CONFIG5 __BIT(11) /* XXX probeable - shouldn't be hard coded */ | 875 | #define MIPS_CP0FL_CONFIG5 __BIT(11) /* XXX probeable - shouldn't be hard coded */ | |
878 | #define MIPS_CP0FL_CONFIG6 __BIT(12) | 876 | #define MIPS_CP0FL_CONFIG6 __BIT(12) | |
879 | #define MIPS_CP0FL_CONFIG7 __BIT(13) | 877 | #define MIPS_CP0FL_CONFIG7 __BIT(13) | |
880 | 878 | |||
881 | /* | 879 | /* | |
882 | * cpu_cidflags defines, by company | 880 | * cpu_cidflags defines, by company | |
883 | */ | 881 | */ | |
884 | /* | 882 | /* | |
885 | * RMI company-specific cpu_cidflags | 883 | * RMI company-specific cpu_cidflags | |
886 | */ | 884 | */ | |
887 | #define MIPS_CIDFL_RMI_TYPE __BITS(2,0) | 885 | #define MIPS_CIDFL_RMI_TYPE __BITS(2,0) | |
888 | # define CIDFL_RMI_TYPE_XLR 0 | 886 | # define CIDFL_RMI_TYPE_XLR 0 | |
889 | # define CIDFL_RMI_TYPE_XLS 1 | 887 | # define CIDFL_RMI_TYPE_XLS 1 | |
890 | # define CIDFL_RMI_TYPE_XLP 2 | 888 | # define CIDFL_RMI_TYPE_XLP 2 | |
891 | #define MIPS_CIDFL_RMI_THREADS_MASK __BITS(6,3) | 889 | #define MIPS_CIDFL_RMI_THREADS_MASK __BITS(6,3) | |
892 | # define MIPS_CIDFL_RMI_THREADS_SHIFT 3 | 890 | # define MIPS_CIDFL_RMI_THREADS_SHIFT 3 | |
893 | #define MIPS_CIDFL_RMI_CORES_MASK __BITS(10,7) | 891 | #define MIPS_CIDFL_RMI_CORES_MASK __BITS(10,7) | |
894 | # define MIPS_CIDFL_RMI_CORES_SHIFT 7 | 892 | # define MIPS_CIDFL_RMI_CORES_SHIFT 7 | |
895 | # define LOG2_1 0 | 893 | # define LOG2_1 0 | |
896 | # define LOG2_2 1 | 894 | # define LOG2_2 1 | |
897 | # define LOG2_4 2 | 895 | # define LOG2_4 2 | |
898 | # define LOG2_8 3 | 896 | # define LOG2_8 3 | |
899 | # define MIPS_CIDFL_RMI_CPUS(ncores, nthreads) \ | 897 | # define MIPS_CIDFL_RMI_CPUS(ncores, nthreads) \ | |
900 | ((LOG2_ ## ncores << MIPS_CIDFL_RMI_CORES_SHIFT) \ | 898 | ((LOG2_ ## ncores << MIPS_CIDFL_RMI_CORES_SHIFT) \ | |
901 | |(LOG2_ ## nthreads << MIPS_CIDFL_RMI_THREADS_SHIFT)) | 899 | |(LOG2_ ## nthreads << MIPS_CIDFL_RMI_THREADS_SHIFT)) | |
902 | # define MIPS_CIDFL_RMI_NTHREADS(cidfl) \ | 900 | # define MIPS_CIDFL_RMI_NTHREADS(cidfl) \ | |
903 | (1 << (((cidfl) & MIPS_CIDFL_RMI_THREADS_MASK) \ | 901 | (1 << (((cidfl) & MIPS_CIDFL_RMI_THREADS_MASK) \ | |
904 | >> MIPS_CIDFL_RMI_THREADS_SHIFT)) | 902 | >> MIPS_CIDFL_RMI_THREADS_SHIFT)) | |
905 | # define MIPS_CIDFL_RMI_NCORES(cidfl) \ | 903 | # define MIPS_CIDFL_RMI_NCORES(cidfl) \ | |
906 | (1 << (((cidfl) & MIPS_CIDFL_RMI_CORES_MASK) \ | 904 | (1 << (((cidfl) & MIPS_CIDFL_RMI_CORES_MASK) \ | |
907 | >> MIPS_CIDFL_RMI_CORES_SHIFT)) | 905 | >> MIPS_CIDFL_RMI_CORES_SHIFT)) | |
908 | #define MIPS_CIDFL_RMI_L2SZ_MASK __BITS(14,11) | 906 | #define MIPS_CIDFL_RMI_L2SZ_MASK __BITS(14,11) | |
909 | # define MIPS_CIDFL_RMI_L2SZ_SHIFT 11 | 907 | # define MIPS_CIDFL_RMI_L2SZ_SHIFT 11 | |
910 | # define RMI_L2SZ_256KB 0 | 908 | # define RMI_L2SZ_256KB 0 | |
911 | # define RMI_L2SZ_512KB 1 | 909 | # define RMI_L2SZ_512KB 1 | |
912 | # define RMI_L2SZ_1MB 2 | 910 | # define RMI_L2SZ_1MB 2 | |
913 | # define RMI_L2SZ_2MB 3 | 911 | # define RMI_L2SZ_2MB 3 | |
914 | # define RMI_L2SZ_4MB 4 | 912 | # define RMI_L2SZ_4MB 4 | |
915 | # define MIPS_CIDFL_RMI_L2(l2sz) \ | 913 | # define MIPS_CIDFL_RMI_L2(l2sz) \ | |
916 | (RMI_L2SZ_ ## l2sz << MIPS_CIDFL_RMI_L2SZ_SHIFT) | 914 | (RMI_L2SZ_ ## l2sz << MIPS_CIDFL_RMI_L2SZ_SHIFT) | |
917 | # define MIPS_CIDFL_RMI_L2SZ(cidfl) \ | 915 | # define MIPS_CIDFL_RMI_L2SZ(cidfl) \ | |
918 | ((256*1024) << (((cidfl) & MIPS_CIDFL_RMI_L2SZ_MASK) \ | 916 | ((256*1024) << (((cidfl) & MIPS_CIDFL_RMI_L2SZ_MASK) \ | |
919 | >> MIPS_CIDFL_RMI_L2SZ_SHIFT)) | 917 | >> MIPS_CIDFL_RMI_L2SZ_SHIFT)) | |
920 | #endif /* _KERNEL */ | 918 | #endif /* _KERNEL */ | |
921 | #endif /* !__ASSEMBLER__ */ | 919 | #endif /* !__ASSEMBLER__ */ | |
922 | 920 | |||
923 | #endif /* _MIPS_LOCORE_H */ | 921 | #endif /* _MIPS_LOCORE_H */ |
--- src/sys/arch/mips/mips/mips_emul.c 2021/05/27 13:32:54 1.28
+++ src/sys/arch/mips/mips/mips_emul.c 2021/05/27 15:00:02 1.29
@@ -1,1221 +1,1224 @@ | @@ -1,1221 +1,1224 @@ | |||
1 | /* $NetBSD: mips_emul.c,v 1.28 2021/05/27 13:32:54 simonb Exp $ */ | 1 | /* $NetBSD: mips_emul.c,v 1.29 2021/05/27 15:00:02 simonb Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1999 Shuichiro URATA. All rights reserved. | 4 | * Copyright (c) 1999 Shuichiro URATA. All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. The name of the author may not be used to endorse or promote products | 14 | * 3. The name of the author may not be used to endorse or promote products | |
15 | * derived from this software without specific prior written permission. | 15 | * derived from this software without specific prior written permission. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.28 2021/05/27 13:32:54 simonb Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.29 2021/05/27 15:00:02 simonb Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/systm.h> | 33 | #include <sys/systm.h> | |
34 | #include <sys/cpu.h> | 34 | #include <sys/cpu.h> | |
35 | #include <sys/proc.h> | 35 | #include <sys/proc.h> | |
36 | 36 | |||
37 | #include <mips/locore.h> | 37 | #include <mips/locore.h> | |
38 | #include <mips/mips_opcode.h> | 38 | #include <mips/mips_opcode.h> | |
39 | 39 | |||
40 | #include <mips/reg.h> | 40 | #include <mips/reg.h> | |
41 | #include <mips/regnum.h> /* symbolic register indices */ | 41 | #include <mips/regnum.h> /* symbolic register indices */ | |
42 | #include <mips/pcb.h> | 42 | #include <mips/pcb.h> | |
43 | #include <mips/vmparam.h> /* for VM_MAX_ADDRESS */ | 43 | #include <mips/vmparam.h> /* for VM_MAX_ADDRESS */ | |
44 | #include <mips/trap.h> | 44 | #include <mips/trap.h> | |
45 | 45 | |||
46 | static inline void send_sigsegv(intptr_t, uint32_t, struct trapframe *, | 46 | static inline void send_sigsegv(intptr_t, uint32_t, struct trapframe *, | |
47 | uint32_t); | 47 | uint32_t); | |
48 | static inline void update_pc(struct trapframe *, uint32_t); | 48 | static inline void update_pc(struct trapframe *, uint32_t); | |
49 | 49 | |||
50 | static void mips_emul_ll(uint32_t, struct trapframe *, uint32_t); | |||
51 | static void mips_emul_sc(uint32_t, struct trapframe *, uint32_t); | |||
52 | ||||
50 | /* | 53 | /* | |
51 | * MIPS2 LL instruction emulation state | 54 | * MIPS2 LL instruction emulation state | |
52 | */ | 55 | */ | |
53 | struct { | 56 | struct { | |
54 | struct lwp *lwp; | 57 | struct lwp *lwp; | |
55 | vaddr_t addr; | 58 | vaddr_t addr; | |
56 | uint32_t value; | 59 | uint32_t value; | |
57 | } llstate; | 60 | } llstate; | |
58 | 61 | |||
59 | /* | 62 | /* | |
60 | * Analyse 'next' PC address taking account of branch/jump instructions | 63 | * Analyse 'next' PC address taking account of branch/jump instructions | |
61 | */ | 64 | */ | |
62 | vaddr_t | 65 | vaddr_t | |
63 | mips_emul_branch(struct trapframe *tf, vaddr_t instpc, uint32_t fpuCSR, | 66 | mips_emul_branch(struct trapframe *tf, vaddr_t instpc, uint32_t fpuCSR, | |
64 | bool allowNonBranch) | 67 | bool allowNonBranch) | |
65 | { | 68 | { | |
66 | #define BRANCHTARGET(pc, i) (4 + (pc) + ((short)(i).IType.imm << 2)) | 69 | #define BRANCHTARGET(pc, i) (4 + (pc) + ((short)(i).IType.imm << 2)) | |
67 | InstFmt inst; | 70 | InstFmt inst; | |
68 | vaddr_t nextpc; | 71 | vaddr_t nextpc; | |
69 | 72 | |||
70 | if (instpc < MIPS_KSEG0_START) { | 73 | if (instpc < MIPS_KSEG0_START) { | |
71 | inst.word = mips_ufetch32((void *)instpc); | 74 | inst.word = mips_ufetch32((void *)instpc); | |
72 | } else { | 75 | } else { | |
73 | inst.word = *(uint32_t *)instpc; | 76 | inst.word = *(uint32_t *)instpc; | |
74 | } | 77 | } | |
75 | 78 | |||
76 | switch ((int)inst.JType.op) { | 79 | switch ((int)inst.JType.op) { | |
77 | case OP_SPECIAL: | 80 | case OP_SPECIAL: | |
78 | if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR) | 81 | if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR) | |
79 | nextpc = tf->tf_regs[inst.RType.rs]; | 82 | nextpc = tf->tf_regs[inst.RType.rs]; | |
80 | else if (allowNonBranch) | 83 | else if (allowNonBranch) | |
81 | nextpc = instpc + 4; | 84 | nextpc = instpc + 4; | |
82 | else | 85 | else | |
83 | panic("%s: %s instruction %08x at pc 0x%"PRIxVADDR, | 86 | panic("%s: %s instruction %08x at pc 0x%"PRIxVADDR, | |
84 | __func__, "non-branch", inst.word, instpc); | 87 | __func__, "non-branch", inst.word, instpc); | |
85 | break; | 88 | break; | |
86 | 89 | |||
87 | case OP_REGIMM: | 90 | case OP_REGIMM: | |
88 | switch ((int)inst.IType.rt) { | 91 | switch ((int)inst.IType.rt) { | |
89 | case OP_BLTZ: | 92 | case OP_BLTZ: | |
90 | case OP_BLTZAL: | 93 | case OP_BLTZAL: | |
91 | case OP_BLTZL: /* squashed */ | 94 | case OP_BLTZL: /* squashed */ | |
92 | case OP_BLTZALL: /* squashed */ | 95 | case OP_BLTZALL: /* squashed */ | |
93 | if ((int)(tf->tf_regs[inst.RType.rs]) < 0) | 96 | if ((int)(tf->tf_regs[inst.RType.rs]) < 0) | |
94 | nextpc = BRANCHTARGET(instpc, inst); | 97 | nextpc = BRANCHTARGET(instpc, inst); | |
95 | else | 98 | else | |
96 | nextpc = instpc + 8; | 99 | nextpc = instpc + 8; | |
97 | break; | 100 | break; | |
98 | 101 | |||
99 | case OP_BGEZ: | 102 | case OP_BGEZ: | |
100 | case OP_BGEZAL: | 103 | case OP_BGEZAL: | |
101 | case OP_BGEZL: /* squashed */ | 104 | case OP_BGEZL: /* squashed */ | |
102 | case OP_BGEZALL: /* squashed */ | 105 | case OP_BGEZALL: /* squashed */ | |
103 | if ((int)(tf->tf_regs[inst.RType.rs]) >= 0) | 106 | if ((int)(tf->tf_regs[inst.RType.rs]) >= 0) | |
104 | nextpc = BRANCHTARGET(instpc, inst); | 107 | nextpc = BRANCHTARGET(instpc, inst); | |
105 | else | 108 | else | |
106 | nextpc = instpc + 8; | 109 | nextpc = instpc + 8; | |
107 | break; | 110 | break; | |
108 | 111 | |||
109 | default: | 112 | default: | |
110 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | 113 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | |
111 | __func__, "bad branch", inst.word, instpc); | 114 | __func__, "bad branch", inst.word, instpc); | |
112 | } | 115 | } | |
113 | break; | 116 | break; | |
114 | 117 | |||
115 | case OP_J: | 118 | case OP_J: | |
116 | case OP_JAL: | 119 | case OP_JAL: | |
117 | nextpc = (inst.JType.target << 2) | | 120 | nextpc = (inst.JType.target << 2) | | |
118 | ((intptr_t)instpc & 0xF0000000); | 121 | ((intptr_t)instpc & 0xF0000000); | |
119 | break; | 122 | break; | |
120 | 123 | |||
121 | case OP_BEQ: | 124 | case OP_BEQ: | |
122 | case OP_BEQL: /* squashed */ | 125 | case OP_BEQL: /* squashed */ | |
123 | if (tf->tf_regs[inst.RType.rs] == tf->tf_regs[inst.RType.rt]) | 126 | if (tf->tf_regs[inst.RType.rs] == tf->tf_regs[inst.RType.rt]) | |
124 | nextpc = BRANCHTARGET(instpc, inst); | 127 | nextpc = BRANCHTARGET(instpc, inst); | |
125 | else | 128 | else | |
126 | nextpc = instpc + 8; | 129 | nextpc = instpc + 8; | |
127 | break; | 130 | break; | |
128 | 131 | |||
129 | case OP_BNE: | 132 | case OP_BNE: | |
130 | case OP_BNEL: /* squashed */ | 133 | case OP_BNEL: /* squashed */ | |
131 | if (tf->tf_regs[inst.RType.rs] != tf->tf_regs[inst.RType.rt]) | 134 | if (tf->tf_regs[inst.RType.rs] != tf->tf_regs[inst.RType.rt]) | |
132 | nextpc = BRANCHTARGET(instpc, inst); | 135 | nextpc = BRANCHTARGET(instpc, inst); | |
133 | else | 136 | else | |
134 | nextpc = instpc + 8; | 137 | nextpc = instpc + 8; | |
135 | break; | 138 | break; | |
136 | 139 | |||
137 | case OP_BLEZ: | 140 | case OP_BLEZ: | |
138 | case OP_BLEZL: /* squashed */ | 141 | case OP_BLEZL: /* squashed */ | |
139 | if ((int)(tf->tf_regs[inst.RType.rs]) <= 0) | 142 | if ((int)(tf->tf_regs[inst.RType.rs]) <= 0) | |
140 | nextpc = BRANCHTARGET(instpc, inst); | 143 | nextpc = BRANCHTARGET(instpc, inst); | |
141 | else | 144 | else | |
142 | nextpc = instpc + 8; | 145 | nextpc = instpc + 8; | |
143 | break; | 146 | break; | |
144 | 147 | |||
145 | case OP_BGTZ: | 148 | case OP_BGTZ: | |
146 | case OP_BGTZL: /* squashed */ | 149 | case OP_BGTZL: /* squashed */ | |
147 | if ((int)(tf->tf_regs[inst.RType.rs]) > 0) | 150 | if ((int)(tf->tf_regs[inst.RType.rs]) > 0) | |
148 | nextpc = BRANCHTARGET(instpc, inst); | 151 | nextpc = BRANCHTARGET(instpc, inst); | |
149 | else | 152 | else | |
150 | nextpc = instpc + 8; | 153 | nextpc = instpc + 8; | |
151 | break; | 154 | break; | |
152 | 155 | |||
153 | case OP_COP1: | 156 | case OP_COP1: | |
154 | if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) { | 157 | if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) { | |
155 | int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0; | 158 | int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0; | |
156 | if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE) | 159 | if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE) | |
157 | condition = !condition; | 160 | condition = !condition; | |
158 | if (condition) | 161 | if (condition) | |
159 | nextpc = BRANCHTARGET(instpc, inst); | 162 | nextpc = BRANCHTARGET(instpc, inst); | |
160 | else | 163 | else | |
161 | nextpc = instpc + 8; | 164 | nextpc = instpc + 8; | |
162 | } | 165 | } | |
163 | else if (allowNonBranch) | 166 | else if (allowNonBranch) | |
164 | nextpc = instpc + 4; | 167 | nextpc = instpc + 4; | |
165 | else | 168 | else | |
166 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | 169 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | |
167 | __func__, "bad COP1 branch", inst.word, instpc); | 170 | __func__, "bad COP1 branch", inst.word, instpc); | |
168 | break; | 171 | break; | |
169 | 172 | |||
170 | default: | 173 | default: | |
171 | if (!allowNonBranch) | 174 | if (!allowNonBranch) | |
172 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | 175 | panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, | |
173 | __func__, "non-branch", inst.word, instpc); | 176 | __func__, "non-branch", inst.word, instpc); | |
174 | nextpc = instpc + 4; | 177 | nextpc = instpc + 4; | |
175 | } | 178 | } | |
176 | KASSERT((nextpc & 0x3) == 0); | 179 | KASSERT((nextpc & 0x3) == 0); | |
177 | return nextpc; | 180 | return nextpc; | |
178 | #undef BRANCHTARGET | 181 | #undef BRANCHTARGET | |
179 | } | 182 | } | |
180 | 183 | |||
181 | /* | 184 | /* | |
182 | * Emulate instructions (including floating-point instructions) | 185 | * Emulate instructions (including floating-point instructions) | |
183 | */ | 186 | */ | |
184 | void | 187 | void | |
185 | mips_emul_inst(uint32_t status, uint32_t cause, vaddr_t opc, | 188 | mips_emul_inst(uint32_t status, uint32_t cause, vaddr_t opc, | |
186 | struct trapframe *tf) | 189 | struct trapframe *tf) | |
187 | { | 190 | { | |
188 | uint32_t inst; | 191 | uint32_t inst; | |
189 | ksiginfo_t ksi; | 192 | ksiginfo_t ksi; | |
190 | int code = ILL_ILLOPC; | 193 | int code = ILL_ILLOPC; | |
191 | 194 | |||
192 | /* | 195 | /* | |
193 | * Fetch the instruction. | 196 | * Fetch the instruction. | |
194 | */ | 197 | */ | |
195 | if (cause & MIPS_CR_BR_DELAY) | 198 | if (cause & MIPS_CR_BR_DELAY) | |
196 | inst = mips_ufetch32((uint32_t *)opc+1); | 199 | inst = mips_ufetch32((uint32_t *)opc+1); | |
197 | else | 200 | else | |
198 | inst = mips_ufetch32((uint32_t *)opc); | 201 | inst = mips_ufetch32((uint32_t *)opc); | |
199 | 202 | |||
200 | switch (((InstFmt)inst).FRType.op) { | 203 | switch (((InstFmt)inst).FRType.op) { | |
201 | case OP_LWC0: | 204 | case OP_LL: | |
202 | mips_emul_lwc0(inst, tf, cause); | 205 | mips_emul_ll(inst, tf, cause); | |
203 | break; | 206 | break; | |
204 | case OP_SWC0: | 207 | case OP_SC: | |
205 | mips_emul_swc0(inst, tf, cause); | 208 | mips_emul_sc(inst, tf, cause); | |
206 | break; | 209 | break; | |
207 | case OP_SPECIAL: | 210 | case OP_SPECIAL: | |
208 | mips_emul_special(inst, tf, cause); | 211 | mips_emul_special(inst, tf, cause); | |
209 | break; | 212 | break; | |
210 | case OP_SPECIAL3: | 213 | case OP_SPECIAL3: | |
211 | mips_emul_special3(inst, tf, cause); | 214 | mips_emul_special3(inst, tf, cause); | |
212 | break; | 215 | break; | |
213 | case OP_COP1: | 216 | case OP_COP1: | |
214 | #if defined(FPEMUL) | 217 | #if defined(FPEMUL) | |
215 | mips_emul_fp(inst, tf, cause); | 218 | mips_emul_fp(inst, tf, cause); | |
216 | break; | 219 | break; | |
217 | #endif | 220 | #endif | |
218 | case OP_LWC1: | 221 | case OP_LWC1: | |
219 | #if defined(FPEMUL) | 222 | #if defined(FPEMUL) | |
220 | mips_emul_lwc1(inst, tf, cause); | 223 | mips_emul_lwc1(inst, tf, cause); | |
221 | break; | 224 | break; | |
222 | #endif | 225 | #endif | |
223 | case OP_LDC1: | 226 | case OP_LDC1: | |
224 | #if defined(FPEMUL) | 227 | #if defined(FPEMUL) | |
225 | mips_emul_ldc1(inst, tf, cause); | 228 | mips_emul_ldc1(inst, tf, cause); | |
226 | break; | 229 | break; | |
227 | #endif | 230 | #endif | |
228 | case OP_SWC1: | 231 | case OP_SWC1: | |
229 | #if defined(FPEMUL) | 232 | #if defined(FPEMUL) | |
230 | mips_emul_swc1(inst, tf, cause); | 233 | mips_emul_swc1(inst, tf, cause); | |
231 | break; | 234 | break; | |
232 | #endif | 235 | #endif | |
233 | case OP_SDC1: | 236 | case OP_SDC1: | |
234 | #if defined(FPEMUL) | 237 | #if defined(FPEMUL) | |
235 | mips_emul_sdc1(inst, tf, cause); | 238 | mips_emul_sdc1(inst, tf, cause); | |
236 | break; | 239 | break; | |
237 | #else | 240 | #else | |
238 | code = ILL_COPROC; | 241 | code = ILL_COPROC; | |
239 | /* FALLTHROUGH */ | 242 | /* FALLTHROUGH */ | |
240 | #endif | 243 | #endif | |
241 | default: | 244 | default: | |
242 | #ifdef DEBUG | 245 | #ifdef DEBUG | |
243 | printf("pid %d (%s): trap: bad insn @ %#"PRIxVADDR | 246 | printf("pid %d (%s): trap: bad insn @ %#"PRIxVADDR | |
244 | " cause %#x status %#"PRIxREGISTER" insn %#x code %d\n", | 247 | " cause %#x status %#"PRIxREGISTER" insn %#x code %d\n", | |
245 | curproc->p_pid, curproc->p_comm, opc, | 248 | curproc->p_pid, curproc->p_comm, opc, | |
246 | cause, tf->tf_regs[_R_SR], inst, code); | 249 | cause, tf->tf_regs[_R_SR], inst, code); | |
247 | #endif | 250 | #endif | |
248 | tf->tf_regs[_R_CAUSE] = cause; | 251 | tf->tf_regs[_R_CAUSE] = cause; | |
249 | tf->tf_regs[_R_BADVADDR] = opc; | 252 | tf->tf_regs[_R_BADVADDR] = opc; | |
250 | KSI_INIT_TRAP(&ksi); | 253 | KSI_INIT_TRAP(&ksi); | |
251 | ksi.ksi_signo = SIGILL; | 254 | ksi.ksi_signo = SIGILL; | |
252 | ksi.ksi_trap = cause; /* XXX */ | 255 | ksi.ksi_trap = cause; /* XXX */ | |
253 | ksi.ksi_code = code; | 256 | ksi.ksi_code = code; | |
254 | ksi.ksi_addr = (void *)opc; | 257 | ksi.ksi_addr = (void *)opc; | |
255 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | 258 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | |
256 | break; | 259 | break; | |
257 | } | 260 | } | |
258 | } | 261 | } | |
259 | 262 | |||
260 | static inline void | 263 | static inline void | |
261 | send_sigsegv(intptr_t vaddr, uint32_t exccode, struct trapframe *tf, | 264 | send_sigsegv(intptr_t vaddr, uint32_t exccode, struct trapframe *tf, | |
262 | uint32_t cause) | 265 | uint32_t cause) | |
263 | { | 266 | { | |
264 | ksiginfo_t ksi; | 267 | ksiginfo_t ksi; | |
265 | cause = (cause & ~0xFF) | (exccode << MIPS_CR_EXC_CODE_SHIFT); | 268 | cause = (cause & ~0xFF) | (exccode << MIPS_CR_EXC_CODE_SHIFT); | |
266 | tf->tf_regs[_R_CAUSE] = cause; | 269 | tf->tf_regs[_R_CAUSE] = cause; | |
267 | tf->tf_regs[_R_BADVADDR] = vaddr; | 270 | tf->tf_regs[_R_BADVADDR] = vaddr; | |
268 | KSI_INIT_TRAP(&ksi); | 271 | KSI_INIT_TRAP(&ksi); | |
269 | ksi.ksi_signo = SIGSEGV; | 272 | ksi.ksi_signo = SIGSEGV; | |
270 | ksi.ksi_trap = cause; | 273 | ksi.ksi_trap = cause; | |
271 | ksi.ksi_code = SEGV_MAPERR; | 274 | ksi.ksi_code = SEGV_MAPERR; | |
272 | ksi.ksi_addr = (void *)vaddr; | 275 | ksi.ksi_addr = (void *)vaddr; | |
273 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | 276 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | |
274 | } | 277 | } | |
275 | 278 | |||
276 | static inline void | 279 | static inline void | |
277 | update_pc(struct trapframe *tf, uint32_t cause) | 280 | update_pc(struct trapframe *tf, uint32_t cause) | |
278 | { | 281 | { | |
279 | 282 | |||
280 | if (cause & MIPS_CR_BR_DELAY) | 283 | if (cause & MIPS_CR_BR_DELAY) | |
281 | tf->tf_regs[_R_PC] = | 284 | tf->tf_regs[_R_PC] = | |
282 | mips_emul_branch(tf, tf->tf_regs[_R_PC], | 285 | mips_emul_branch(tf, tf->tf_regs[_R_PC], | |
283 | PCB_FSR(curpcb), 0); | 286 | PCB_FSR(curpcb), 0); | |
284 | else | 287 | else | |
285 | tf->tf_regs[_R_PC] += 4; | 288 | tf->tf_regs[_R_PC] += 4; | |
286 | } | 289 | } | |
287 | 290 | |||
288 | /* | 291 | /* | |
289 | * MIPS2 LL instruction | 292 | * MIPS2 LL instruction | |
290 | */ | 293 | */ | |
291 | void | 294 | void | |
292 | mips_emul_lwc0(uint32_t inst, struct trapframe *tf, uint32_t cause) | 295 | mips_emul_ll(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
293 | { | 296 | { | |
294 | intptr_t vaddr; | 297 | intptr_t vaddr; | |
295 | int16_t offset; | 298 | int16_t offset; | |
296 | void *t; | 299 | void *t; | |
297 | 300 | |||
298 | offset = inst & 0xFFFF; | 301 | offset = inst & 0xFFFF; | |
299 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 302 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
300 | 303 | |||
301 | /* segment and alignment check */ | 304 | /* segment and alignment check */ | |
302 | if (vaddr < 0 || (vaddr & 3)) { | 305 | if (vaddr < 0 || (vaddr & 3)) { | |
303 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 306 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
304 | return; | 307 | return; | |
305 | } | 308 | } | |
306 | 309 | |||
307 | t = &(tf->tf_regs[(inst>>16)&0x1F]); | 310 | t = &(tf->tf_regs[(inst>>16)&0x1F]); | |
308 | 311 | |||
309 | if (copyin((void *)vaddr, t, 4) != 0) { | 312 | if (copyin((void *)vaddr, t, 4) != 0) { | |
310 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 313 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
311 | return; | 314 | return; | |
312 | } | 315 | } | |
313 | 316 | |||
314 | llstate.lwp = curlwp; | 317 | llstate.lwp = curlwp; | |
315 | llstate.addr = vaddr; | 318 | llstate.addr = vaddr; | |
316 | llstate.value = *((uint32_t *)t); | 319 | llstate.value = *((uint32_t *)t); | |
317 | 320 | |||
318 | update_pc(tf, cause); | 321 | update_pc(tf, cause); | |
319 | } | 322 | } | |
320 | 323 | |||
321 | /* | 324 | /* | |
322 | * MIPS2 SC instruction | 325 | * MIPS2 SC instruction | |
323 | */ | 326 | */ | |
324 | void | 327 | void | |
325 | mips_emul_swc0(uint32_t inst, struct trapframe *tf, uint32_t cause) | 328 | mips_emul_sc(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
326 | { | 329 | { | |
327 | intptr_t vaddr; | 330 | intptr_t vaddr; | |
328 | uint32_t value; | 331 | uint32_t value; | |
329 | int16_t offset; | 332 | int16_t offset; | |
330 | mips_reg_t *t; | 333 | mips_reg_t *t; | |
331 | 334 | |||
332 | offset = inst & 0xFFFF; | 335 | offset = inst & 0xFFFF; | |
333 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 336 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
334 | 337 | |||
335 | /* segment and alignment check */ | 338 | /* segment and alignment check */ | |
336 | if (vaddr < 0 || (vaddr & 3)) { | 339 | if (vaddr < 0 || (vaddr & 3)) { | |
337 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 340 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
338 | return; | 341 | return; | |
339 | } | 342 | } | |
340 | 343 | |||
341 | t = (mips_reg_t *)&(tf->tf_regs[(inst>>16)&0x1F]); | 344 | t = (mips_reg_t *)&(tf->tf_regs[(inst>>16)&0x1F]); | |
342 | 345 | |||
343 | /* | 346 | /* | |
344 | * Check that the process and address match the last | 347 | * Check that the process and address match the last | |
345 | * LL instruction. | 348 | * LL instruction. | |
346 | */ | 349 | */ | |
347 | if (curlwp == llstate.lwp && vaddr == llstate.addr) { | 350 | if (curlwp == llstate.lwp && vaddr == llstate.addr) { | |
348 | llstate.lwp = NULL; | 351 | llstate.lwp = NULL; | |
349 | /* | 352 | /* | |
350 | * Check that the data at the address hasn't changed | 353 | * Check that the data at the address hasn't changed | |
351 | * since the LL instruction. | 354 | * since the LL instruction. | |
352 | */ | 355 | */ | |
353 | if (copyin((void *)vaddr, &value, 4) != 0) { | 356 | if (copyin((void *)vaddr, &value, 4) != 0) { | |
354 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 357 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
355 | return; | 358 | return; | |
356 | } | 359 | } | |
357 | if (value == llstate.value) { | 360 | if (value == llstate.value) { | |
358 | /* SC successful */ | 361 | /* SC successful */ | |
359 | if (copyout(t, (void *)vaddr, 4) != 0) { | 362 | if (copyout(t, (void *)vaddr, 4) != 0) { | |
360 | send_sigsegv(vaddr, T_TLB_ST_MISS, | 363 | send_sigsegv(vaddr, T_TLB_ST_MISS, | |
361 | tf, cause); | 364 | tf, cause); | |
362 | return; | 365 | return; | |
363 | } | 366 | } | |
364 | *t = 1; | 367 | *t = 1; | |
365 | update_pc(tf, cause); | 368 | update_pc(tf, cause); | |
366 | return; | 369 | return; | |
367 | } | 370 | } | |
368 | } | 371 | } | |
369 | 372 | |||
370 | /* SC failed */ | 373 | /* SC failed */ | |
371 | *t = 0; | 374 | *t = 0; | |
372 | update_pc(tf, cause); | 375 | update_pc(tf, cause); | |
373 | } | 376 | } | |
374 | 377 | |||
375 | void | 378 | void | |
376 | mips_emul_special(uint32_t inst, struct trapframe *tf, uint32_t cause) | 379 | mips_emul_special(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
377 | { | 380 | { | |
378 | ksiginfo_t ksi; | 381 | ksiginfo_t ksi; | |
379 | const InstFmt instfmt = { .word = inst }; | 382 | const InstFmt instfmt = { .word = inst }; | |
380 | 383 | |||
381 | switch (instfmt.RType.func) { | 384 | switch (instfmt.RType.func) { | |
382 | case OP_SYNC: | 385 | case OP_SYNC: | |
383 | /* nothing */ | 386 | /* nothing */ | |
384 | break; | 387 | break; | |
385 | default: | 388 | default: | |
386 | tf->tf_regs[_R_CAUSE] = cause; | 389 | tf->tf_regs[_R_CAUSE] = cause; | |
387 | tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; | 390 | tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; | |
388 | KSI_INIT_TRAP(&ksi); | 391 | KSI_INIT_TRAP(&ksi); | |
389 | ksi.ksi_signo = SIGILL; | 392 | ksi.ksi_signo = SIGILL; | |
390 | ksi.ksi_trap = cause; | 393 | ksi.ksi_trap = cause; | |
391 | ksi.ksi_code = ILL_ILLOPC; | 394 | ksi.ksi_code = ILL_ILLOPC; | |
392 | ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; | 395 | ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; | |
393 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | 396 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | |
394 | break; | 397 | break; | |
395 | } | 398 | } | |
396 | 399 | |||
397 | update_pc(tf, cause); | 400 | update_pc(tf, cause); | |
398 | } | 401 | } | |
399 | 402 | |||
400 | void | 403 | void | |
401 | mips_emul_special3(uint32_t inst, struct trapframe *tf, uint32_t cause) | 404 | mips_emul_special3(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
402 | { | 405 | { | |
403 | ksiginfo_t ksi; | 406 | ksiginfo_t ksi; | |
404 | const InstFmt instfmt = { .word = inst }; | 407 | const InstFmt instfmt = { .word = inst }; | |
405 | switch (instfmt.RType.func) { | 408 | switch (instfmt.RType.func) { | |
406 | case OP_LX: { | 409 | case OP_LX: { | |
407 | const intptr_t vaddr = tf->tf_regs[instfmt.RType.rs] | 410 | const intptr_t vaddr = tf->tf_regs[instfmt.RType.rs] | |
408 | + tf->tf_regs[instfmt.RType.rt]; | 411 | + tf->tf_regs[instfmt.RType.rt]; | |
409 | mips_reg_t r; | 412 | mips_reg_t r; | |
410 | int error = EFAULT; | 413 | int error = EFAULT; | |
411 | if (vaddr < 0) { | 414 | if (vaddr < 0) { | |
412 | addr_err: | 415 | addr_err: | |
413 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 416 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
414 | return; | 417 | return; | |
415 | } | 418 | } | |
416 | switch (instfmt.RType.shamt) { | 419 | switch (instfmt.RType.shamt) { | |
417 | #if !defined(__mips_o32) | 420 | #if !defined(__mips_o32) | |
418 | case OP_LX_LDX: { | 421 | case OP_LX_LDX: { | |
419 | uint64_t tmp64; | 422 | uint64_t tmp64; | |
420 | if (vaddr & 7) | 423 | if (vaddr & 7) | |
421 | goto addr_err; | 424 | goto addr_err; | |
422 | error = copyin((void *)vaddr, &tmp64, sizeof(tmp64)); | 425 | error = copyin((void *)vaddr, &tmp64, sizeof(tmp64)); | |
423 | r = tmp64; | 426 | r = tmp64; | |
424 | break; | 427 | break; | |
425 | } | 428 | } | |
426 | #endif | 429 | #endif | |
427 | case OP_LX_LWX: { | 430 | case OP_LX_LWX: { | |
428 | int32_t tmp32; | 431 | int32_t tmp32; | |
429 | if (vaddr & 3) | 432 | if (vaddr & 3) | |
430 | goto addr_err; | 433 | goto addr_err; | |
431 | error = copyin((void *)vaddr, &tmp32, sizeof(tmp32)); | 434 | error = copyin((void *)vaddr, &tmp32, sizeof(tmp32)); | |
432 | r = tmp32; | 435 | r = tmp32; | |
433 | break; | 436 | break; | |
434 | } | 437 | } | |
435 | case OP_LX_LHX: { | 438 | case OP_LX_LHX: { | |
436 | int16_t tmp16; | 439 | int16_t tmp16; | |
437 | if (vaddr & 1) | 440 | if (vaddr & 1) | |
438 | goto addr_err; | 441 | goto addr_err; | |
439 | error = copyin((void *)vaddr, &tmp16, sizeof(tmp16)); | 442 | error = copyin((void *)vaddr, &tmp16, sizeof(tmp16)); | |
440 | r = tmp16; | 443 | r = tmp16; | |
441 | break; | 444 | break; | |
442 | } | 445 | } | |
443 | case OP_LX_LBUX: { | 446 | case OP_LX_LBUX: { | |
444 | uint8_t tmp8; | 447 | uint8_t tmp8; | |
445 | error = copyin((void *)vaddr, &tmp8, sizeof(tmp8)); | 448 | error = copyin((void *)vaddr, &tmp8, sizeof(tmp8)); | |
446 | r = tmp8; | 449 | r = tmp8; | |
447 | break; | 450 | break; | |
448 | } | 451 | } | |
449 | default: | 452 | default: | |
450 | goto illopc; | 453 | goto illopc; | |
451 | } | 454 | } | |
452 | if (error) { | 455 | if (error) { | |
453 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 456 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
454 | return; | 457 | return; | |
455 | } | 458 | } | |
456 | tf->tf_regs[instfmt.RType.rd] = r; | 459 | tf->tf_regs[instfmt.RType.rd] = r; | |
457 | break; | 460 | break; | |
458 | } | 461 | } | |
459 | case OP_RDHWR: | 462 | case OP_RDHWR: | |
460 | switch (instfmt.RType.rd) { | 463 | switch (instfmt.RType.rd) { | |
461 | case 29: | 464 | case 29: | |
462 | tf->tf_regs[instfmt.RType.rt] = | 465 | tf->tf_regs[instfmt.RType.rt] = | |
463 | (mips_reg_t)(intptr_t)curlwp->l_private; | 466 | (mips_reg_t)(intptr_t)curlwp->l_private; | |
464 | goto done; | 467 | goto done; | |
465 | } | 468 | } | |
466 | /* FALLTHROUGH */ | 469 | /* FALLTHROUGH */ | |
467 | illopc: | 470 | illopc: | |
468 | default: | 471 | default: | |
469 | tf->tf_regs[_R_CAUSE] = cause; | 472 | tf->tf_regs[_R_CAUSE] = cause; | |
470 | tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; | 473 | tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; | |
471 | KSI_INIT_TRAP(&ksi); | 474 | KSI_INIT_TRAP(&ksi); | |
472 | ksi.ksi_signo = SIGILL; | 475 | ksi.ksi_signo = SIGILL; | |
473 | ksi.ksi_trap = cause; | 476 | ksi.ksi_trap = cause; | |
474 | ksi.ksi_code = ILL_ILLOPC; | 477 | ksi.ksi_code = ILL_ILLOPC; | |
475 | ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; | 478 | ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; | |
476 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | 479 | (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); | |
477 | return; | 480 | return; | |
478 | } | 481 | } | |
479 | done: | 482 | done: | |
480 | update_pc(tf, cause); | 483 | update_pc(tf, cause); | |
481 | } | 484 | } | |
482 | 485 | |||
483 | #if defined(FPEMUL) | 486 | #if defined(FPEMUL) | |
484 | 487 | |||
485 | #define LWSWC1_MAXLOOP 12 | 488 | #define LWSWC1_MAXLOOP 12 | |
486 | 489 | |||
487 | void | 490 | void | |
488 | mips_emul_lwc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | 491 | mips_emul_lwc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
489 | { | 492 | { | |
490 | intptr_t vaddr; | 493 | intptr_t vaddr; | |
491 | int16_t offset; | 494 | int16_t offset; | |
492 | void *t; | 495 | void *t; | |
493 | mips_reg_t pc; | 496 | mips_reg_t pc; | |
494 | int i; | 497 | int i; | |
495 | 498 | |||
496 | offset = inst & 0xFFFF; | 499 | offset = inst & 0xFFFF; | |
497 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 500 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
498 | 501 | |||
499 | /* segment and alignment check */ | 502 | /* segment and alignment check */ | |
500 | if (vaddr < 0 || (vaddr & 3)) { | 503 | if (vaddr < 0 || (vaddr & 3)) { | |
501 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 504 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
502 | return; | 505 | return; | |
503 | } | 506 | } | |
504 | 507 | |||
505 | /* NewABI FIXME */ | 508 | /* NewABI FIXME */ | |
506 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | 509 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | |
507 | 510 | |||
508 | if (copyin((void *)vaddr, t, 4) != 0) { | 511 | if (copyin((void *)vaddr, t, 4) != 0) { | |
509 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 512 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
510 | return; | 513 | return; | |
511 | } | 514 | } | |
512 | 515 | |||
513 | pc = tf->tf_regs[_R_PC]; | 516 | pc = tf->tf_regs[_R_PC]; | |
514 | update_pc(tf, cause); | 517 | update_pc(tf, cause); | |
515 | 518 | |||
516 | if (cause & MIPS_CR_BR_DELAY) | 519 | if (cause & MIPS_CR_BR_DELAY) | |
517 | return; | 520 | return; | |
518 | 521 | |||
519 | for (i = 1; i < LWSWC1_MAXLOOP; i++) { | 522 | for (i = 1; i < LWSWC1_MAXLOOP; i++) { | |
520 | if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) | 523 | if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) | |
521 | return; | 524 | return; | |
522 | 525 | |||
523 | vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ | 526 | vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ | |
524 | inst = mips_ufetch32((uint32_t *)vaddr); | 527 | inst = mips_ufetch32((uint32_t *)vaddr); | |
525 | if (((InstFmt)inst).FRType.op != OP_LWC1) | 528 | if (((InstFmt)inst).FRType.op != OP_LWC1) | |
526 | return; | 529 | return; | |
527 | 530 | |||
528 | offset = inst & 0xFFFF; | 531 | offset = inst & 0xFFFF; | |
529 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 532 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
530 | 533 | |||
531 | /* segment and alignment check */ | 534 | /* segment and alignment check */ | |
532 | if (vaddr < 0 || (vaddr & 3)) { | 535 | if (vaddr < 0 || (vaddr & 3)) { | |
533 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 536 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
534 | return; | 537 | return; | |
535 | } | 538 | } | |
536 | 539 | |||
537 | /* NewABI FIXME */ | 540 | /* NewABI FIXME */ | |
538 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | 541 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | |
539 | 542 | |||
540 | if (copyin((void *)vaddr, t, 4) != 0) { | 543 | if (copyin((void *)vaddr, t, 4) != 0) { | |
541 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 544 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
542 | return; | 545 | return; | |
543 | } | 546 | } | |
544 | 547 | |||
545 | pc = tf->tf_regs[_R_PC]; | 548 | pc = tf->tf_regs[_R_PC]; | |
546 | update_pc(tf, cause); | 549 | update_pc(tf, cause); | |
547 | } | 550 | } | |
548 | } | 551 | } | |
549 | 552 | |||
550 | void | 553 | void | |
551 | mips_emul_ldc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | 554 | mips_emul_ldc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
552 | { | 555 | { | |
553 | intptr_t vaddr; | 556 | intptr_t vaddr; | |
554 | int16_t offset; | 557 | int16_t offset; | |
555 | void *t; | 558 | void *t; | |
556 | 559 | |||
557 | offset = inst & 0xFFFF; | 560 | offset = inst & 0xFFFF; | |
558 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 561 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
559 | 562 | |||
560 | /* segment and alignment check */ | 563 | /* segment and alignment check */ | |
561 | if (vaddr < 0 || (vaddr & 7)) { | 564 | if (vaddr < 0 || (vaddr & 7)) { | |
562 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 565 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
563 | return; | 566 | return; | |
564 | } | 567 | } | |
565 | 568 | |||
566 | /* NewABI FIXME */ | 569 | /* NewABI FIXME */ | |
567 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); | 570 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); | |
568 | 571 | |||
569 | if (copyin((void *)vaddr, t, 8) != 0) { | 572 | if (copyin((void *)vaddr, t, 8) != 0) { | |
570 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 573 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
571 | return; | 574 | return; | |
572 | } | 575 | } | |
573 | 576 | |||
574 | update_pc(tf, cause); | 577 | update_pc(tf, cause); | |
575 | } | 578 | } | |
576 | 579 | |||
577 | void | 580 | void | |
578 | mips_emul_swc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | 581 | mips_emul_swc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
579 | { | 582 | { | |
580 | intptr_t vaddr; | 583 | intptr_t vaddr; | |
581 | int16_t offset; | 584 | int16_t offset; | |
582 | void *t; | 585 | void *t; | |
583 | mips_reg_t pc; | 586 | mips_reg_t pc; | |
584 | int i; | 587 | int i; | |
585 | 588 | |||
586 | offset = inst & 0xFFFF; | 589 | offset = inst & 0xFFFF; | |
587 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 590 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
588 | 591 | |||
589 | /* segment and alignment check */ | 592 | /* segment and alignment check */ | |
590 | if (vaddr < 0 || (vaddr & 3)) { | 593 | if (vaddr < 0 || (vaddr & 3)) { | |
591 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 594 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
592 | return; | 595 | return; | |
593 | } | 596 | } | |
594 | 597 | |||
595 | /* NewABI FIXME */ | 598 | /* NewABI FIXME */ | |
596 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | 599 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | |
597 | 600 | |||
598 | if (copyout(t, (void *)vaddr, 4) != 0) { | 601 | if (copyout(t, (void *)vaddr, 4) != 0) { | |
599 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 602 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
600 | return; | 603 | return; | |
601 | } | 604 | } | |
602 | 605 | |||
603 | pc = tf->tf_regs[_R_PC]; | 606 | pc = tf->tf_regs[_R_PC]; | |
604 | update_pc(tf, cause); | 607 | update_pc(tf, cause); | |
605 | 608 | |||
606 | if (cause & MIPS_CR_BR_DELAY) | 609 | if (cause & MIPS_CR_BR_DELAY) | |
607 | return; | 610 | return; | |
608 | 611 | |||
609 | for (i = 1; i < LWSWC1_MAXLOOP; i++) { | 612 | for (i = 1; i < LWSWC1_MAXLOOP; i++) { | |
610 | if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) | 613 | if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) | |
611 | return; | 614 | return; | |
612 | 615 | |||
613 | vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ | 616 | vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ | |
614 | inst = mips_ufetch32((uint32_t *)vaddr); | 617 | inst = mips_ufetch32((uint32_t *)vaddr); | |
615 | if (((InstFmt)inst).FRType.op != OP_SWC1) | 618 | if (((InstFmt)inst).FRType.op != OP_SWC1) | |
616 | return; | 619 | return; | |
617 | 620 | |||
618 | offset = inst & 0xFFFF; | 621 | offset = inst & 0xFFFF; | |
619 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 622 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
620 | 623 | |||
621 | /* segment and alignment check */ | 624 | /* segment and alignment check */ | |
622 | if (vaddr < 0 || (vaddr & 3)) { | 625 | if (vaddr < 0 || (vaddr & 3)) { | |
623 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 626 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
624 | return; | 627 | return; | |
625 | } | 628 | } | |
626 | 629 | |||
627 | /* NewABI FIXME */ | 630 | /* NewABI FIXME */ | |
628 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | 631 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); | |
629 | 632 | |||
630 | if (copyout(t, (void *)vaddr, 4) != 0) { | 633 | if (copyout(t, (void *)vaddr, 4) != 0) { | |
631 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 634 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
632 | return; | 635 | return; | |
633 | } | 636 | } | |
634 | 637 | |||
635 | pc = tf->tf_regs[_R_PC]; | 638 | pc = tf->tf_regs[_R_PC]; | |
636 | update_pc(tf, cause); | 639 | update_pc(tf, cause); | |
637 | } | 640 | } | |
638 | } | 641 | } | |
639 | 642 | |||
640 | void | 643 | void | |
641 | mips_emul_sdc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | 644 | mips_emul_sdc1(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
642 | { | 645 | { | |
643 | intptr_t vaddr; | 646 | intptr_t vaddr; | |
644 | int16_t offset; | 647 | int16_t offset; | |
645 | void *t; | 648 | void *t; | |
646 | 649 | |||
647 | offset = inst & 0xFFFF; | 650 | offset = inst & 0xFFFF; | |
648 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 651 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
649 | 652 | |||
650 | /* segment and alignment check */ | 653 | /* segment and alignment check */ | |
651 | if (vaddr < 0 || (vaddr & 7)) { | 654 | if (vaddr < 0 || (vaddr & 7)) { | |
652 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 655 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
653 | return; | 656 | return; | |
654 | } | 657 | } | |
655 | 658 | |||
656 | /* NewABI FIXME */ | 659 | /* NewABI FIXME */ | |
657 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); | 660 | t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); | |
658 | 661 | |||
659 | if (copyout(t, (void *)vaddr, 8) != 0) { | 662 | if (copyout(t, (void *)vaddr, 8) != 0) { | |
660 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 663 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
661 | return; | 664 | return; | |
662 | } | 665 | } | |
663 | 666 | |||
664 | update_pc(tf, cause); | 667 | update_pc(tf, cause); | |
665 | } | 668 | } | |
666 | 669 | |||
667 | void | 670 | void | |
668 | mips_emul_lb(uint32_t inst, struct trapframe *tf, uint32_t cause) | 671 | mips_emul_lb(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
669 | { | 672 | { | |
670 | intptr_t vaddr; | 673 | intptr_t vaddr; | |
671 | int16_t offset; | 674 | int16_t offset; | |
672 | int8_t x; | 675 | int8_t x; | |
673 | 676 | |||
674 | offset = inst & 0xFFFF; | 677 | offset = inst & 0xFFFF; | |
675 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 678 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
676 | 679 | |||
677 | /* segment check */ | 680 | /* segment check */ | |
678 | if (vaddr < 0) { | 681 | if (vaddr < 0) { | |
679 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 682 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
680 | return; | 683 | return; | |
681 | } | 684 | } | |
682 | 685 | |||
683 | if (copyin((void *)vaddr, &x, 1) != 0) { | 686 | if (copyin((void *)vaddr, &x, 1) != 0) { | |
684 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 687 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
685 | return; | 688 | return; | |
686 | } | 689 | } | |
687 | 690 | |||
688 | tf->tf_regs[(inst>>16)&0x1F] = x; | 691 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
689 | 692 | |||
690 | update_pc(tf, cause); | 693 | update_pc(tf, cause); | |
691 | } | 694 | } | |
692 | 695 | |||
693 | void | 696 | void | |
694 | mips_emul_lbu(uint32_t inst, struct trapframe *tf, uint32_t cause) | 697 | mips_emul_lbu(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
695 | { | 698 | { | |
696 | intptr_t vaddr; | 699 | intptr_t vaddr; | |
697 | int16_t offset; | 700 | int16_t offset; | |
698 | uint8_t x; | 701 | uint8_t x; | |
699 | 702 | |||
700 | offset = inst & 0xFFFF; | 703 | offset = inst & 0xFFFF; | |
701 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 704 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
702 | 705 | |||
703 | /* segment check */ | 706 | /* segment check */ | |
704 | if (vaddr < 0) { | 707 | if (vaddr < 0) { | |
705 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 708 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
706 | return; | 709 | return; | |
707 | } | 710 | } | |
708 | 711 | |||
709 | if (copyin((void *)vaddr, &x, 1) != 0) { | 712 | if (copyin((void *)vaddr, &x, 1) != 0) { | |
710 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 713 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
711 | return; | 714 | return; | |
712 | } | 715 | } | |
713 | 716 | |||
714 | tf->tf_regs[(inst>>16)&0x1F] = x; | 717 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
715 | 718 | |||
716 | update_pc(tf, cause); | 719 | update_pc(tf, cause); | |
717 | } | 720 | } | |
718 | 721 | |||
719 | void | 722 | void | |
720 | mips_emul_lh(uint32_t inst, struct trapframe *tf, uint32_t cause) | 723 | mips_emul_lh(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
721 | { | 724 | { | |
722 | intptr_t vaddr; | 725 | intptr_t vaddr; | |
723 | int16_t offset; | 726 | int16_t offset; | |
724 | int16_t x; | 727 | int16_t x; | |
725 | 728 | |||
726 | offset = inst & 0xFFFF; | 729 | offset = inst & 0xFFFF; | |
727 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 730 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
728 | 731 | |||
729 | /* segment and alignment check */ | 732 | /* segment and alignment check */ | |
730 | if (vaddr < 0 || (vaddr & 1)) { | 733 | if (vaddr < 0 || (vaddr & 1)) { | |
731 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 734 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
732 | return; | 735 | return; | |
733 | } | 736 | } | |
734 | 737 | |||
735 | if (copyin((void *)vaddr, &x, 2) != 0) { | 738 | if (copyin((void *)vaddr, &x, 2) != 0) { | |
736 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 739 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
737 | return; | 740 | return; | |
738 | } | 741 | } | |
739 | 742 | |||
740 | tf->tf_regs[(inst>>16)&0x1F] = x; | 743 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
741 | 744 | |||
742 | update_pc(tf, cause); | 745 | update_pc(tf, cause); | |
743 | } | 746 | } | |
744 | 747 | |||
745 | void | 748 | void | |
746 | mips_emul_lhu(uint32_t inst, struct trapframe *tf, uint32_t cause) | 749 | mips_emul_lhu(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
747 | { | 750 | { | |
748 | intptr_t vaddr; | 751 | intptr_t vaddr; | |
749 | int16_t offset; | 752 | int16_t offset; | |
750 | uint16_t x; | 753 | uint16_t x; | |
751 | 754 | |||
752 | offset = inst & 0xFFFF; | 755 | offset = inst & 0xFFFF; | |
753 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 756 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
754 | 757 | |||
755 | /* segment and alignment check */ | 758 | /* segment and alignment check */ | |
756 | if (vaddr < 0 || (vaddr & 1)) { | 759 | if (vaddr < 0 || (vaddr & 1)) { | |
757 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 760 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
758 | return; | 761 | return; | |
759 | } | 762 | } | |
760 | 763 | |||
761 | if (copyin((void *)vaddr, &x, 2) != 0) { | 764 | if (copyin((void *)vaddr, &x, 2) != 0) { | |
762 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 765 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
763 | return; | 766 | return; | |
764 | } | 767 | } | |
765 | 768 | |||
766 | tf->tf_regs[(inst>>16)&0x1F] = (mips_ureg_t)x; | 769 | tf->tf_regs[(inst>>16)&0x1F] = (mips_ureg_t)x; | |
767 | 770 | |||
768 | update_pc(tf, cause); | 771 | update_pc(tf, cause); | |
769 | } | 772 | } | |
770 | 773 | |||
771 | void | 774 | void | |
772 | mips_emul_lw(uint32_t inst, struct trapframe *tf, uint32_t cause) | 775 | mips_emul_lw(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
773 | { | 776 | { | |
774 | intptr_t vaddr; | 777 | intptr_t vaddr; | |
775 | int16_t offset; | 778 | int16_t offset; | |
776 | int32_t x; | 779 | int32_t x; | |
777 | 780 | |||
778 | offset = inst & 0xFFFF; | 781 | offset = inst & 0xFFFF; | |
779 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 782 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
780 | 783 | |||
781 | /* segment and alignment check */ | 784 | /* segment and alignment check */ | |
782 | if (vaddr < 0 || (vaddr & 3)) { | 785 | if (vaddr < 0 || (vaddr & 3)) { | |
783 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 786 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
784 | return; | 787 | return; | |
785 | } | 788 | } | |
786 | 789 | |||
787 | if (copyin((void *)vaddr, &x, 4) != 0) { | 790 | if (copyin((void *)vaddr, &x, 4) != 0) { | |
788 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 791 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
789 | return; | 792 | return; | |
790 | } | 793 | } | |
791 | 794 | |||
792 | tf->tf_regs[(inst>>16)&0x1F] = x; | 795 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
793 | 796 | |||
794 | update_pc(tf, cause); | 797 | update_pc(tf, cause); | |
795 | } | 798 | } | |
796 | 799 | |||
797 | void | 800 | void | |
798 | mips_emul_lwl(uint32_t inst, struct trapframe *tf, uint32_t cause) | 801 | mips_emul_lwl(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
799 | { | 802 | { | |
800 | intptr_t vaddr; | 803 | intptr_t vaddr; | |
801 | uint32_t a, x, shift; | 804 | uint32_t a, x, shift; | |
802 | int16_t offset; | 805 | int16_t offset; | |
803 | 806 | |||
804 | offset = inst & 0xFFFF; | 807 | offset = inst & 0xFFFF; | |
805 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 808 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
806 | 809 | |||
807 | /* segment check */ | 810 | /* segment check */ | |
808 | if (vaddr < 0) { | 811 | if (vaddr < 0) { | |
809 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 812 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
810 | return; | 813 | return; | |
811 | } | 814 | } | |
812 | 815 | |||
813 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | 816 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | |
814 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 817 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
815 | return; | 818 | return; | |
816 | } | 819 | } | |
817 | 820 | |||
818 | x = tf->tf_regs[(inst>>16)&0x1F]; | 821 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
819 | 822 | |||
820 | shift = (3 - (vaddr & 0x00000003)) * 8; | 823 | shift = (3 - (vaddr & 0x00000003)) * 8; | |
821 | a <<= shift; | 824 | a <<= shift; | |
822 | x &= ~(0xFFFFFFFFUL << shift); | 825 | x &= ~(0xFFFFFFFFUL << shift); | |
823 | x |= a; | 826 | x |= a; | |
824 | 827 | |||
825 | tf->tf_regs[(inst>>16)&0x1F] = x; | 828 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
826 | 829 | |||
827 | update_pc(tf, cause); | 830 | update_pc(tf, cause); | |
828 | } | 831 | } | |
829 | 832 | |||
830 | void | 833 | void | |
831 | mips_emul_lwr(uint32_t inst, struct trapframe *tf, uint32_t cause) | 834 | mips_emul_lwr(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
832 | { | 835 | { | |
833 | intptr_t vaddr; | 836 | intptr_t vaddr; | |
834 | uint32_t a, x, shift; | 837 | uint32_t a, x, shift; | |
835 | int16_t offset; | 838 | int16_t offset; | |
836 | 839 | |||
837 | offset = inst & 0xFFFF; | 840 | offset = inst & 0xFFFF; | |
838 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 841 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
839 | 842 | |||
840 | /* segment check */ | 843 | /* segment check */ | |
841 | if (vaddr & 0x80000000) { | 844 | if (vaddr & 0x80000000) { | |
842 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 845 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
843 | return; | 846 | return; | |
844 | } | 847 | } | |
845 | 848 | |||
846 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | 849 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | |
847 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 850 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
848 | return; | 851 | return; | |
849 | } | 852 | } | |
850 | 853 | |||
851 | x = tf->tf_regs[(inst>>16)&0x1F]; | 854 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
852 | 855 | |||
853 | shift = (vaddr & 0x00000003) * 8; | 856 | shift = (vaddr & 0x00000003) * 8; | |
854 | a >>= shift; | 857 | a >>= shift; | |
855 | x &= ~(0xFFFFFFFFUL >> shift); | 858 | x &= ~(0xFFFFFFFFUL >> shift); | |
856 | x |= a; | 859 | x |= a; | |
857 | 860 | |||
858 | tf->tf_regs[(inst>>16)&0x1F] = x; | 861 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
859 | 862 | |||
860 | update_pc(tf, cause); | 863 | update_pc(tf, cause); | |
861 | } | 864 | } | |
862 | 865 | |||
863 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | 866 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | |
864 | void | 867 | void | |
865 | mips_emul_lwu(uint32_t inst, struct trapframe *tf, uint32_t cause) | 868 | mips_emul_lwu(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
866 | { | 869 | { | |
867 | intptr_t vaddr; | 870 | intptr_t vaddr; | |
868 | int16_t offset; | 871 | int16_t offset; | |
869 | uint32_t x; | 872 | uint32_t x; | |
870 | 873 | |||
871 | offset = inst & 0xFFFF; | 874 | offset = inst & 0xFFFF; | |
872 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 875 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
873 | 876 | |||
874 | /* segment and alignment check */ | 877 | /* segment and alignment check */ | |
875 | if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) { | 878 | if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) { | |
876 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 879 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
877 | return; | 880 | return; | |
878 | } | 881 | } | |
879 | 882 | |||
880 | if (copyin((void *)vaddr, &x, 4) != 0) { | 883 | if (copyin((void *)vaddr, &x, 4) != 0) { | |
881 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 884 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
882 | return; | 885 | return; | |
883 | } | 886 | } | |
884 | 887 | |||
885 | tf->tf_regs[(inst>>16)&0x1F] = x; | 888 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
886 | 889 | |||
887 | update_pc(tf, cause); | 890 | update_pc(tf, cause); | |
888 | } | 891 | } | |
889 | 892 | |||
890 | void | 893 | void | |
891 | mips_emul_ld(uint32_t inst, struct trapframe *tf, uint32_t cause) | 894 | mips_emul_ld(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
892 | { | 895 | { | |
893 | intptr_t vaddr; | 896 | intptr_t vaddr; | |
894 | int16_t offset; | 897 | int16_t offset; | |
895 | 898 | |||
896 | offset = inst & 0xFFFF; | 899 | offset = inst & 0xFFFF; | |
897 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 900 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
898 | 901 | |||
899 | /* segment and alignment check */ | 902 | /* segment and alignment check */ | |
900 | if (vaddr > VM_MAX_ADDRESS || vaddr & 0x7) { | 903 | if (vaddr > VM_MAX_ADDRESS || vaddr & 0x7) { | |
901 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 904 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
902 | return; | 905 | return; | |
903 | } | 906 | } | |
904 | 907 | |||
905 | if (copyin((void *)vaddr, &(tf->tf_regs[(inst>>16)&0x1F]), 8) != 0) { | 908 | if (copyin((void *)vaddr, &(tf->tf_regs[(inst>>16)&0x1F]), 8) != 0) { | |
906 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 909 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
907 | return; | 910 | return; | |
908 | } | 911 | } | |
909 | 912 | |||
910 | update_pc(tf, cause); | 913 | update_pc(tf, cause); | |
911 | } | 914 | } | |
912 | 915 | |||
913 | void | 916 | void | |
914 | mips_emul_ldl(uint32_t inst, struct trapframe *tf, uint32_t cause) | 917 | mips_emul_ldl(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
915 | { | 918 | { | |
916 | intptr_t vaddr; | 919 | intptr_t vaddr; | |
917 | uint64_t a, x; | 920 | uint64_t a, x; | |
918 | uint32_t shift; | 921 | uint32_t shift; | |
919 | int16_t offset; | 922 | int16_t offset; | |
920 | 923 | |||
921 | offset = inst & 0xFFFF; | 924 | offset = inst & 0xFFFF; | |
922 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 925 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
923 | 926 | |||
924 | /* segment check */ | 927 | /* segment check */ | |
925 | if (vaddr & 0x80000000) { | 928 | if (vaddr & 0x80000000) { | |
926 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 929 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
927 | return; | 930 | return; | |
928 | } | 931 | } | |
929 | 932 | |||
930 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | 933 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
931 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 934 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
932 | return; | 935 | return; | |
933 | } | 936 | } | |
934 | 937 | |||
935 | x = tf->tf_regs[(inst>>16)&0x1F]; | 938 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
936 | 939 | |||
937 | shift = (7 - (vaddr & 0x7)) * 8; | 940 | shift = (7 - (vaddr & 0x7)) * 8; | |
938 | a <<= shift; | 941 | a <<= shift; | |
939 | x &= ~(~(uint64_t)0UL << shift); | 942 | x &= ~(~(uint64_t)0UL << shift); | |
940 | x |= a; | 943 | x |= a; | |
941 | 944 | |||
942 | tf->tf_regs[(inst>>16)&0x1F] = x; | 945 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
943 | 946 | |||
944 | update_pc(tf, cause); | 947 | update_pc(tf, cause); | |
945 | } | 948 | } | |
946 | 949 | |||
947 | void | 950 | void | |
948 | mips_emul_ldr(uint32_t inst, struct trapframe *tf, uint32_t cause) | 951 | mips_emul_ldr(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
949 | { | 952 | { | |
950 | intptr_t vaddr; | 953 | intptr_t vaddr; | |
951 | uint64_t a, x; | 954 | uint64_t a, x; | |
952 | uint32_t shift; | 955 | uint32_t shift; | |
953 | int16_t offset; | 956 | int16_t offset; | |
954 | 957 | |||
955 | offset = inst & 0xFFFF; | 958 | offset = inst & 0xFFFF; | |
956 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 959 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
957 | 960 | |||
958 | /* segment check */ | 961 | /* segment check */ | |
959 | if (vaddr < 0) { | 962 | if (vaddr < 0) { | |
960 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | 963 | send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); | |
961 | return; | 964 | return; | |
962 | } | 965 | } | |
963 | 966 | |||
964 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | 967 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
965 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | 968 | send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); | |
966 | return; | 969 | return; | |
967 | } | 970 | } | |
968 | 971 | |||
969 | x = tf->tf_regs[(inst>>16)&0x1F]; | 972 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
970 | 973 | |||
971 | shift = (vaddr & 0x7) * 8; | 974 | shift = (vaddr & 0x7) * 8; | |
972 | a >>= shift; | 975 | a >>= shift; | |
973 | x &= ~(~(uint64_t)0UL >> shift); | 976 | x &= ~(~(uint64_t)0UL >> shift); | |
974 | x |= a; | 977 | x |= a; | |
975 | 978 | |||
976 | tf->tf_regs[(inst>>16)&0x1F] = x; | 979 | tf->tf_regs[(inst>>16)&0x1F] = x; | |
977 | 980 | |||
978 | update_pc(tf, cause); | 981 | update_pc(tf, cause); | |
979 | } | 982 | } | |
980 | #endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ | 983 | #endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ | |
981 | 984 | |||
982 | void | 985 | void | |
983 | mips_emul_sb(uint32_t inst, struct trapframe *tf, uint32_t cause) | 986 | mips_emul_sb(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
984 | { | 987 | { | |
985 | intptr_t vaddr; | 988 | intptr_t vaddr; | |
986 | int16_t offset; | 989 | int16_t offset; | |
987 | 990 | |||
988 | offset = inst & 0xFFFF; | 991 | offset = inst & 0xFFFF; | |
989 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 992 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
990 | 993 | |||
991 | /* segment check */ | 994 | /* segment check */ | |
992 | if (vaddr < 0) { | 995 | if (vaddr < 0) { | |
993 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 996 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
994 | return; | 997 | return; | |
995 | } | 998 | } | |
996 | 999 | |||
997 | if (ustore_8((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | 1000 | if (ustore_8((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | |
998 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1001 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
999 | return; | 1002 | return; | |
1000 | } | 1003 | } | |
1001 | 1004 | |||
1002 | update_pc(tf, cause); | 1005 | update_pc(tf, cause); | |
1003 | } | 1006 | } | |
1004 | 1007 | |||
1005 | void | 1008 | void | |
1006 | mips_emul_sh(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1009 | mips_emul_sh(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1007 | { | 1010 | { | |
1008 | intptr_t vaddr; | 1011 | intptr_t vaddr; | |
1009 | int16_t offset; | 1012 | int16_t offset; | |
1010 | 1013 | |||
1011 | offset = inst & 0xFFFF; | 1014 | offset = inst & 0xFFFF; | |
1012 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1015 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1013 | 1016 | |||
1014 | /* segment and alignment check */ | 1017 | /* segment and alignment check */ | |
1015 | if (vaddr < 0 || vaddr & 1) { | 1018 | if (vaddr < 0 || vaddr & 1) { | |
1016 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1019 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1017 | return; | 1020 | return; | |
1018 | } | 1021 | } | |
1019 | 1022 | |||
1020 | if (ustore_16((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | 1023 | if (ustore_16((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | |
1021 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1024 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1022 | return; | 1025 | return; | |
1023 | } | 1026 | } | |
1024 | 1027 | |||
1025 | update_pc(tf, cause); | 1028 | update_pc(tf, cause); | |
1026 | } | 1029 | } | |
1027 | 1030 | |||
1028 | void | 1031 | void | |
1029 | mips_emul_sw(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1032 | mips_emul_sw(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1030 | { | 1033 | { | |
1031 | intptr_t vaddr; | 1034 | intptr_t vaddr; | |
1032 | int16_t offset; | 1035 | int16_t offset; | |
1033 | 1036 | |||
1034 | offset = inst & 0xFFFF; | 1037 | offset = inst & 0xFFFF; | |
1035 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1038 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1036 | 1039 | |||
1037 | /* segment and alignment check */ | 1040 | /* segment and alignment check */ | |
1038 | if (vaddr < 0 || (vaddr & 3)) { | 1041 | if (vaddr < 0 || (vaddr & 3)) { | |
1039 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1042 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1040 | return; | 1043 | return; | |
1041 | } | 1044 | } | |
1042 | 1045 | |||
1043 | if (ustore_32((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | 1046 | if (ustore_32((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { | |
1044 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1047 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1045 | return; | 1048 | return; | |
1046 | } | 1049 | } | |
1047 | 1050 | |||
1048 | update_pc(tf, cause); | 1051 | update_pc(tf, cause); | |
1049 | } | 1052 | } | |
1050 | 1053 | |||
1051 | void | 1054 | void | |
1052 | mips_emul_swl(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1055 | mips_emul_swl(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1053 | { | 1056 | { | |
1054 | intptr_t vaddr; | 1057 | intptr_t vaddr; | |
1055 | uint32_t a, x, shift; | 1058 | uint32_t a, x, shift; | |
1056 | int16_t offset; | 1059 | int16_t offset; | |
1057 | 1060 | |||
1058 | offset = inst & 0xFFFF; | 1061 | offset = inst & 0xFFFF; | |
1059 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1062 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1060 | 1063 | |||
1061 | /* segment check */ | 1064 | /* segment check */ | |
1062 | if (vaddr < 0) { | 1065 | if (vaddr < 0) { | |
1063 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1066 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1064 | return; | 1067 | return; | |
1065 | } | 1068 | } | |
1066 | 1069 | |||
1067 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | 1070 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | |
1068 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1071 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1069 | return; | 1072 | return; | |
1070 | } | 1073 | } | |
1071 | 1074 | |||
1072 | x = tf->tf_regs[(inst>>16)&0x1F]; | 1075 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
1073 | 1076 | |||
1074 | shift = (3 - (vaddr & 3)) * 8; | 1077 | shift = (3 - (vaddr & 3)) * 8; | |
1075 | x >>= shift; | 1078 | x >>= shift; | |
1076 | a &= ~(0xFFFFFFFFUL >> shift); | 1079 | a &= ~(0xFFFFFFFFUL >> shift); | |
1077 | a |= x; | 1080 | a |= x; | |
1078 | 1081 | |||
1079 | if (ustore_32((void *)vaddr, a) != 0) { | 1082 | if (ustore_32((void *)vaddr, a) != 0) { | |
1080 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1083 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1081 | return; | 1084 | return; | |
1082 | } | 1085 | } | |
1083 | 1086 | |||
1084 | update_pc(tf, cause); | 1087 | update_pc(tf, cause); | |
1085 | } | 1088 | } | |
1086 | 1089 | |||
1087 | void | 1090 | void | |
1088 | mips_emul_swr(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1091 | mips_emul_swr(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1089 | { | 1092 | { | |
1090 | intptr_t vaddr; | 1093 | intptr_t vaddr; | |
1091 | uint32_t a, x, shift; | 1094 | uint32_t a, x, shift; | |
1092 | int16_t offset; | 1095 | int16_t offset; | |
1093 | 1096 | |||
1094 | offset = inst & 0xFFFF; | 1097 | offset = inst & 0xFFFF; | |
1095 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1098 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1096 | 1099 | |||
1097 | /* segment check */ | 1100 | /* segment check */ | |
1098 | if (vaddr < 0) { | 1101 | if (vaddr < 0) { | |
1099 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1102 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1100 | return; | 1103 | return; | |
1101 | } | 1104 | } | |
1102 | 1105 | |||
1103 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | 1106 | if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { | |
1104 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1107 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1105 | return; | 1108 | return; | |
1106 | } | 1109 | } | |
1107 | 1110 | |||
1108 | x = tf->tf_regs[(inst>>16)&0x1F]; | 1111 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
1109 | 1112 | |||
1110 | shift = (vaddr & 3) * 8; | 1113 | shift = (vaddr & 3) * 8; | |
1111 | x <<= shift; | 1114 | x <<= shift; | |
1112 | a &= ~(0xFFFFFFFFUL << shift); | 1115 | a &= ~(0xFFFFFFFFUL << shift); | |
1113 | a |= x; | 1116 | a |= x; | |
1114 | 1117 | |||
1115 | if (ustore_32((void *)vaddr, a) != 0) { | 1118 | if (ustore_32((void *)vaddr, a) != 0) { | |
1116 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1119 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1117 | return; | 1120 | return; | |
1118 | } | 1121 | } | |
1119 | 1122 | |||
1120 | update_pc(tf, cause); | 1123 | update_pc(tf, cause); | |
1121 | } | 1124 | } | |
1122 | 1125 | |||
1123 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | 1126 | #if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) | |
1124 | void | 1127 | void | |
1125 | mips_emul_sd(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1128 | mips_emul_sd(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1126 | { | 1129 | { | |
1127 | intptr_t vaddr; | 1130 | intptr_t vaddr; | |
1128 | int16_t offset; | 1131 | int16_t offset; | |
1129 | 1132 | |||
1130 | offset = inst & 0xFFFF; | 1133 | offset = inst & 0xFFFF; | |
1131 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1134 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1132 | 1135 | |||
1133 | /* segment and alignment check */ | 1136 | /* segment and alignment check */ | |
1134 | if (vaddr < 0 || vaddr & 0x7) { | 1137 | if (vaddr < 0 || vaddr & 0x7) { | |
1135 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1138 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1136 | return; | 1139 | return; | |
1137 | } | 1140 | } | |
1138 | 1141 | |||
1139 | if (copyout((void *)vaddr, &tf->tf_regs[(inst>>16)&0x1F], 8) < 0) { | 1142 | if (copyout((void *)vaddr, &tf->tf_regs[(inst>>16)&0x1F], 8) < 0) { | |
1140 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1143 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1141 | return; | 1144 | return; | |
1142 | } | 1145 | } | |
1143 | 1146 | |||
1144 | update_pc(tf, cause); | 1147 | update_pc(tf, cause); | |
1145 | } | 1148 | } | |
1146 | 1149 | |||
1147 | void | 1150 | void | |
1148 | mips_emul_sdl(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1151 | mips_emul_sdl(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1149 | { | 1152 | { | |
1150 | intptr_t vaddr; | 1153 | intptr_t vaddr; | |
1151 | uint64_t a, x; | 1154 | uint64_t a, x; | |
1152 | uint32_t shift; | 1155 | uint32_t shift; | |
1153 | int16_t offset; | 1156 | int16_t offset; | |
1154 | 1157 | |||
1155 | offset = inst & 0xFFFF; | 1158 | offset = inst & 0xFFFF; | |
1156 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1159 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1157 | 1160 | |||
1158 | /* segment check */ | 1161 | /* segment check */ | |
1159 | if (vaddr < 0) { | 1162 | if (vaddr < 0) { | |
1160 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1163 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1161 | return; | 1164 | return; | |
1162 | } | 1165 | } | |
1163 | 1166 | |||
1164 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | 1167 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
1165 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1168 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1166 | return; | 1169 | return; | |
1167 | } | 1170 | } | |
1168 | 1171 | |||
1169 | x = tf->tf_regs[(inst>>16)&0x1F]; | 1172 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
1170 | 1173 | |||
1171 | shift = (7 - (vaddr & 7)) * 8; | 1174 | shift = (7 - (vaddr & 7)) * 8; | |
1172 | x >>= shift; | 1175 | x >>= shift; | |
1173 | a &= ~(~(uint64_t)0U >> shift); | 1176 | a &= ~(~(uint64_t)0U >> shift); | |
1174 | a |= x; | 1177 | a |= x; | |
1175 | 1178 | |||
1176 | if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { | 1179 | if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
1177 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1180 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1178 | return; | 1181 | return; | |
1179 | } | 1182 | } | |
1180 | 1183 | |||
1181 | update_pc(tf, cause); | 1184 | update_pc(tf, cause); | |
1182 | } | 1185 | } | |
1183 | 1186 | |||
1184 | void | 1187 | void | |
1185 | mips_emul_sdr(uint32_t inst, struct trapframe *tf, uint32_t cause) | 1188 | mips_emul_sdr(uint32_t inst, struct trapframe *tf, uint32_t cause) | |
1186 | { | 1189 | { | |
1187 | intptr_t vaddr; | 1190 | intptr_t vaddr; | |
1188 | uint64_t a, x; | 1191 | uint64_t a, x; | |
1189 | uint32_t shift; | 1192 | uint32_t shift; | |
1190 | int16_t offset; | 1193 | int16_t offset; | |
1191 | 1194 | |||
1192 | offset = inst & 0xFFFF; | 1195 | offset = inst & 0xFFFF; | |
1193 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | 1196 | vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; | |
1194 | 1197 | |||
1195 | /* segment check */ | 1198 | /* segment check */ | |
1196 | if (vaddr < 0) { | 1199 | if (vaddr < 0) { | |
1197 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | 1200 | send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); | |
1198 | return; | 1201 | return; | |
1199 | } | 1202 | } | |
1200 | 1203 | |||
1201 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | 1204 | if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
1202 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1205 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1203 | return; | 1206 | return; | |
1204 | } | 1207 | } | |
1205 | 1208 | |||
1206 | x = tf->tf_regs[(inst>>16)&0x1F]; | 1209 | x = tf->tf_regs[(inst>>16)&0x1F]; | |
1207 | 1210 | |||
1208 | shift = (vaddr & 7) * 8; | 1211 | shift = (vaddr & 7) * 8; | |
1209 | x <<= shift; | 1212 | x <<= shift; | |
1210 | a &= ~(~(uint64_t)0U << shift); | 1213 | a &= ~(~(uint64_t)0U << shift); | |
1211 | a |= x; | 1214 | a |= x; | |
1212 | 1215 | |||
1213 | if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { | 1216 | if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { | |
1214 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | 1217 | send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); | |
1215 | return; | 1218 | return; | |
1216 | } | 1219 | } | |
1217 | 1220 | |||
1218 | update_pc(tf, cause); | 1221 | update_pc(tf, cause); | |
1219 | } | 1222 | } | |
1220 | #endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ | 1223 | #endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ | |
1221 | #endif /* defined(FPEMUL) */ | 1224 | #endif /* defined(FPEMUL) */ |