Thu May 27 13:32:54 2021 UTC ()
Print the CP0 status register too in the debug trap code.


(simonb)
diff -r1.27 -r1.28 src/sys/arch/mips/mips/mips_emul.c

cvs diff -r1.27 -r1.28 src/sys/arch/mips/mips/mips_emul.c (switch to unified diff)

--- src/sys/arch/mips/mips/mips_emul.c 2019/04/06 03:06:26 1.27
+++ src/sys/arch/mips/mips/mips_emul.c 2021/05/27 13:32:54 1.28
@@ -1,1218 +1,1221 @@ @@ -1,1218 +1,1221 @@
1/* $NetBSD: mips_emul.c,v 1.27 2019/04/06 03:06:26 thorpej Exp $ */ 1/* $NetBSD: mips_emul.c,v 1.28 2021/05/27 13:32:54 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.27 2019/04/06 03:06:26 thorpej Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.28 2021/05/27 13:32:54 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
46static inline void send_sigsegv(intptr_t, uint32_t, struct trapframe *, 46static inline void send_sigsegv(intptr_t, uint32_t, struct trapframe *,
47 uint32_t); 47 uint32_t);
48static inline void update_pc(struct trapframe *, uint32_t); 48static inline void update_pc(struct trapframe *, uint32_t);
49 49
50/* 50/*
51 * MIPS2 LL instruction emulation state 51 * MIPS2 LL instruction emulation state
52 */ 52 */
53struct { 53struct {
54 struct lwp *lwp; 54 struct lwp *lwp;
55 vaddr_t addr; 55 vaddr_t addr;
56 uint32_t value; 56 uint32_t value;
57} llstate; 57} llstate;
58 58
59/* 59/*
60 * Analyse 'next' PC address taking account of branch/jump instructions 60 * Analyse 'next' PC address taking account of branch/jump instructions
61 */ 61 */
62vaddr_t 62vaddr_t
63mips_emul_branch(struct trapframe *tf, vaddr_t instpc, uint32_t fpuCSR, 63mips_emul_branch(struct trapframe *tf, vaddr_t instpc, uint32_t fpuCSR,
64 bool allowNonBranch) 64 bool allowNonBranch)
65{ 65{
66#define BRANCHTARGET(pc, i) (4 + (pc) + ((short)(i).IType.imm << 2)) 66#define BRANCHTARGET(pc, i) (4 + (pc) + ((short)(i).IType.imm << 2))
67 InstFmt inst; 67 InstFmt inst;
68 vaddr_t nextpc; 68 vaddr_t nextpc;
69 69
70 if (instpc < MIPS_KSEG0_START) { 70 if (instpc < MIPS_KSEG0_START) {
71 inst.word = mips_ufetch32((void *)instpc); 71 inst.word = mips_ufetch32((void *)instpc);
72 } else { 72 } else {
73 inst.word = *(uint32_t *)instpc; 73 inst.word = *(uint32_t *)instpc;
74 } 74 }
75 75
76 switch ((int)inst.JType.op) { 76 switch ((int)inst.JType.op) {
77 case OP_SPECIAL: 77 case OP_SPECIAL:
78 if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR) 78 if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR)
79 nextpc = tf->tf_regs[inst.RType.rs]; 79 nextpc = tf->tf_regs[inst.RType.rs];
80 else if (allowNonBranch) 80 else if (allowNonBranch)
81 nextpc = instpc + 4; 81 nextpc = instpc + 4;
82 else 82 else
83 panic("%s: %s instruction %08x at pc 0x%"PRIxVADDR, 83 panic("%s: %s instruction %08x at pc 0x%"PRIxVADDR,
84 __func__, "non-branch", inst.word, instpc); 84 __func__, "non-branch", inst.word, instpc);
85 break; 85 break;
86 86
87 case OP_REGIMM: 87 case OP_REGIMM:
88 switch ((int)inst.IType.rt) { 88 switch ((int)inst.IType.rt) {
89 case OP_BLTZ: 89 case OP_BLTZ:
90 case OP_BLTZAL: 90 case OP_BLTZAL:
91 case OP_BLTZL: /* squashed */ 91 case OP_BLTZL: /* squashed */
92 case OP_BLTZALL: /* squashed */ 92 case OP_BLTZALL: /* squashed */
93 if ((int)(tf->tf_regs[inst.RType.rs]) < 0) 93 if ((int)(tf->tf_regs[inst.RType.rs]) < 0)
94 nextpc = BRANCHTARGET(instpc, inst); 94 nextpc = BRANCHTARGET(instpc, inst);
95 else 95 else
96 nextpc = instpc + 8; 96 nextpc = instpc + 8;
97 break; 97 break;
98 98
99 case OP_BGEZ: 99 case OP_BGEZ:
100 case OP_BGEZAL: 100 case OP_BGEZAL:
101 case OP_BGEZL: /* squashed */ 101 case OP_BGEZL: /* squashed */
102 case OP_BGEZALL: /* squashed */ 102 case OP_BGEZALL: /* squashed */
103 if ((int)(tf->tf_regs[inst.RType.rs]) >= 0) 103 if ((int)(tf->tf_regs[inst.RType.rs]) >= 0)
104 nextpc = BRANCHTARGET(instpc, inst); 104 nextpc = BRANCHTARGET(instpc, inst);
105 else 105 else
106 nextpc = instpc + 8; 106 nextpc = instpc + 8;
107 break; 107 break;
108 108
109 default: 109 default:
110 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, 110 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
111 __func__, "bad branch", inst.word, instpc); 111 __func__, "bad branch", inst.word, instpc);
112 } 112 }
113 break; 113 break;
114 114
115 case OP_J: 115 case OP_J:
116 case OP_JAL: 116 case OP_JAL:
117 nextpc = (inst.JType.target << 2) | 117 nextpc = (inst.JType.target << 2) |
118 ((intptr_t)instpc & 0xF0000000); 118 ((intptr_t)instpc & 0xF0000000);
119 break; 119 break;
120 120
121 case OP_BEQ: 121 case OP_BEQ:
122 case OP_BEQL: /* squashed */ 122 case OP_BEQL: /* squashed */
123 if (tf->tf_regs[inst.RType.rs] == tf->tf_regs[inst.RType.rt]) 123 if (tf->tf_regs[inst.RType.rs] == tf->tf_regs[inst.RType.rt])
124 nextpc = BRANCHTARGET(instpc, inst); 124 nextpc = BRANCHTARGET(instpc, inst);
125 else 125 else
126 nextpc = instpc + 8; 126 nextpc = instpc + 8;
127 break; 127 break;
128 128
129 case OP_BNE: 129 case OP_BNE:
130 case OP_BNEL: /* squashed */ 130 case OP_BNEL: /* squashed */
131 if (tf->tf_regs[inst.RType.rs] != tf->tf_regs[inst.RType.rt]) 131 if (tf->tf_regs[inst.RType.rs] != tf->tf_regs[inst.RType.rt])
132 nextpc = BRANCHTARGET(instpc, inst); 132 nextpc = BRANCHTARGET(instpc, inst);
133 else 133 else
134 nextpc = instpc + 8; 134 nextpc = instpc + 8;
135 break; 135 break;
136 136
137 case OP_BLEZ: 137 case OP_BLEZ:
138 case OP_BLEZL: /* squashed */ 138 case OP_BLEZL: /* squashed */
139 if ((int)(tf->tf_regs[inst.RType.rs]) <= 0) 139 if ((int)(tf->tf_regs[inst.RType.rs]) <= 0)
140 nextpc = BRANCHTARGET(instpc, inst); 140 nextpc = BRANCHTARGET(instpc, inst);
141 else 141 else
142 nextpc = instpc + 8; 142 nextpc = instpc + 8;
143 break; 143 break;
144 144
145 case OP_BGTZ: 145 case OP_BGTZ:
146 case OP_BGTZL: /* squashed */ 146 case OP_BGTZL: /* squashed */
147 if ((int)(tf->tf_regs[inst.RType.rs]) > 0) 147 if ((int)(tf->tf_regs[inst.RType.rs]) > 0)
148 nextpc = BRANCHTARGET(instpc, inst); 148 nextpc = BRANCHTARGET(instpc, inst);
149 else 149 else
150 nextpc = instpc + 8; 150 nextpc = instpc + 8;
151 break; 151 break;
152 152
153 case OP_COP1: 153 case OP_COP1:
154 if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) { 154 if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) {
155 int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0; 155 int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0;
156 if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE) 156 if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE)
157 condition = !condition; 157 condition = !condition;
158 if (condition) 158 if (condition)
159 nextpc = BRANCHTARGET(instpc, inst); 159 nextpc = BRANCHTARGET(instpc, inst);
160 else 160 else
161 nextpc = instpc + 8; 161 nextpc = instpc + 8;
162 } 162 }
163 else if (allowNonBranch) 163 else if (allowNonBranch)
164 nextpc = instpc + 4; 164 nextpc = instpc + 4;
165 else 165 else
166 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, 166 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
167 __func__, "bad COP1 branch", inst.word, instpc); 167 __func__, "bad COP1 branch", inst.word, instpc);
168 break; 168 break;
169 169
170 default: 170 default:
171 if (!allowNonBranch) 171 if (!allowNonBranch)
172 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR, 172 panic("%s: %s instruction 0x%08x at pc 0x%"PRIxVADDR,
173 __func__, "non-branch", inst.word, instpc); 173 __func__, "non-branch", inst.word, instpc);
174 nextpc = instpc + 4; 174 nextpc = instpc + 4;
175 } 175 }
176 KASSERT((nextpc & 0x3) == 0); 176 KASSERT((nextpc & 0x3) == 0);
177 return nextpc; 177 return nextpc;
178#undef BRANCHTARGET 178#undef BRANCHTARGET
179} 179}
180 180
181/* 181/*
182 * Emulate instructions (including floating-point instructions) 182 * Emulate instructions (including floating-point instructions)
183 */ 183 */
184void 184void
185mips_emul_inst(uint32_t status, uint32_t cause, vaddr_t opc, 185mips_emul_inst(uint32_t status, uint32_t cause, vaddr_t opc,
186 struct trapframe *tf) 186 struct trapframe *tf)
187{ 187{
188 uint32_t inst; 188 uint32_t inst;
189 ksiginfo_t ksi; 189 ksiginfo_t ksi;
190 int code = ILL_ILLOPC; 190 int code = ILL_ILLOPC;
191 191
192 /* 192 /*
193 * Fetch the instruction. 193 * Fetch the instruction.
194 */ 194 */
195 if (cause & MIPS_CR_BR_DELAY) 195 if (cause & MIPS_CR_BR_DELAY)
196 inst = mips_ufetch32((uint32_t *)opc+1); 196 inst = mips_ufetch32((uint32_t *)opc+1);
197 else 197 else
198 inst = mips_ufetch32((uint32_t *)opc); 198 inst = mips_ufetch32((uint32_t *)opc);
199 199
200 switch (((InstFmt)inst).FRType.op) { 200 switch (((InstFmt)inst).FRType.op) {
201 case OP_LWC0: 201 case OP_LWC0:
202 mips_emul_lwc0(inst, tf, cause); 202 mips_emul_lwc0(inst, tf, cause);
203 break; 203 break;
204 case OP_SWC0: 204 case OP_SWC0:
205 mips_emul_swc0(inst, tf, cause); 205 mips_emul_swc0(inst, tf, cause);
206 break; 206 break;
207 case OP_SPECIAL: 207 case OP_SPECIAL:
208 mips_emul_special(inst, tf, cause); 208 mips_emul_special(inst, tf, cause);
209 break; 209 break;
210 case OP_SPECIAL3: 210 case OP_SPECIAL3:
211 mips_emul_special3(inst, tf, cause); 211 mips_emul_special3(inst, tf, cause);
212 break; 212 break;
213 case OP_COP1: 213 case OP_COP1:
214#if defined(FPEMUL) 214#if defined(FPEMUL)
215 mips_emul_fp(inst, tf, cause); 215 mips_emul_fp(inst, tf, cause);
216 break; 216 break;
217#endif 217#endif
218 case OP_LWC1: 218 case OP_LWC1:
219#if defined(FPEMUL) 219#if defined(FPEMUL)
220 mips_emul_lwc1(inst, tf, cause); 220 mips_emul_lwc1(inst, tf, cause);
221 break; 221 break;
222#endif 222#endif
223 case OP_LDC1: 223 case OP_LDC1:
224#if defined(FPEMUL) 224#if defined(FPEMUL)
225 mips_emul_ldc1(inst, tf, cause); 225 mips_emul_ldc1(inst, tf, cause);
226 break; 226 break;
227#endif 227#endif
228 case OP_SWC1: 228 case OP_SWC1:
229#if defined(FPEMUL) 229#if defined(FPEMUL)
230 mips_emul_swc1(inst, tf, cause); 230 mips_emul_swc1(inst, tf, cause);
231 break; 231 break;
232#endif 232#endif
233 case OP_SDC1: 233 case OP_SDC1:
234#if defined(FPEMUL) 234#if defined(FPEMUL)
235 mips_emul_sdc1(inst, tf, cause); 235 mips_emul_sdc1(inst, tf, cause);
236 break; 236 break;
237#else 237#else
238 code = ILL_COPROC; 238 code = ILL_COPROC;
239 /* FALLTHROUGH */ 239 /* FALLTHROUGH */
240#endif 240#endif
241 default: 241 default:
242#ifdef DEBUG 242#ifdef DEBUG
243 printf("pid %d (%s): trap: bad insn @ %#"PRIxVADDR" cause %#x insn %#x code %d\n", curproc->p_pid, curproc->p_comm, opc, cause, inst, code); 243 printf("pid %d (%s): trap: bad insn @ %#"PRIxVADDR
 244 " cause %#x status %#"PRIxREGISTER" insn %#x code %d\n",
 245 curproc->p_pid, curproc->p_comm, opc,
 246 cause, tf->tf_regs[_R_SR], inst, code);
244#endif 247#endif
245 tf->tf_regs[_R_CAUSE] = cause; 248 tf->tf_regs[_R_CAUSE] = cause;
246 tf->tf_regs[_R_BADVADDR] = opc; 249 tf->tf_regs[_R_BADVADDR] = opc;
247 KSI_INIT_TRAP(&ksi); 250 KSI_INIT_TRAP(&ksi);
248 ksi.ksi_signo = SIGILL; 251 ksi.ksi_signo = SIGILL;
249 ksi.ksi_trap = cause; /* XXX */ 252 ksi.ksi_trap = cause; /* XXX */
250 ksi.ksi_code = code; 253 ksi.ksi_code = code;
251 ksi.ksi_addr = (void *)opc; 254 ksi.ksi_addr = (void *)opc;
252 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); 255 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
253 break; 256 break;
254 } 257 }
255} 258}
256 259
257static inline void 260static inline void
258send_sigsegv(intptr_t vaddr, uint32_t exccode, struct trapframe *tf, 261send_sigsegv(intptr_t vaddr, uint32_t exccode, struct trapframe *tf,
259 uint32_t cause) 262 uint32_t cause)
260{ 263{
261 ksiginfo_t ksi; 264 ksiginfo_t ksi;
262 cause = (cause & ~0xFF) | (exccode << MIPS_CR_EXC_CODE_SHIFT); 265 cause = (cause & ~0xFF) | (exccode << MIPS_CR_EXC_CODE_SHIFT);
263 tf->tf_regs[_R_CAUSE] = cause; 266 tf->tf_regs[_R_CAUSE] = cause;
264 tf->tf_regs[_R_BADVADDR] = vaddr; 267 tf->tf_regs[_R_BADVADDR] = vaddr;
265 KSI_INIT_TRAP(&ksi); 268 KSI_INIT_TRAP(&ksi);
266 ksi.ksi_signo = SIGSEGV; 269 ksi.ksi_signo = SIGSEGV;
267 ksi.ksi_trap = cause; 270 ksi.ksi_trap = cause;
268 ksi.ksi_code = SEGV_MAPERR; 271 ksi.ksi_code = SEGV_MAPERR;
269 ksi.ksi_addr = (void *)vaddr; 272 ksi.ksi_addr = (void *)vaddr;
270 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); 273 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
271} 274}
272 275
273static inline void 276static inline void
274update_pc(struct trapframe *tf, uint32_t cause) 277update_pc(struct trapframe *tf, uint32_t cause)
275{ 278{
276 279
277 if (cause & MIPS_CR_BR_DELAY) 280 if (cause & MIPS_CR_BR_DELAY)
278 tf->tf_regs[_R_PC] =  281 tf->tf_regs[_R_PC] =
279 mips_emul_branch(tf, tf->tf_regs[_R_PC], 282 mips_emul_branch(tf, tf->tf_regs[_R_PC],
280 PCB_FSR(curpcb), 0); 283 PCB_FSR(curpcb), 0);
281 else 284 else
282 tf->tf_regs[_R_PC] += 4; 285 tf->tf_regs[_R_PC] += 4;
283} 286}
284 287
285/* 288/*
286 * MIPS2 LL instruction 289 * MIPS2 LL instruction
287 */ 290 */
288void 291void
289mips_emul_lwc0(uint32_t inst, struct trapframe *tf, uint32_t cause) 292mips_emul_lwc0(uint32_t inst, struct trapframe *tf, uint32_t cause)
290{ 293{
291 intptr_t vaddr; 294 intptr_t vaddr;
292 int16_t offset; 295 int16_t offset;
293 void *t; 296 void *t;
294 297
295 offset = inst & 0xFFFF; 298 offset = inst & 0xFFFF;
296 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 299 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
297 300
298 /* segment and alignment check */ 301 /* segment and alignment check */
299 if (vaddr < 0 || (vaddr & 3)) { 302 if (vaddr < 0 || (vaddr & 3)) {
300 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 303 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
301 return; 304 return;
302 } 305 }
303 306
304 t = &(tf->tf_regs[(inst>>16)&0x1F]); 307 t = &(tf->tf_regs[(inst>>16)&0x1F]);
305 308
306 if (copyin((void *)vaddr, t, 4) != 0) { 309 if (copyin((void *)vaddr, t, 4) != 0) {
307 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 310 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
308 return; 311 return;
309 } 312 }
310 313
311 llstate.lwp = curlwp; 314 llstate.lwp = curlwp;
312 llstate.addr = vaddr; 315 llstate.addr = vaddr;
313 llstate.value = *((uint32_t *)t); 316 llstate.value = *((uint32_t *)t);
314 317
315 update_pc(tf, cause); 318 update_pc(tf, cause);
316} 319}
317 320
318/* 321/*
319 * MIPS2 SC instruction 322 * MIPS2 SC instruction
320 */ 323 */
321void 324void
322mips_emul_swc0(uint32_t inst, struct trapframe *tf, uint32_t cause) 325mips_emul_swc0(uint32_t inst, struct trapframe *tf, uint32_t cause)
323{ 326{
324 intptr_t vaddr; 327 intptr_t vaddr;
325 uint32_t value; 328 uint32_t value;
326 int16_t offset; 329 int16_t offset;
327 mips_reg_t *t; 330 mips_reg_t *t;
328 331
329 offset = inst & 0xFFFF; 332 offset = inst & 0xFFFF;
330 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 333 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
331 334
332 /* segment and alignment check */ 335 /* segment and alignment check */
333 if (vaddr < 0 || (vaddr & 3)) { 336 if (vaddr < 0 || (vaddr & 3)) {
334 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 337 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
335 return; 338 return;
336 } 339 }
337 340
338 t = (mips_reg_t *)&(tf->tf_regs[(inst>>16)&0x1F]); 341 t = (mips_reg_t *)&(tf->tf_regs[(inst>>16)&0x1F]);
339 342
340 /* 343 /*
341 * Check that the process and address match the last 344 * Check that the process and address match the last
342 * LL instruction. 345 * LL instruction.
343 */ 346 */
344 if (curlwp == llstate.lwp && vaddr == llstate.addr) { 347 if (curlwp == llstate.lwp && vaddr == llstate.addr) {
345 llstate.lwp = NULL; 348 llstate.lwp = NULL;
346 /* 349 /*
347 * Check that the data at the address hasn't changed 350 * Check that the data at the address hasn't changed
348 * since the LL instruction. 351 * since the LL instruction.
349 */ 352 */
350 if (copyin((void *)vaddr, &value, 4) != 0) { 353 if (copyin((void *)vaddr, &value, 4) != 0) {
351 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 354 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
352 return; 355 return;
353 } 356 }
354 if (value == llstate.value) { 357 if (value == llstate.value) {
355 /* SC successful */ 358 /* SC successful */
356 if (copyout(t, (void *)vaddr, 4) != 0) { 359 if (copyout(t, (void *)vaddr, 4) != 0) {
357 send_sigsegv(vaddr, T_TLB_ST_MISS, 360 send_sigsegv(vaddr, T_TLB_ST_MISS,
358 tf, cause); 361 tf, cause);
359 return; 362 return;
360 } 363 }
361 *t = 1; 364 *t = 1;
362 update_pc(tf, cause); 365 update_pc(tf, cause);
363 return; 366 return;
364 } 367 }
365 } 368 }
366 369
367 /* SC failed */ 370 /* SC failed */
368 *t = 0; 371 *t = 0;
369 update_pc(tf, cause); 372 update_pc(tf, cause);
370} 373}
371 374
372void 375void
373mips_emul_special(uint32_t inst, struct trapframe *tf, uint32_t cause) 376mips_emul_special(uint32_t inst, struct trapframe *tf, uint32_t cause)
374{ 377{
375 ksiginfo_t ksi; 378 ksiginfo_t ksi;
376 const InstFmt instfmt = { .word = inst }; 379 const InstFmt instfmt = { .word = inst };
377 380
378 switch (instfmt.RType.func) { 381 switch (instfmt.RType.func) {
379 case OP_SYNC: 382 case OP_SYNC:
380 /* nothing */ 383 /* nothing */
381 break; 384 break;
382 default: 385 default:
383 tf->tf_regs[_R_CAUSE] = cause; 386 tf->tf_regs[_R_CAUSE] = cause;
384 tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; 387 tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC];
385 KSI_INIT_TRAP(&ksi); 388 KSI_INIT_TRAP(&ksi);
386 ksi.ksi_signo = SIGILL; 389 ksi.ksi_signo = SIGILL;
387 ksi.ksi_trap = cause; 390 ksi.ksi_trap = cause;
388 ksi.ksi_code = ILL_ILLOPC; 391 ksi.ksi_code = ILL_ILLOPC;
389 ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; 392 ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC];
390 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); 393 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
391 break; 394 break;
392 } 395 }
393 396
394 update_pc(tf, cause); 397 update_pc(tf, cause);
395} 398}
396 399
397void 400void
398mips_emul_special3(uint32_t inst, struct trapframe *tf, uint32_t cause) 401mips_emul_special3(uint32_t inst, struct trapframe *tf, uint32_t cause)
399{ 402{
400 ksiginfo_t ksi; 403 ksiginfo_t ksi;
401 const InstFmt instfmt = { .word = inst }; 404 const InstFmt instfmt = { .word = inst };
402 switch (instfmt.RType.func) { 405 switch (instfmt.RType.func) {
403 case OP_LX: { 406 case OP_LX: {
404 const intptr_t vaddr = tf->tf_regs[instfmt.RType.rs]  407 const intptr_t vaddr = tf->tf_regs[instfmt.RType.rs]
405 + tf->tf_regs[instfmt.RType.rt]; 408 + tf->tf_regs[instfmt.RType.rt];
406 mips_reg_t r; 409 mips_reg_t r;
407 int error = EFAULT; 410 int error = EFAULT;
408 if (vaddr < 0) { 411 if (vaddr < 0) {
409 addr_err: 412 addr_err:
410 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 413 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
411 return; 414 return;
412 } 415 }
413 switch (instfmt.RType.shamt) { 416 switch (instfmt.RType.shamt) {
414#if !defined(__mips_o32) 417#if !defined(__mips_o32)
415 case OP_LX_LDX: { 418 case OP_LX_LDX: {
416 uint64_t tmp64; 419 uint64_t tmp64;
417 if (vaddr & 7) 420 if (vaddr & 7)
418 goto addr_err; 421 goto addr_err;
419 error = copyin((void *)vaddr, &tmp64, sizeof(tmp64)); 422 error = copyin((void *)vaddr, &tmp64, sizeof(tmp64));
420 r = tmp64; 423 r = tmp64;
421 break; 424 break;
422 } 425 }
423#endif 426#endif
424 case OP_LX_LWX: { 427 case OP_LX_LWX: {
425 int32_t tmp32; 428 int32_t tmp32;
426 if (vaddr & 3) 429 if (vaddr & 3)
427 goto addr_err; 430 goto addr_err;
428 error = copyin((void *)vaddr, &tmp32, sizeof(tmp32)); 431 error = copyin((void *)vaddr, &tmp32, sizeof(tmp32));
429 r = tmp32; 432 r = tmp32;
430 break; 433 break;
431 } 434 }
432 case OP_LX_LHX: { 435 case OP_LX_LHX: {
433 int16_t tmp16; 436 int16_t tmp16;
434 if (vaddr & 1) 437 if (vaddr & 1)
435 goto addr_err; 438 goto addr_err;
436 error = copyin((void *)vaddr, &tmp16, sizeof(tmp16)); 439 error = copyin((void *)vaddr, &tmp16, sizeof(tmp16));
437 r = tmp16; 440 r = tmp16;
438 break; 441 break;
439 } 442 }
440 case OP_LX_LBUX: { 443 case OP_LX_LBUX: {
441 uint8_t tmp8; 444 uint8_t tmp8;
442 error = copyin((void *)vaddr, &tmp8, sizeof(tmp8)); 445 error = copyin((void *)vaddr, &tmp8, sizeof(tmp8));
443 r = tmp8; 446 r = tmp8;
444 break; 447 break;
445 } 448 }
446 default: 449 default:
447 goto illopc; 450 goto illopc;
448 } 451 }
449 if (error) { 452 if (error) {
450 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 453 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
451 return; 454 return;
452 } 455 }
453 tf->tf_regs[instfmt.RType.rd] = r; 456 tf->tf_regs[instfmt.RType.rd] = r;
454 break; 457 break;
455 } 458 }
456 case OP_RDHWR: 459 case OP_RDHWR:
457 switch (instfmt.RType.rd) { 460 switch (instfmt.RType.rd) {
458 case 29: 461 case 29:
459 tf->tf_regs[instfmt.RType.rt] = 462 tf->tf_regs[instfmt.RType.rt] =
460 (mips_reg_t)(intptr_t)curlwp->l_private; 463 (mips_reg_t)(intptr_t)curlwp->l_private;
461 goto done; 464 goto done;
462 } 465 }
463 /* FALLTHROUGH */ 466 /* FALLTHROUGH */
464 illopc: 467 illopc:
465 default: 468 default:
466 tf->tf_regs[_R_CAUSE] = cause; 469 tf->tf_regs[_R_CAUSE] = cause;
467 tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC]; 470 tf->tf_regs[_R_BADVADDR] = tf->tf_regs[_R_PC];
468 KSI_INIT_TRAP(&ksi); 471 KSI_INIT_TRAP(&ksi);
469 ksi.ksi_signo = SIGILL; 472 ksi.ksi_signo = SIGILL;
470 ksi.ksi_trap = cause; 473 ksi.ksi_trap = cause;
471 ksi.ksi_code = ILL_ILLOPC; 474 ksi.ksi_code = ILL_ILLOPC;
472 ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC]; 475 ksi.ksi_addr = (void *)(intptr_t)tf->tf_regs[_R_PC];
473 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); 476 (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
474 return; 477 return;
475 } 478 }
476done: 479done:
477 update_pc(tf, cause); 480 update_pc(tf, cause);
478} 481}
479 482
480#if defined(FPEMUL) 483#if defined(FPEMUL)
481 484
482#define LWSWC1_MAXLOOP 12 485#define LWSWC1_MAXLOOP 12
483 486
484void 487void
485mips_emul_lwc1(uint32_t inst, struct trapframe *tf, uint32_t cause) 488mips_emul_lwc1(uint32_t inst, struct trapframe *tf, uint32_t cause)
486{ 489{
487 intptr_t vaddr; 490 intptr_t vaddr;
488 int16_t offset; 491 int16_t offset;
489 void *t; 492 void *t;
490 mips_reg_t pc; 493 mips_reg_t pc;
491 int i; 494 int i;
492 495
493 offset = inst & 0xFFFF; 496 offset = inst & 0xFFFF;
494 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 497 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
495 498
496 /* segment and alignment check */ 499 /* segment and alignment check */
497 if (vaddr < 0 || (vaddr & 3)) { 500 if (vaddr < 0 || (vaddr & 3)) {
498 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 501 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
499 return; 502 return;
500 } 503 }
501 504
502 /* NewABI FIXME */ 505 /* NewABI FIXME */
503 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); 506 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
504 507
505 if (copyin((void *)vaddr, t, 4) != 0) { 508 if (copyin((void *)vaddr, t, 4) != 0) {
506 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 509 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
507 return; 510 return;
508 } 511 }
509 512
510 pc = tf->tf_regs[_R_PC]; 513 pc = tf->tf_regs[_R_PC];
511 update_pc(tf, cause); 514 update_pc(tf, cause);
512 515
513 if (cause & MIPS_CR_BR_DELAY) 516 if (cause & MIPS_CR_BR_DELAY)
514 return; 517 return;
515 518
516 for (i = 1; i < LWSWC1_MAXLOOP; i++) { 519 for (i = 1; i < LWSWC1_MAXLOOP; i++) {
517 if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) 520 if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc))
518 return; 521 return;
519 522
520 vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ 523 vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */
521 inst = mips_ufetch32((uint32_t *)vaddr); 524 inst = mips_ufetch32((uint32_t *)vaddr);
522 if (((InstFmt)inst).FRType.op != OP_LWC1) 525 if (((InstFmt)inst).FRType.op != OP_LWC1)
523 return; 526 return;
524 527
525 offset = inst & 0xFFFF; 528 offset = inst & 0xFFFF;
526 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 529 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
527 530
528 /* segment and alignment check */ 531 /* segment and alignment check */
529 if (vaddr < 0 || (vaddr & 3)) { 532 if (vaddr < 0 || (vaddr & 3)) {
530 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 533 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
531 return; 534 return;
532 } 535 }
533 536
534 /* NewABI FIXME */ 537 /* NewABI FIXME */
535 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); 538 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
536 539
537 if (copyin((void *)vaddr, t, 4) != 0) { 540 if (copyin((void *)vaddr, t, 4) != 0) {
538 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 541 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
539 return; 542 return;
540 } 543 }
541 544
542 pc = tf->tf_regs[_R_PC]; 545 pc = tf->tf_regs[_R_PC];
543 update_pc(tf, cause); 546 update_pc(tf, cause);
544 } 547 }
545} 548}
546 549
547void 550void
548mips_emul_ldc1(uint32_t inst, struct trapframe *tf, uint32_t cause) 551mips_emul_ldc1(uint32_t inst, struct trapframe *tf, uint32_t cause)
549{ 552{
550 intptr_t vaddr; 553 intptr_t vaddr;
551 int16_t offset; 554 int16_t offset;
552 void *t; 555 void *t;
553 556
554 offset = inst & 0xFFFF; 557 offset = inst & 0xFFFF;
555 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 558 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
556 559
557 /* segment and alignment check */ 560 /* segment and alignment check */
558 if (vaddr < 0 || (vaddr & 7)) { 561 if (vaddr < 0 || (vaddr & 7)) {
559 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 562 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
560 return; 563 return;
561 } 564 }
562 565
563 /* NewABI FIXME */ 566 /* NewABI FIXME */
564 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); 567 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]);
565 568
566 if (copyin((void *)vaddr, t, 8) != 0) { 569 if (copyin((void *)vaddr, t, 8) != 0) {
567 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 570 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
568 return; 571 return;
569 } 572 }
570 573
571 update_pc(tf, cause); 574 update_pc(tf, cause);
572} 575}
573 576
574void 577void
575mips_emul_swc1(uint32_t inst, struct trapframe *tf, uint32_t cause) 578mips_emul_swc1(uint32_t inst, struct trapframe *tf, uint32_t cause)
576{ 579{
577 intptr_t vaddr; 580 intptr_t vaddr;
578 int16_t offset; 581 int16_t offset;
579 void *t; 582 void *t;
580 mips_reg_t pc; 583 mips_reg_t pc;
581 int i; 584 int i;
582 585
583 offset = inst & 0xFFFF; 586 offset = inst & 0xFFFF;
584 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 587 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
585 588
586 /* segment and alignment check */ 589 /* segment and alignment check */
587 if (vaddr < 0 || (vaddr & 3)) { 590 if (vaddr < 0 || (vaddr & 3)) {
588 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 591 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
589 return; 592 return;
590 } 593 }
591 594
592 /* NewABI FIXME */ 595 /* NewABI FIXME */
593 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); 596 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
594 597
595 if (copyout(t, (void *)vaddr, 4) != 0) { 598 if (copyout(t, (void *)vaddr, 4) != 0) {
596 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 599 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
597 return; 600 return;
598 } 601 }
599 602
600 pc = tf->tf_regs[_R_PC]; 603 pc = tf->tf_regs[_R_PC];
601 update_pc(tf, cause); 604 update_pc(tf, cause);
602 605
603 if (cause & MIPS_CR_BR_DELAY) 606 if (cause & MIPS_CR_BR_DELAY)
604 return; 607 return;
605 608
606 for (i = 1; i < LWSWC1_MAXLOOP; i++) { 609 for (i = 1; i < LWSWC1_MAXLOOP; i++) {
607 if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc)) 610 if (mips_btop(tf->tf_regs[_R_PC]) != mips_btop(pc))
608 return; 611 return;
609 612
610 vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */ 613 vaddr = tf->tf_regs[_R_PC]; /* XXX truncates to 32 bits */
611 inst = mips_ufetch32((uint32_t *)vaddr); 614 inst = mips_ufetch32((uint32_t *)vaddr);
612 if (((InstFmt)inst).FRType.op != OP_SWC1) 615 if (((InstFmt)inst).FRType.op != OP_SWC1)
613 return; 616 return;
614 617
615 offset = inst & 0xFFFF; 618 offset = inst & 0xFFFF;
616 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 619 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
617 620
618 /* segment and alignment check */ 621 /* segment and alignment check */
619 if (vaddr < 0 || (vaddr & 3)) { 622 if (vaddr < 0 || (vaddr & 3)) {
620 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 623 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
621 return; 624 return;
622 } 625 }
623 626
624 /* NewABI FIXME */ 627 /* NewABI FIXME */
625 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]); 628 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
626 629
627 if (copyout(t, (void *)vaddr, 4) != 0) { 630 if (copyout(t, (void *)vaddr, 4) != 0) {
628 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 631 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
629 return; 632 return;
630 } 633 }
631 634
632 pc = tf->tf_regs[_R_PC]; 635 pc = tf->tf_regs[_R_PC];
633 update_pc(tf, cause); 636 update_pc(tf, cause);
634 } 637 }
635} 638}
636 639
637void 640void
638mips_emul_sdc1(uint32_t inst, struct trapframe *tf, uint32_t cause) 641mips_emul_sdc1(uint32_t inst, struct trapframe *tf, uint32_t cause)
639{ 642{
640 intptr_t vaddr; 643 intptr_t vaddr;
641 int16_t offset; 644 int16_t offset;
642 void *t; 645 void *t;
643 646
644 offset = inst & 0xFFFF; 647 offset = inst & 0xFFFF;
645 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 648 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
646 649
647 /* segment and alignment check */ 650 /* segment and alignment check */
648 if (vaddr < 0 || (vaddr & 7)) { 651 if (vaddr < 0 || (vaddr & 7)) {
649 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 652 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
650 return; 653 return;
651 } 654 }
652 655
653 /* NewABI FIXME */ 656 /* NewABI FIXME */
654 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]); 657 t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]);
655 658
656 if (copyout(t, (void *)vaddr, 8) != 0) { 659 if (copyout(t, (void *)vaddr, 8) != 0) {
657 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 660 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
658 return; 661 return;
659 } 662 }
660 663
661 update_pc(tf, cause); 664 update_pc(tf, cause);
662} 665}
663 666
664void 667void
665mips_emul_lb(uint32_t inst, struct trapframe *tf, uint32_t cause) 668mips_emul_lb(uint32_t inst, struct trapframe *tf, uint32_t cause)
666{ 669{
667 intptr_t vaddr; 670 intptr_t vaddr;
668 int16_t offset; 671 int16_t offset;
669 int8_t x; 672 int8_t x;
670 673
671 offset = inst & 0xFFFF; 674 offset = inst & 0xFFFF;
672 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 675 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
673 676
674 /* segment check */ 677 /* segment check */
675 if (vaddr < 0) { 678 if (vaddr < 0) {
676 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 679 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
677 return; 680 return;
678 } 681 }
679 682
680 if (copyin((void *)vaddr, &x, 1) != 0) { 683 if (copyin((void *)vaddr, &x, 1) != 0) {
681 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 684 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
682 return; 685 return;
683 } 686 }
684 687
685 tf->tf_regs[(inst>>16)&0x1F] = x; 688 tf->tf_regs[(inst>>16)&0x1F] = x;
686 689
687 update_pc(tf, cause); 690 update_pc(tf, cause);
688} 691}
689 692
690void 693void
691mips_emul_lbu(uint32_t inst, struct trapframe *tf, uint32_t cause) 694mips_emul_lbu(uint32_t inst, struct trapframe *tf, uint32_t cause)
692{ 695{
693 intptr_t vaddr; 696 intptr_t vaddr;
694 int16_t offset; 697 int16_t offset;
695 uint8_t x; 698 uint8_t x;
696 699
697 offset = inst & 0xFFFF; 700 offset = inst & 0xFFFF;
698 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 701 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
699 702
700 /* segment check */ 703 /* segment check */
701 if (vaddr < 0) { 704 if (vaddr < 0) {
702 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 705 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
703 return; 706 return;
704 } 707 }
705 708
706 if (copyin((void *)vaddr, &x, 1) != 0) { 709 if (copyin((void *)vaddr, &x, 1) != 0) {
707 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 710 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
708 return; 711 return;
709 } 712 }
710 713
711 tf->tf_regs[(inst>>16)&0x1F] = x; 714 tf->tf_regs[(inst>>16)&0x1F] = x;
712 715
713 update_pc(tf, cause); 716 update_pc(tf, cause);
714} 717}
715 718
716void 719void
717mips_emul_lh(uint32_t inst, struct trapframe *tf, uint32_t cause) 720mips_emul_lh(uint32_t inst, struct trapframe *tf, uint32_t cause)
718{ 721{
719 intptr_t vaddr; 722 intptr_t vaddr;
720 int16_t offset; 723 int16_t offset;
721 int16_t x; 724 int16_t x;
722 725
723 offset = inst & 0xFFFF; 726 offset = inst & 0xFFFF;
724 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 727 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
725 728
726 /* segment and alignment check */ 729 /* segment and alignment check */
727 if (vaddr < 0 || (vaddr & 1)) { 730 if (vaddr < 0 || (vaddr & 1)) {
728 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 731 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
729 return; 732 return;
730 } 733 }
731 734
732 if (copyin((void *)vaddr, &x, 2) != 0) { 735 if (copyin((void *)vaddr, &x, 2) != 0) {
733 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 736 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
734 return; 737 return;
735 } 738 }
736 739
737 tf->tf_regs[(inst>>16)&0x1F] = x; 740 tf->tf_regs[(inst>>16)&0x1F] = x;
738 741
739 update_pc(tf, cause); 742 update_pc(tf, cause);
740} 743}
741 744
742void 745void
743mips_emul_lhu(uint32_t inst, struct trapframe *tf, uint32_t cause) 746mips_emul_lhu(uint32_t inst, struct trapframe *tf, uint32_t cause)
744{ 747{
745 intptr_t vaddr; 748 intptr_t vaddr;
746 int16_t offset; 749 int16_t offset;
747 uint16_t x; 750 uint16_t x;
748 751
749 offset = inst & 0xFFFF; 752 offset = inst & 0xFFFF;
750 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 753 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
751 754
752 /* segment and alignment check */ 755 /* segment and alignment check */
753 if (vaddr < 0 || (vaddr & 1)) { 756 if (vaddr < 0 || (vaddr & 1)) {
754 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 757 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
755 return; 758 return;
756 } 759 }
757 760
758 if (copyin((void *)vaddr, &x, 2) != 0) { 761 if (copyin((void *)vaddr, &x, 2) != 0) {
759 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 762 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
760 return; 763 return;
761 } 764 }
762 765
763 tf->tf_regs[(inst>>16)&0x1F] = (mips_ureg_t)x; 766 tf->tf_regs[(inst>>16)&0x1F] = (mips_ureg_t)x;
764 767
765 update_pc(tf, cause); 768 update_pc(tf, cause);
766} 769}
767 770
768void 771void
769mips_emul_lw(uint32_t inst, struct trapframe *tf, uint32_t cause) 772mips_emul_lw(uint32_t inst, struct trapframe *tf, uint32_t cause)
770{ 773{
771 intptr_t vaddr; 774 intptr_t vaddr;
772 int16_t offset; 775 int16_t offset;
773 int32_t x; 776 int32_t x;
774 777
775 offset = inst & 0xFFFF; 778 offset = inst & 0xFFFF;
776 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 779 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
777 780
778 /* segment and alignment check */ 781 /* segment and alignment check */
779 if (vaddr < 0 || (vaddr & 3)) { 782 if (vaddr < 0 || (vaddr & 3)) {
780 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 783 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
781 return; 784 return;
782 } 785 }
783 786
784 if (copyin((void *)vaddr, &x, 4) != 0) { 787 if (copyin((void *)vaddr, &x, 4) != 0) {
785 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 788 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
786 return; 789 return;
787 } 790 }
788 791
789 tf->tf_regs[(inst>>16)&0x1F] = x; 792 tf->tf_regs[(inst>>16)&0x1F] = x;
790 793
791 update_pc(tf, cause); 794 update_pc(tf, cause);
792} 795}
793 796
794void 797void
795mips_emul_lwl(uint32_t inst, struct trapframe *tf, uint32_t cause) 798mips_emul_lwl(uint32_t inst, struct trapframe *tf, uint32_t cause)
796{ 799{
797 intptr_t vaddr; 800 intptr_t vaddr;
798 uint32_t a, x, shift; 801 uint32_t a, x, shift;
799 int16_t offset; 802 int16_t offset;
800 803
801 offset = inst & 0xFFFF; 804 offset = inst & 0xFFFF;
802 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 805 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
803 806
804 /* segment check */ 807 /* segment check */
805 if (vaddr < 0) { 808 if (vaddr < 0) {
806 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 809 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
807 return; 810 return;
808 } 811 }
809 812
810 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { 813 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
811 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 814 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
812 return; 815 return;
813 } 816 }
814 817
815 x = tf->tf_regs[(inst>>16)&0x1F]; 818 x = tf->tf_regs[(inst>>16)&0x1F];
816 819
817 shift = (3 - (vaddr & 0x00000003)) * 8; 820 shift = (3 - (vaddr & 0x00000003)) * 8;
818 a <<= shift; 821 a <<= shift;
819 x &= ~(0xFFFFFFFFUL << shift); 822 x &= ~(0xFFFFFFFFUL << shift);
820 x |= a; 823 x |= a;
821 824
822 tf->tf_regs[(inst>>16)&0x1F] = x; 825 tf->tf_regs[(inst>>16)&0x1F] = x;
823 826
824 update_pc(tf, cause); 827 update_pc(tf, cause);
825} 828}
826 829
827void 830void
828mips_emul_lwr(uint32_t inst, struct trapframe *tf, uint32_t cause) 831mips_emul_lwr(uint32_t inst, struct trapframe *tf, uint32_t cause)
829{ 832{
830 intptr_t vaddr; 833 intptr_t vaddr;
831 uint32_t a, x, shift; 834 uint32_t a, x, shift;
832 int16_t offset; 835 int16_t offset;
833 836
834 offset = inst & 0xFFFF; 837 offset = inst & 0xFFFF;
835 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 838 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
836 839
837 /* segment check */ 840 /* segment check */
838 if (vaddr & 0x80000000) { 841 if (vaddr & 0x80000000) {
839 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 842 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
840 return; 843 return;
841 } 844 }
842 845
843 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { 846 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
844 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 847 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
845 return; 848 return;
846 } 849 }
847 850
848 x = tf->tf_regs[(inst>>16)&0x1F]; 851 x = tf->tf_regs[(inst>>16)&0x1F];
849 852
850 shift = (vaddr & 0x00000003) * 8; 853 shift = (vaddr & 0x00000003) * 8;
851 a >>= shift; 854 a >>= shift;
852 x &= ~(0xFFFFFFFFUL >> shift); 855 x &= ~(0xFFFFFFFFUL >> shift);
853 x |= a; 856 x |= a;
854 857
855 tf->tf_regs[(inst>>16)&0x1F] = x; 858 tf->tf_regs[(inst>>16)&0x1F] = x;
856 859
857 update_pc(tf, cause); 860 update_pc(tf, cause);
858} 861}
859 862
860#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) 863#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
861void 864void
862mips_emul_lwu(uint32_t inst, struct trapframe *tf, uint32_t cause) 865mips_emul_lwu(uint32_t inst, struct trapframe *tf, uint32_t cause)
863{ 866{
864 intptr_t vaddr; 867 intptr_t vaddr;
865 int16_t offset; 868 int16_t offset;
866 uint32_t x; 869 uint32_t x;
867 870
868 offset = inst & 0xFFFF; 871 offset = inst & 0xFFFF;
869 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 872 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
870 873
871 /* segment and alignment check */ 874 /* segment and alignment check */
872 if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) { 875 if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
873 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 876 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
874 return; 877 return;
875 } 878 }
876 879
877 if (copyin((void *)vaddr, &x, 4) != 0) { 880 if (copyin((void *)vaddr, &x, 4) != 0) {
878 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 881 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
879 return; 882 return;
880 } 883 }
881 884
882 tf->tf_regs[(inst>>16)&0x1F] = x; 885 tf->tf_regs[(inst>>16)&0x1F] = x;
883 886
884 update_pc(tf, cause); 887 update_pc(tf, cause);
885} 888}
886 889
887void 890void
888mips_emul_ld(uint32_t inst, struct trapframe *tf, uint32_t cause) 891mips_emul_ld(uint32_t inst, struct trapframe *tf, uint32_t cause)
889{ 892{
890 intptr_t vaddr; 893 intptr_t vaddr;
891 int16_t offset; 894 int16_t offset;
892 895
893 offset = inst & 0xFFFF; 896 offset = inst & 0xFFFF;
894 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 897 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
895 898
896 /* segment and alignment check */ 899 /* segment and alignment check */
897 if (vaddr > VM_MAX_ADDRESS || vaddr & 0x7) { 900 if (vaddr > VM_MAX_ADDRESS || vaddr & 0x7) {
898 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 901 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
899 return; 902 return;
900 } 903 }
901 904
902 if (copyin((void *)vaddr, &(tf->tf_regs[(inst>>16)&0x1F]), 8) != 0) { 905 if (copyin((void *)vaddr, &(tf->tf_regs[(inst>>16)&0x1F]), 8) != 0) {
903 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 906 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
904 return; 907 return;
905 } 908 }
906 909
907 update_pc(tf, cause); 910 update_pc(tf, cause);
908} 911}
909 912
910void 913void
911mips_emul_ldl(uint32_t inst, struct trapframe *tf, uint32_t cause) 914mips_emul_ldl(uint32_t inst, struct trapframe *tf, uint32_t cause)
912{ 915{
913 intptr_t vaddr; 916 intptr_t vaddr;
914 uint64_t a, x; 917 uint64_t a, x;
915 uint32_t shift; 918 uint32_t shift;
916 int16_t offset; 919 int16_t offset;
917 920
918 offset = inst & 0xFFFF; 921 offset = inst & 0xFFFF;
919 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 922 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
920 923
921 /* segment check */ 924 /* segment check */
922 if (vaddr & 0x80000000) { 925 if (vaddr & 0x80000000) {
923 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 926 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
924 return; 927 return;
925 } 928 }
926 929
927 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { 930 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
928 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 931 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
929 return; 932 return;
930 } 933 }
931 934
932 x = tf->tf_regs[(inst>>16)&0x1F]; 935 x = tf->tf_regs[(inst>>16)&0x1F];
933 936
934 shift = (7 - (vaddr & 0x7)) * 8; 937 shift = (7 - (vaddr & 0x7)) * 8;
935 a <<= shift; 938 a <<= shift;
936 x &= ~(~(uint64_t)0UL << shift); 939 x &= ~(~(uint64_t)0UL << shift);
937 x |= a; 940 x |= a;
938 941
939 tf->tf_regs[(inst>>16)&0x1F] = x; 942 tf->tf_regs[(inst>>16)&0x1F] = x;
940 943
941 update_pc(tf, cause); 944 update_pc(tf, cause);
942} 945}
943 946
944void 947void
945mips_emul_ldr(uint32_t inst, struct trapframe *tf, uint32_t cause) 948mips_emul_ldr(uint32_t inst, struct trapframe *tf, uint32_t cause)
946{ 949{
947 intptr_t vaddr; 950 intptr_t vaddr;
948 uint64_t a, x; 951 uint64_t a, x;
949 uint32_t shift; 952 uint32_t shift;
950 int16_t offset; 953 int16_t offset;
951 954
952 offset = inst & 0xFFFF; 955 offset = inst & 0xFFFF;
953 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 956 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
954 957
955 /* segment check */ 958 /* segment check */
956 if (vaddr < 0) { 959 if (vaddr < 0) {
957 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause); 960 send_sigsegv(vaddr, T_ADDR_ERR_LD, tf, cause);
958 return; 961 return;
959 } 962 }
960 963
961 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { 964 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
962 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause); 965 send_sigsegv(vaddr, T_TLB_LD_MISS, tf, cause);
963 return; 966 return;
964 } 967 }
965 968
966 x = tf->tf_regs[(inst>>16)&0x1F]; 969 x = tf->tf_regs[(inst>>16)&0x1F];
967 970
968 shift = (vaddr & 0x7) * 8; 971 shift = (vaddr & 0x7) * 8;
969 a >>= shift; 972 a >>= shift;
970 x &= ~(~(uint64_t)0UL >> shift); 973 x &= ~(~(uint64_t)0UL >> shift);
971 x |= a; 974 x |= a;
972 975
973 tf->tf_regs[(inst>>16)&0x1F] = x; 976 tf->tf_regs[(inst>>16)&0x1F] = x;
974 977
975 update_pc(tf, cause); 978 update_pc(tf, cause);
976} 979}
977#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ 980#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */
978 981
979void 982void
980mips_emul_sb(uint32_t inst, struct trapframe *tf, uint32_t cause) 983mips_emul_sb(uint32_t inst, struct trapframe *tf, uint32_t cause)
981{ 984{
982 intptr_t vaddr; 985 intptr_t vaddr;
983 int16_t offset; 986 int16_t offset;
984 987
985 offset = inst & 0xFFFF; 988 offset = inst & 0xFFFF;
986 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 989 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
987 990
988 /* segment check */ 991 /* segment check */
989 if (vaddr < 0) { 992 if (vaddr < 0) {
990 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 993 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
991 return; 994 return;
992 } 995 }
993 996
994 if (ustore_8((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { 997 if (ustore_8((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) {
995 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 998 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
996 return; 999 return;
997 } 1000 }
998 1001
999 update_pc(tf, cause); 1002 update_pc(tf, cause);
1000} 1003}
1001 1004
1002void 1005void
1003mips_emul_sh(uint32_t inst, struct trapframe *tf, uint32_t cause) 1006mips_emul_sh(uint32_t inst, struct trapframe *tf, uint32_t cause)
1004{ 1007{
1005 intptr_t vaddr; 1008 intptr_t vaddr;
1006 int16_t offset; 1009 int16_t offset;
1007 1010
1008 offset = inst & 0xFFFF; 1011 offset = inst & 0xFFFF;
1009 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1012 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1010 1013
1011 /* segment and alignment check */ 1014 /* segment and alignment check */
1012 if (vaddr < 0 || vaddr & 1) { 1015 if (vaddr < 0 || vaddr & 1) {
1013 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1016 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1014 return; 1017 return;
1015 } 1018 }
1016 1019
1017 if (ustore_16((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { 1020 if (ustore_16((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) {
1018 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1021 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1019 return; 1022 return;
1020 } 1023 }
1021 1024
1022 update_pc(tf, cause); 1025 update_pc(tf, cause);
1023} 1026}
1024 1027
1025void 1028void
1026mips_emul_sw(uint32_t inst, struct trapframe *tf, uint32_t cause) 1029mips_emul_sw(uint32_t inst, struct trapframe *tf, uint32_t cause)
1027{ 1030{
1028 intptr_t vaddr; 1031 intptr_t vaddr;
1029 int16_t offset; 1032 int16_t offset;
1030 1033
1031 offset = inst & 0xFFFF; 1034 offset = inst & 0xFFFF;
1032 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1035 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1033 1036
1034 /* segment and alignment check */ 1037 /* segment and alignment check */
1035 if (vaddr < 0 || (vaddr & 3)) { 1038 if (vaddr < 0 || (vaddr & 3)) {
1036 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1039 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1037 return; 1040 return;
1038 } 1041 }
1039 1042
1040 if (ustore_32((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) { 1043 if (ustore_32((void *)vaddr, tf->tf_regs[(inst>>16)&0x1F]) != 0) {
1041 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1044 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1042 return; 1045 return;
1043 } 1046 }
1044 1047
1045 update_pc(tf, cause); 1048 update_pc(tf, cause);
1046} 1049}
1047 1050
1048void 1051void
1049mips_emul_swl(uint32_t inst, struct trapframe *tf, uint32_t cause) 1052mips_emul_swl(uint32_t inst, struct trapframe *tf, uint32_t cause)
1050{ 1053{
1051 intptr_t vaddr; 1054 intptr_t vaddr;
1052 uint32_t a, x, shift; 1055 uint32_t a, x, shift;
1053 int16_t offset; 1056 int16_t offset;
1054 1057
1055 offset = inst & 0xFFFF; 1058 offset = inst & 0xFFFF;
1056 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1059 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1057 1060
1058 /* segment check */ 1061 /* segment check */
1059 if (vaddr < 0) { 1062 if (vaddr < 0) {
1060 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1063 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1061 return; 1064 return;
1062 } 1065 }
1063 1066
1064 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { 1067 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
1065 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1068 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1066 return; 1069 return;
1067 } 1070 }
1068 1071
1069 x = tf->tf_regs[(inst>>16)&0x1F]; 1072 x = tf->tf_regs[(inst>>16)&0x1F];
1070 1073
1071 shift = (3 - (vaddr & 3)) * 8; 1074 shift = (3 - (vaddr & 3)) * 8;
1072 x >>= shift; 1075 x >>= shift;
1073 a &= ~(0xFFFFFFFFUL >> shift); 1076 a &= ~(0xFFFFFFFFUL >> shift);
1074 a |= x; 1077 a |= x;
1075 1078
1076 if (ustore_32((void *)vaddr, a) != 0) { 1079 if (ustore_32((void *)vaddr, a) != 0) {
1077 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1080 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1078 return; 1081 return;
1079 } 1082 }
1080 1083
1081 update_pc(tf, cause); 1084 update_pc(tf, cause);
1082} 1085}
1083 1086
1084void 1087void
1085mips_emul_swr(uint32_t inst, struct trapframe *tf, uint32_t cause) 1088mips_emul_swr(uint32_t inst, struct trapframe *tf, uint32_t cause)
1086{ 1089{
1087 intptr_t vaddr; 1090 intptr_t vaddr;
1088 uint32_t a, x, shift; 1091 uint32_t a, x, shift;
1089 int16_t offset; 1092 int16_t offset;
1090 1093
1091 offset = inst & 0xFFFF; 1094 offset = inst & 0xFFFF;
1092 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1095 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1093 1096
1094 /* segment check */ 1097 /* segment check */
1095 if (vaddr < 0) { 1098 if (vaddr < 0) {
1096 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1099 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1097 return; 1100 return;
1098 } 1101 }
1099 1102
1100 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) { 1103 if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
1101 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1104 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1102 return; 1105 return;
1103 } 1106 }
1104 1107
1105 x = tf->tf_regs[(inst>>16)&0x1F]; 1108 x = tf->tf_regs[(inst>>16)&0x1F];
1106 1109
1107 shift = (vaddr & 3) * 8; 1110 shift = (vaddr & 3) * 8;
1108 x <<= shift; 1111 x <<= shift;
1109 a &= ~(0xFFFFFFFFUL << shift); 1112 a &= ~(0xFFFFFFFFUL << shift);
1110 a |= x; 1113 a |= x;
1111 1114
1112 if (ustore_32((void *)vaddr, a) != 0) { 1115 if (ustore_32((void *)vaddr, a) != 0) {
1113 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1116 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1114 return; 1117 return;
1115 } 1118 }
1116 1119
1117 update_pc(tf, cause); 1120 update_pc(tf, cause);
1118} 1121}
1119 1122
1120#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) 1123#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
1121void 1124void
1122mips_emul_sd(uint32_t inst, struct trapframe *tf, uint32_t cause) 1125mips_emul_sd(uint32_t inst, struct trapframe *tf, uint32_t cause)
1123{ 1126{
1124 intptr_t vaddr; 1127 intptr_t vaddr;
1125 int16_t offset; 1128 int16_t offset;
1126 1129
1127 offset = inst & 0xFFFF; 1130 offset = inst & 0xFFFF;
1128 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1131 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1129 1132
1130 /* segment and alignment check */ 1133 /* segment and alignment check */
1131 if (vaddr < 0 || vaddr & 0x7) { 1134 if (vaddr < 0 || vaddr & 0x7) {
1132 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1135 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1133 return; 1136 return;
1134 } 1137 }
1135 1138
1136 if (copyout((void *)vaddr, &tf->tf_regs[(inst>>16)&0x1F], 8) < 0) { 1139 if (copyout((void *)vaddr, &tf->tf_regs[(inst>>16)&0x1F], 8) < 0) {
1137 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1140 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1138 return; 1141 return;
1139 } 1142 }
1140 1143
1141 update_pc(tf, cause); 1144 update_pc(tf, cause);
1142} 1145}
1143 1146
1144void 1147void
1145mips_emul_sdl(uint32_t inst, struct trapframe *tf, uint32_t cause) 1148mips_emul_sdl(uint32_t inst, struct trapframe *tf, uint32_t cause)
1146{ 1149{
1147 intptr_t vaddr; 1150 intptr_t vaddr;
1148 uint64_t a, x; 1151 uint64_t a, x;
1149 uint32_t shift; 1152 uint32_t shift;
1150 int16_t offset; 1153 int16_t offset;
1151 1154
1152 offset = inst & 0xFFFF; 1155 offset = inst & 0xFFFF;
1153 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1156 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1154 1157
1155 /* segment check */ 1158 /* segment check */
1156 if (vaddr < 0) { 1159 if (vaddr < 0) {
1157 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1160 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1158 return; 1161 return;
1159 } 1162 }
1160 1163
1161 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { 1164 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
1162 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1165 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1163 return; 1166 return;
1164 } 1167 }
1165 1168
1166 x = tf->tf_regs[(inst>>16)&0x1F]; 1169 x = tf->tf_regs[(inst>>16)&0x1F];
1167 1170
1168 shift = (7 - (vaddr & 7)) * 8; 1171 shift = (7 - (vaddr & 7)) * 8;
1169 x >>= shift; 1172 x >>= shift;
1170 a &= ~(~(uint64_t)0U >> shift); 1173 a &= ~(~(uint64_t)0U >> shift);
1171 a |= x; 1174 a |= x;
1172 1175
1173 if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { 1176 if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) {
1174 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1177 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1175 return; 1178 return;
1176 } 1179 }
1177 1180
1178 update_pc(tf, cause); 1181 update_pc(tf, cause);
1179} 1182}
1180 1183
1181void 1184void
1182mips_emul_sdr(uint32_t inst, struct trapframe *tf, uint32_t cause) 1185mips_emul_sdr(uint32_t inst, struct trapframe *tf, uint32_t cause)
1183{ 1186{
1184 intptr_t vaddr; 1187 intptr_t vaddr;
1185 uint64_t a, x; 1188 uint64_t a, x;
1186 uint32_t shift; 1189 uint32_t shift;
1187 int16_t offset; 1190 int16_t offset;
1188 1191
1189 offset = inst & 0xFFFF; 1192 offset = inst & 0xFFFF;
1190 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset; 1193 vaddr = tf->tf_regs[(inst>>21)&0x1F] + offset;
1191 1194
1192 /* segment check */ 1195 /* segment check */
1193 if (vaddr < 0) { 1196 if (vaddr < 0) {
1194 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause); 1197 send_sigsegv(vaddr, T_ADDR_ERR_ST, tf, cause);
1195 return; 1198 return;
1196 } 1199 }
1197 1200
1198 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) { 1201 if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
1199 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1202 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1200 return; 1203 return;
1201 } 1204 }
1202 1205
1203 x = tf->tf_regs[(inst>>16)&0x1F]; 1206 x = tf->tf_regs[(inst>>16)&0x1F];
1204 1207
1205 shift = (vaddr & 7) * 8; 1208 shift = (vaddr & 7) * 8;
1206 x <<= shift; 1209 x <<= shift;
1207 a &= ~(~(uint64_t)0U << shift); 1210 a &= ~(~(uint64_t)0U << shift);
1208 a |= x; 1211 a |= x;
1209 1212
1210 if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) { 1213 if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) {
1211 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause); 1214 send_sigsegv(vaddr, T_TLB_ST_MISS, tf, cause);
1212 return; 1215 return;
1213 } 1216 }
1214 1217
1215 update_pc(tf, cause); 1218 update_pc(tf, cause);
1216} 1219}
1217#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */ 1220#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */
1218#endif /* defined(FPEMUL) */ 1221#endif /* defined(FPEMUL) */