support.S revision 327195
1286441Srpaulo/* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */ 2286441Srpaulo/*- 3286441Srpaulo * Copyright (c) 1992, 1993 4286441Srpaulo * The Regents of the University of California. All rights reserved. 5286441Srpaulo * 6286441Srpaulo * This code is derived from software contributed to Berkeley by 7286441Srpaulo * Digital Equipment Corporation and Ralph Campbell. 8286441Srpaulo * 9286441Srpaulo * Redistribution and use in source and binary forms, with or without 10286441Srpaulo * modification, are permitted provided that the following conditions 11286441Srpaulo * are met: 12286441Srpaulo * 1. Redistributions of source code must retain the above copyright 13286441Srpaulo * notice, this list of conditions and the following disclaimer. 14286441Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 15286441Srpaulo * notice, this list of conditions and the following disclaimer in the 16286441Srpaulo * documentation and/or other materials provided with the distribution. 17286441Srpaulo * 4. Neither the name of the University nor the names of its contributors 18286441Srpaulo * may be used to endorse or promote products derived from this software 19286441Srpaulo * without specific prior written permission. 20286441Srpaulo * 21286441Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22286441Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23286441Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24286441Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25286441Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26286441Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27286441Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28286441Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29286441Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30286441Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31286441Srpaulo * SUCH DAMAGE. 32286441Srpaulo * 33286441Srpaulo * Copyright (C) 1989 Digital Equipment Corporation. 34286441Srpaulo * Permission to use, copy, modify, and distribute this software and 35286441Srpaulo * its documentation for any purpose and without fee is hereby granted, 36286441Srpaulo * provided that the above copyright notice appears in all copies. 37286441Srpaulo * Digital Equipment Corporation makes no representations about the 38286441Srpaulo * suitability of this software for any purpose. It is provided "as is" 39286441Srpaulo * without express or implied warranty. 40286441Srpaulo * 41286441Srpaulo * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 42286441Srpaulo * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 43286441Srpaulo * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 44286441Srpaulo * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 45286441Srpaulo * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 46286441Srpaulo * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 47286441Srpaulo * 48286441Srpaulo * from: @(#)locore.s 8.5 (Berkeley) 1/4/94 49286441Srpaulo * JNPR: support.S,v 1.5.2.2 2007/08/29 10:03:49 girish 50286441Srpaulo * $FreeBSD: stable/11/sys/mips/mips/support.S 327195 2017-12-26 10:07:17Z kib $ 51286441Srpaulo */ 52286441Srpaulo 53286441Srpaulo/* 54286441Srpaulo * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) 55286441Srpaulo * All rights reserved. 56286441Srpaulo * 57286441Srpaulo * Redistribution and use in source and binary forms, with or without 58286441Srpaulo * modification, are permitted provided that the following conditions 59286441Srpaulo * are met: 60286441Srpaulo * 1. Redistributions of source code must retain the above copyright 61286441Srpaulo * notice, this list of conditions and the following disclaimer. 62286441Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 63286441Srpaulo * notice, this list of conditions and the following disclaimer in the 64286441Srpaulo * documentation and/or other materials provided with the distribution. 65286441Srpaulo * 3. All advertising materials mentioning features or use of this software 66286441Srpaulo * must display the following acknowledgement: 67286441Srpaulo * This product includes software developed by Jonathan R. Stone for 68286441Srpaulo * the NetBSD Project. 69286441Srpaulo * 4. The name of the author may not be used to endorse or promote products 70286441Srpaulo * derived from this software without specific prior written permission. 71286441Srpaulo * 72286441Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 73286441Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 74286441Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 75286441Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 76286441Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 77286441Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 78286441Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 79286441Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 80286441Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 81286441Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 82286441Srpaulo * SUCH DAMAGE. 83286441Srpaulo */ 84286441Srpaulo 85286441Srpaulo/* 86286441Srpaulo * Contains assembly language support routines. 87286441Srpaulo */ 88286441Srpaulo 89286441Srpaulo#include "opt_ddb.h" 90286441Srpaulo#include <sys/errno.h> 91286441Srpaulo#include <machine/asm.h> 92286441Srpaulo#include <machine/cpu.h> 93286441Srpaulo#include <machine/regnum.h> 94286441Srpaulo#include <machine/cpuregs.h> 95286441Srpaulo#include <machine/pcb.h> 96286441Srpaulo 97286441Srpaulo#include "assym.s" 98286441Srpaulo 99286441Srpaulo .set noreorder # Noreorder is default style! 100286441Srpaulo 101286441Srpaulo/* 102286441Srpaulo * Primitives 103286441Srpaulo */ 104286441Srpaulo 105286441Srpaulo .text 106286441Srpaulo 107286441Srpaulo/* 108286441Srpaulo * See if access to addr with a len type instruction causes a machine check. 109286441Srpaulo * len is length of access (1=byte, 2=short, 4=int) 110286441Srpaulo * 111286441Srpaulo * badaddr(addr, len) 112286441Srpaulo * char *addr; 113286441Srpaulo * int len; 114286441Srpaulo */ 115286441SrpauloLEAF(badaddr) 116286441Srpaulo PTR_LA v0, baderr 117286441Srpaulo GET_CPU_PCPU(v1) 118286441Srpaulo PTR_L v1, PC_CURPCB(v1) 119286441Srpaulo bne a1, 1, 2f 120286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 121286441Srpaulo b 5f 122286441Srpaulo lbu v0, (a0) 123286441Srpaulo2: 124286441Srpaulo bne a1, 2, 4f 125286441Srpaulo nop 126286441Srpaulo b 5f 127286441Srpaulo lhu v0, (a0) 128286441Srpaulo4: 129286441Srpaulo lw v0, (a0) 130286441Srpaulo5: 131286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 132286441Srpaulo j ra 133286441Srpaulo move v0, zero # made it w/o errors 134286441Srpaulobaderr: 135286441Srpaulo j ra 136286441Srpaulo li v0, 1 # trap sends us here 137286441SrpauloEND(badaddr) 138286441Srpaulo 139286441Srpaulo/* 140286441Srpaulo * int copystr(void *kfaddr, void *kdaddr, size_t maxlen, size_t *lencopied) 141286441Srpaulo * Copy a NIL-terminated string, at most maxlen characters long. Return the 142286441Srpaulo * number of characters copied (including the NIL) in *lencopied. If the 143286441Srpaulo * string is too long, return ENAMETOOLONG; else return 0. 144286441Srpaulo */ 145286441SrpauloLEAF(copystr) 146286441Srpaulo move t0, a2 147286441Srpaulo beq a2, zero, 4f 148286441Srpaulo1: 149286441Srpaulo lbu v0, 0(a0) 150286441Srpaulo PTR_SUBU a2, a2, 1 151286475Srpaulo beq v0, zero, 2f 152286475Srpaulo sb v0, 0(a1) # each byte until NIL 153286475Srpaulo PTR_ADDU a0, a0, 1 154286475Srpaulo bne a2, zero, 1b # less than maxlen 155286475Srpaulo PTR_ADDU a1, a1, 1 156286475Srpaulo4: 157286475Srpaulo li v0, ENAMETOOLONG # run out of space 158286475Srpaulo2: 159286475Srpaulo beq a3, zero, 3f # return num. of copied bytes 160286475Srpaulo PTR_SUBU a2, t0, a2 # if the 4th arg was non-NULL 161286475Srpaulo PTR_S a2, 0(a3) 162286441Srpaulo3: 163286475Srpaulo j ra # v0 is 0 or ENAMETOOLONG 164286441Srpaulo nop 165286441SrpauloEND(copystr) 166286441Srpaulo 167286441Srpaulo 168286441Srpaulo/* 169298877Savos * Copy a null terminated string from the user address space into 170286441Srpaulo * the kernel address space. 171286441Srpaulo * 172286441Srpaulo * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 173286441Srpaulo * caddr_t fromaddr; 174286441Srpaulo * caddr_t toaddr; 175298877Savos * u_int maxlength; 176298877Savos * u_int *lencopied; 177298877Savos */ 178286441SrpauloNESTED(copyinstr, CALLFRAME_SIZ, ra) 179286441Srpaulo PTR_SUBU sp, sp, CALLFRAME_SIZ 180286441Srpaulo .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 181286441Srpaulo PTR_LA v0, copyerr 182286441Srpaulo blt a0, zero, _C_LABEL(copyerr) # make sure address is in user space 183286441Srpaulo REG_S ra, CALLFRAME_RA(sp) 184286441Srpaulo GET_CPU_PCPU(v1) 185286441Srpaulo PTR_L v1, PC_CURPCB(v1) 186286441Srpaulo jal _C_LABEL(copystr) 187286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 188286441Srpaulo REG_L ra, CALLFRAME_RA(sp) 189286441Srpaulo GET_CPU_PCPU(v1) 190286441Srpaulo PTR_L v1, PC_CURPCB(v1) 191286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 192286441Srpaulo j ra 193286441Srpaulo PTR_ADDU sp, sp, CALLFRAME_SIZ 194286441SrpauloEND(copyinstr) 195286441Srpaulo 196286441Srpaulo/* 197286441Srpaulo * Copy a null terminated string from the kernel address space into 198286441Srpaulo * the user address space. 199286441Srpaulo * 200286441Srpaulo * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 201286441Srpaulo * caddr_t fromaddr; 202286441Srpaulo * caddr_t toaddr; 203286441Srpaulo * u_int maxlength; 204286441Srpaulo * u_int *lencopied; 205286441Srpaulo */ 206286441SrpauloNESTED(copyoutstr, CALLFRAME_SIZ, ra) 207286441Srpaulo PTR_SUBU sp, sp, CALLFRAME_SIZ 208286441Srpaulo .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 209286441Srpaulo PTR_LA v0, copyerr 210286441Srpaulo blt a1, zero, _C_LABEL(copyerr) # make sure address is in user space 211286441Srpaulo REG_S ra, CALLFRAME_RA(sp) 212286441Srpaulo GET_CPU_PCPU(v1) 213286441Srpaulo PTR_L v1, PC_CURPCB(v1) 214286441Srpaulo jal _C_LABEL(copystr) 215286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 216286441Srpaulo REG_L ra, CALLFRAME_RA(sp) 217286441Srpaulo GET_CPU_PCPU(v1) 218286441Srpaulo PTR_L v1, PC_CURPCB(v1) 219286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 220286441Srpaulo j ra 221286441Srpaulo PTR_ADDU sp, sp, CALLFRAME_SIZ 222286441SrpauloEND(copyoutstr) 223286441Srpaulo 224286441Srpaulo/* 225286441Srpaulo * Copy specified amount of data from user space into the kernel 226286441Srpaulo * copyin(from, to, len) 227286441Srpaulo * caddr_t *from; (user source address) 228286441Srpaulo * caddr_t *to; (kernel destination address) 229286441Srpaulo * unsigned len; 230286441Srpaulo */ 231286441SrpauloNESTED(copyin, CALLFRAME_SIZ, ra) 232286441Srpaulo PTR_SUBU sp, sp, CALLFRAME_SIZ 233286441Srpaulo .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 234286441Srpaulo PTR_LA v0, copyerr 235286441Srpaulo blt a0, zero, _C_LABEL(copyerr) # make sure address is in user space 236286441Srpaulo REG_S ra, CALLFRAME_RA(sp) 237286441Srpaulo GET_CPU_PCPU(v1) 238286441Srpaulo PTR_L v1, PC_CURPCB(v1) 239286441Srpaulo jal _C_LABEL(bcopy) 240286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 241286441Srpaulo REG_L ra, CALLFRAME_RA(sp) 242286441Srpaulo GET_CPU_PCPU(v1) 243286441Srpaulo PTR_L v1, PC_CURPCB(v1) # bcopy modified v1, so reload 244286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 245286441Srpaulo PTR_ADDU sp, sp, CALLFRAME_SIZ 246286441Srpaulo j ra 247298877Savos move v0, zero 248298877SavosEND(copyin) 249298877Savos 250298877Savos/* 251298877Savos * Copy specified amount of data from kernel to the user space 252298877Savos * copyout(from, to, len) 253286441Srpaulo * caddr_t *from; (kernel source address) 254286441Srpaulo * caddr_t *to; (user destination address) 255286441Srpaulo * unsigned len; 256286441Srpaulo */ 257286441SrpauloNESTED(copyout, CALLFRAME_SIZ, ra) 258286441Srpaulo PTR_SUBU sp, sp, CALLFRAME_SIZ 259286441Srpaulo .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 260286441Srpaulo PTR_LA v0, copyerr 261286441Srpaulo blt a1, zero, _C_LABEL(copyerr) # make sure address is in user space 262286441Srpaulo REG_S ra, CALLFRAME_RA(sp) 263286441Srpaulo GET_CPU_PCPU(v1) 264286441Srpaulo PTR_L v1, PC_CURPCB(v1) 265286441Srpaulo jal _C_LABEL(bcopy) 266286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 267286441Srpaulo REG_L ra, CALLFRAME_RA(sp) 268286441Srpaulo GET_CPU_PCPU(v1) 269286441Srpaulo PTR_L v1, PC_CURPCB(v1) # bcopy modified v1, so reload 270286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 271286441Srpaulo PTR_ADDU sp, sp, CALLFRAME_SIZ 272286441Srpaulo j ra 273286441Srpaulo move v0, zero 274286441SrpauloEND(copyout) 275286441Srpaulo 276286441SrpauloLEAF(copyerr) 277286441Srpaulo REG_L ra, CALLFRAME_RA(sp) 278286441Srpaulo PTR_ADDU sp, sp, CALLFRAME_SIZ 279286441Srpaulo j ra 280293100Savos li v0, EFAULT # return error 281286441SrpauloEND(copyerr) 282286441Srpaulo 283286441Srpaulo/* 284286441Srpaulo * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to 285286441Srpaulo * user text space. 286286441Srpaulo * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to 287286441Srpaulo * user data space. 288286441Srpaulo */ 289286441Srpaulo#ifdef __mips_n64 290286441SrpauloLEAF(fuword64) 291286441SrpauloXLEAF(fuword) 292286441Srpaulo PTR_LA v0, fswberr 293286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 294286441Srpaulo nop 295286441Srpaulo GET_CPU_PCPU(v1) 296286441Srpaulo PTR_L v1, PC_CURPCB(v1) 297286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 298286441Srpaulo ld v0, 0(a0) # fetch word 299286441Srpaulo j ra 300286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 301286441SrpauloEND(fuword64) 302286441Srpaulo#endif 303286441Srpaulo 304286441SrpauloLEAF(fuword32) 305286441Srpaulo#ifndef __mips_n64 306286441SrpauloXLEAF(fuword) 307286441Srpaulo#endif 308286441Srpaulo PTR_LA v0, fswberr 309286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 310286441Srpaulo nop 311286441Srpaulo GET_CPU_PCPU(v1) 312286441Srpaulo PTR_L v1, PC_CURPCB(v1) 313286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 314286441Srpaulo lw v0, 0(a0) # fetch word 315286441Srpaulo j ra 316286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 317286441SrpauloEND(fuword32) 318286441Srpaulo 319286441SrpauloLEAF(fusword) 320286441Srpaulo PTR_LA v0, fswberr 321286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 322287197Sglebius nop 323287197Sglebius GET_CPU_PCPU(v1) 324287197Sglebius PTR_L v1, PC_CURPCB(v1) 325286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 326287197Sglebius lhu v0, 0(a0) # fetch short 327286441Srpaulo j ra 328286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 329286441SrpauloEND(fusword) 330286441Srpaulo 331286441SrpauloLEAF(fubyte) 332286441Srpaulo PTR_LA v0, fswberr 333286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 334286441Srpaulo nop 335286441Srpaulo GET_CPU_PCPU(v1) 336286441Srpaulo PTR_L v1, PC_CURPCB(v1) 337286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 338286441Srpaulo lbu v0, 0(a0) # fetch byte 339286441Srpaulo j ra 340286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 341286441SrpauloEND(fubyte) 342286441Srpaulo 343286441SrpauloLEAF(suword32) 344286441Srpaulo#ifndef __mips_n64 345286441SrpauloXLEAF(suword) 346286441Srpaulo#endif 347286441Srpaulo PTR_LA v0, fswberr 348286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 349286441Srpaulo nop 350286441Srpaulo GET_CPU_PCPU(v1) 351286441Srpaulo PTR_L v1, PC_CURPCB(v1) 352286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 353286441Srpaulo sw a1, 0(a0) # store word 354286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 355286441Srpaulo j ra 356286441Srpaulo move v0, zero 357286441SrpauloEND(suword32) 358286441Srpaulo 359286441Srpaulo#ifdef __mips_n64 360286441SrpauloLEAF(suword64) 361286441SrpauloXLEAF(suword) 362286441Srpaulo PTR_LA v0, fswberr 363286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 364286441Srpaulo nop 365286441Srpaulo GET_CPU_PCPU(v1) 366286441Srpaulo PTR_L v1, PC_CURPCB(v1) 367286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 368286441Srpaulo sd a1, 0(a0) # store word 369286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 370286441Srpaulo j ra 371286441Srpaulo move v0, zero 372286441SrpauloEND(suword64) 373286441Srpaulo#endif 374286441Srpaulo 375286441Srpaulo/* 376286441Srpaulo * casuword(9) 377286441Srpaulo * <v0>u_long casuword(<a0>u_long *p, <a1>u_long oldval, <a2>u_long newval) 378286441Srpaulo */ 379286441Srpaulo/* 380286441Srpaulo * casuword32(9) 381286441Srpaulo * <v0>uint32_t casuword(<a0>uint32_t *p, <a1>uint32_t oldval, 382286441Srpaulo * <a2>uint32_t newval) 383286441Srpaulo */ 384286441SrpauloLEAF(casuword32) 385286441Srpaulo#ifndef __mips_n64 386286441SrpauloXLEAF(casuword) 387286441Srpaulo#endif 388286441Srpaulo PTR_LA v0, fswberr 389286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 390286441Srpaulo nop 391286441Srpaulo GET_CPU_PCPU(v1) 392286441Srpaulo PTR_L v1, PC_CURPCB(v1) 393286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 394286441Srpaulo1: 395286441Srpaulo move t0, a2 396286441Srpaulo ll v0, 0(a0) 397286441Srpaulo bne a1, v0, 2f 398286441Srpaulo nop 399286441Srpaulo sc t0, 0(a0) # store word 400286441Srpaulo beqz t0, 1b 401286441Srpaulo nop 402286441Srpaulo j 3f 403286441Srpaulo nop 404286441Srpaulo2: 405286441Srpaulo li v0, -1 406286441Srpaulo3: 407286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 408286441Srpaulo jr ra 409286441Srpaulo nop 410286441SrpauloEND(casuword32) 411286441Srpaulo 412286441Srpaulo#ifdef __mips_n64 413286441SrpauloLEAF(casuword64) 414286441SrpauloXLEAF(casuword) 415286441Srpaulo PTR_LA v0, fswberr 416286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 417286441Srpaulo nop 418286441Srpaulo GET_CPU_PCPU(v1) 419286441Srpaulo PTR_L v1, PC_CURPCB(v1) 420286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 421286441Srpaulo1: 422286441Srpaulo move t0, a2 423286441Srpaulo lld v0, 0(a0) 424286441Srpaulo bne a1, v0, 2f 425286441Srpaulo nop 426286441Srpaulo scd t0, 0(a0) # store double word 427286441Srpaulo beqz t0, 1b 428286441Srpaulo nop 429286441Srpaulo j 3f 430286441Srpaulo nop 431286441Srpaulo2: 432286441Srpaulo li v0, -1 433293177Savos3: 434293177Savos PTR_S zero, U_PCB_ONFAULT(v1) 435286441Srpaulo jr ra 436286441Srpaulo nop 437286441SrpauloEND(casuword64) 438286441Srpaulo#endif 439286441Srpaulo 440286441Srpaulo/* 441286441Srpaulo * Will have to flush the instruction cache if byte merging is done in hardware. 442286441Srpaulo */ 443286441SrpauloLEAF(susword) 444286441Srpaulo PTR_LA v0, fswberr 445286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 446286441Srpaulo nop 447286441Srpaulo GET_CPU_PCPU(v1) 448286441Srpaulo PTR_L v1, PC_CURPCB(v1) 449286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 450286441Srpaulo sh a1, 0(a0) # store short 451286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 452286441Srpaulo j ra 453286441Srpaulo move v0, zero 454286441SrpauloEND(susword) 455286441Srpaulo 456286441SrpauloLEAF(subyte) 457286441Srpaulo PTR_LA v0, fswberr 458286441Srpaulo blt a0, zero, fswberr # make sure address is in user space 459293177Savos nop 460286441Srpaulo GET_CPU_PCPU(v1) 461286441Srpaulo PTR_L v1, PC_CURPCB(v1) 462286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 463286441Srpaulo sb a1, 0(a0) # store byte 464293177Savos PTR_S zero, U_PCB_ONFAULT(v1) 465286441Srpaulo j ra 466286441Srpaulo move v0, zero 467286441SrpauloEND(subyte) 468293177Savos 469286441SrpauloLEAF(fswberr) 470286441Srpaulo j ra 471286441Srpaulo li v0, -1 472286441SrpauloEND(fswberr) 473286441Srpaulo 474286441Srpaulo/* 475293177Savos * fuswintr and suswintr are just like fusword and susword except that if 476286441Srpaulo * the page is not in memory or would cause a trap, then we return an error. 477286441Srpaulo * The important thing is to prevent sleep() and switch(). 478286441Srpaulo */ 479286441SrpauloLEAF(fuswintr) 480286441Srpaulo PTR_LA v0, fswintrberr 481293177Savos blt a0, zero, fswintrberr # make sure address is in user space 482293177Savos nop 483286441Srpaulo GET_CPU_PCPU(v1) 484286441Srpaulo PTR_L v1, PC_CURPCB(v1) 485286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 486286441Srpaulo lhu v0, 0(a0) # fetch short 487286441Srpaulo j ra 488286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 489286441SrpauloEND(fuswintr) 490286441Srpaulo 491286441SrpauloLEAF(suswintr) 492293177Savos PTR_LA v0, fswintrberr 493286441Srpaulo blt a0, zero, fswintrberr # make sure address is in user space 494286441Srpaulo nop 495286441Srpaulo GET_CPU_PCPU(v1) 496286441Srpaulo PTR_L v1, PC_CURPCB(v1) 497286441Srpaulo PTR_S v0, U_PCB_ONFAULT(v1) 498286441Srpaulo sh a1, 0(a0) # store short 499286441Srpaulo PTR_S zero, U_PCB_ONFAULT(v1) 500286441Srpaulo j ra 501286441Srpaulo move v0, zero 502286441SrpauloEND(suswintr) 503286441Srpaulo 504286441SrpauloLEAF(fswintrberr) 505286441Srpaulo j ra 506286441Srpaulo li v0, -1 507286441SrpauloEND(fswintrberr) 508286441Srpaulo 509286441Srpaulo/* 510286441Srpaulo * memset(void *s1, int c, int len) 511286441Srpaulo * NetBSD: memset.S,v 1.3 2001/10/16 15:40:53 uch Exp 512286441Srpaulo */ 513286441SrpauloLEAF(memset) 514286441Srpaulo .set noreorder 515286441Srpaulo blt a2, 12, memsetsmallclr # small amount to clear? 516286441Srpaulo move v0, a0 # save s1 for result 517286441Srpaulo 518286441Srpaulo sll t1, a1, 8 # compute c << 8 in t1 519286441Srpaulo or t1, t1, a1 # compute c << 8 | c in 11 520286441Srpaulo sll t2, t1, 16 # shift that left 16 521286441Srpaulo or t1, t2, t1 # or together 522286441Srpaulo 523286441Srpaulo PTR_SUBU t0, zero, a0 # compute # bytes to word align address 524286441Srpaulo and t0, t0, 3 525286441Srpaulo beq t0, zero, 1f # skip if word aligned 526286441Srpaulo PTR_SUBU a2, a2, t0 # subtract from remaining count 527286441Srpaulo SWHI t1, 0(a0) # store 1, 2, or 3 bytes to align 528286441Srpaulo PTR_ADDU a0, a0, t0 529286441Srpaulo1: 530286441Srpaulo and v1, a2, 3 # compute number of whole words left 531286441Srpaulo PTR_SUBU t0, a2, v1 532286441Srpaulo PTR_SUBU a2, a2, t0 533286441Srpaulo PTR_ADDU t0, t0, a0 # compute ending address 534286441Srpaulo2: 535286441Srpaulo PTR_ADDU a0, a0, 4 # clear words 536286441Srpaulo bne a0, t0, 2b # unrolling loop does not help 537286441Srpaulo sw t1, -4(a0) # since we are limited by memory speed 538286441Srpaulo 539286441Srpaulomemsetsmallclr: 540286441Srpaulo ble a2, zero, 2f 541286441Srpaulo PTR_ADDU t0, a2, a0 # compute ending address 542286441Srpaulo1: 543286441Srpaulo PTR_ADDU a0, a0, 1 # clear bytes 544286441Srpaulo bne a0, t0, 1b 545286441Srpaulo sb a1, -1(a0) 546286441Srpaulo2: 547286441Srpaulo j ra 548286441Srpaulo nop 549286441Srpaulo .set reorder 550286441SrpauloEND(memset) 551286441Srpaulo 552286441Srpaulo/* 553286441Srpaulo * bzero(s1, n) 554286441Srpaulo */ 555286441SrpauloLEAF(bzero) 556286441SrpauloXLEAF(blkclr) 557286441Srpaulo .set noreorder 558286441Srpaulo blt a1, 12, smallclr # small amount to clear? 559286441Srpaulo PTR_SUBU a3, zero, a0 # compute # bytes to word align address 560286441Srpaulo and a3, a3, 3 561286441Srpaulo beq a3, zero, 1f # skip if word aligned 562286441Srpaulo PTR_SUBU a1, a1, a3 # subtract from remaining count 563286441Srpaulo SWHI zero, 0(a0) # clear 1, 2, or 3 bytes to align 564286441Srpaulo PTR_ADDU a0, a0, a3 565286441Srpaulo1: 566286441Srpaulo and v0, a1, 3 # compute number of words left 567286441Srpaulo PTR_SUBU a3, a1, v0 568286441Srpaulo move a1, v0 569286441Srpaulo PTR_ADDU a3, a3, a0 # compute ending address 570286441Srpaulo2: 571286441Srpaulo PTR_ADDU a0, a0, 4 # clear words 572286441Srpaulo bne a0, a3, 2b # unrolling loop does not help 573286441Srpaulo sw zero, -4(a0) # since we are limited by memory speed 574286441Srpaulosmallclr: 575286441Srpaulo ble a1, zero, 2f 576286441Srpaulo PTR_ADDU a3, a1, a0 # compute ending address 577286441Srpaulo1: 578286441Srpaulo PTR_ADDU a0, a0, 1 # clear bytes 579286441Srpaulo bne a0, a3, 1b 580286441Srpaulo sb zero, -1(a0) 581286441Srpaulo2: 582286441Srpaulo j ra 583286441Srpaulo nop 584286441SrpauloEND(bzero) 585286441Srpaulo 586286441Srpaulo 587286441Srpaulo/* 588286441Srpaulo * bcmp(s1, s2, n) 589286441Srpaulo */ 590286441SrpauloLEAF(bcmp) 591286441Srpaulo .set noreorder 592286441Srpaulo blt a2, 16, smallcmp # is it worth any trouble? 593286441Srpaulo xor v0, a0, a1 # compare low two bits of addresses 594286441Srpaulo and v0, v0, 3 595286441Srpaulo PTR_SUBU a3, zero, a1 # compute # bytes to word align address 596286441Srpaulo bne v0, zero, unalignedcmp # not possible to align addresses 597286441Srpaulo and a3, a3, 3 598286441Srpaulo 599286441Srpaulo beq a3, zero, 1f 600286441Srpaulo PTR_SUBU a2, a2, a3 # subtract from remaining count 601286441Srpaulo move v0, v1 # init v0,v1 so unmodified bytes match 602286441Srpaulo LWHI v0, 0(a0) # read 1, 2, or 3 bytes 603286441Srpaulo LWHI v1, 0(a1) 604286441Srpaulo PTR_ADDU a1, a1, a3 605286441Srpaulo bne v0, v1, nomatch 606286441Srpaulo PTR_ADDU a0, a0, a3 607286441Srpaulo1: 608286441Srpaulo and a3, a2, ~3 # compute number of whole words left 609286441Srpaulo PTR_SUBU a2, a2, a3 # which has to be >= (16-3) & ~3 610286441Srpaulo PTR_ADDU a3, a3, a0 # compute ending address 611286441Srpaulo2: 612286441Srpaulo lw v0, 0(a0) # compare words 613286441Srpaulo lw v1, 0(a1) 614286441Srpaulo PTR_ADDU a0, a0, 4 615286441Srpaulo bne v0, v1, nomatch 616286441Srpaulo PTR_ADDU a1, a1, 4 617286441Srpaulo bne a0, a3, 2b 618286441Srpaulo nop 619286441Srpaulo b smallcmp # finish remainder 620286441Srpaulo nop 621286441Srpaulounalignedcmp: 622286441Srpaulo beq a3, zero, 2f 623286441Srpaulo PTR_SUBU a2, a2, a3 # subtract from remaining count 624286441Srpaulo PTR_ADDU a3, a3, a0 # compute ending address 625286441Srpaulo1: 626286441Srpaulo lbu v0, 0(a0) # compare bytes until a1 word aligned 627286441Srpaulo lbu v1, 0(a1) 628286441Srpaulo PTR_ADDU a0, a0, 1 629286441Srpaulo bne v0, v1, nomatch 630286441Srpaulo PTR_ADDU a1, a1, 1 631286441Srpaulo bne a0, a3, 1b 632286441Srpaulo nop 633286441Srpaulo2: 634286441Srpaulo and a3, a2, ~3 # compute number of whole words left 635286441Srpaulo PTR_SUBU a2, a2, a3 # which has to be >= (16-3) & ~3 636286441Srpaulo PTR_ADDU a3, a3, a0 # compute ending address 637286441Srpaulo3: 638286441Srpaulo LWHI v0, 0(a0) # compare words a0 unaligned, a1 aligned 639286441Srpaulo LWLO v0, 3(a0) 640286441Srpaulo lw v1, 0(a1) 641286441Srpaulo PTR_ADDU a0, a0, 4 642286441Srpaulo bne v0, v1, nomatch 643286441Srpaulo PTR_ADDU a1, a1, 4 644286441Srpaulo bne a0, a3, 3b 645286441Srpaulo nop 646286441Srpaulosmallcmp: 647286441Srpaulo ble a2, zero, match 648286441Srpaulo PTR_ADDU a3, a2, a0 # compute ending address 649286441Srpaulo1: 650286441Srpaulo lbu v0, 0(a0) 651286441Srpaulo lbu v1, 0(a1) 652286441Srpaulo PTR_ADDU a0, a0, 1 653286441Srpaulo bne v0, v1, nomatch 654286441Srpaulo PTR_ADDU a1, a1, 1 655286441Srpaulo bne a0, a3, 1b 656286441Srpaulo nop 657286441Srpaulomatch: 658286441Srpaulo j ra 659286441Srpaulo move v0, zero 660286441Srpaulonomatch: 661286441Srpaulo j ra 662286441Srpaulo li v0, 1 663286441SrpauloEND(bcmp) 664286441Srpaulo 665286441Srpaulo 666286441Srpaulo/* 667286441Srpaulo * bit = ffs(value) 668286441Srpaulo */ 669286441SrpauloLEAF(ffs) 670286441Srpaulo .set noreorder 671286441Srpaulo beq a0, zero, 2f 672286441Srpaulo move v0, zero 673286441Srpaulo1: 674286441Srpaulo and v1, a0, 1 # bit set? 675286441Srpaulo addu v0, v0, 1 676286441Srpaulo beq v1, zero, 1b # no, continue 677286441Srpaulo srl a0, a0, 1 678286441Srpaulo2: 679286441Srpaulo j ra 680286441Srpaulo nop 681286441SrpauloEND(ffs) 682286441Srpaulo 683286441Srpaulo/** 684286441Srpaulo * void 685286441Srpaulo * atomic_set_16(u_int16_t *a, u_int16_t b) 686286441Srpaulo * { 687286441Srpaulo * *a |= b; 688286441Srpaulo * } 689286441Srpaulo */ 690286441SrpauloLEAF(atomic_set_16) 691293177Savos .set noreorder 692286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 693286441Srpaulo sll a0, a0, 2 694286441Srpaulo andi a1, a1, 0xffff 695286441Srpaulo1: 696286441Srpaulo ll t0, 0(a0) 697286441Srpaulo or t0, t0, a1 698286441Srpaulo sc t0, 0(a0) 699286441Srpaulo beq t0, zero, 1b 700286441Srpaulo nop 701286441Srpaulo j ra 702286441Srpaulo nop 703286441SrpauloEND(atomic_set_16) 704286441Srpaulo 705286441Srpaulo/** 706286441Srpaulo * void 707286441Srpaulo * atomic_clear_16(u_int16_t *a, u_int16_t b) 708286441Srpaulo * { 709286441Srpaulo * *a &= ~b; 710286441Srpaulo * } 711286441Srpaulo */ 712286441SrpauloLEAF(atomic_clear_16) 713286441Srpaulo .set noreorder 714286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 715286441Srpaulo sll a0, a0, 2 716286441Srpaulo nor a1, zero, a1 717286441Srpaulo1: 718286441Srpaulo ll t0, 0(a0) 719286441Srpaulo move t1, t0 720286441Srpaulo andi t1, t1, 0xffff # t1 has the original lower 16 bits 721286441Srpaulo and t1, t1, a1 # t1 has the new lower 16 bits 722286441Srpaulo srl t0, t0, 16 # preserve original top 16 bits 723286441Srpaulo sll t0, t0, 16 724289679Skevlo or t0, t0, t1 725286441Srpaulo sc t0, 0(a0) 726286441Srpaulo beq t0, zero, 1b 727286441Srpaulo nop 728286441Srpaulo j ra 729286441Srpaulo nop 730286441SrpauloEND(atomic_clear_16) 731286441Srpaulo 732286441Srpaulo 733286441Srpaulo/** 734286441Srpaulo * void 735286441Srpaulo * atomic_subtract_16(uint16_t *a, uint16_t b) 736286441Srpaulo * { 737286441Srpaulo * *a -= b; 738286441Srpaulo * } 739286441Srpaulo */ 740286441SrpauloLEAF(atomic_subtract_16) 741286441Srpaulo .set noreorder 742286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 743286441Srpaulo sll a0, a0, 2 744286441Srpaulo1: 745286441Srpaulo ll t0, 0(a0) 746286441Srpaulo move t1, t0 747286441Srpaulo andi t1, t1, 0xffff # t1 has the original lower 16 bits 748286441Srpaulo subu t1, t1, a1 749286441Srpaulo andi t1, t1, 0xffff # t1 has the new lower 16 bits 750286441Srpaulo srl t0, t0, 16 # preserve original top 16 bits 751286441Srpaulo sll t0, t0, 16 752286441Srpaulo or t0, t0, t1 753286441Srpaulo sc t0, 0(a0) 754286441Srpaulo beq t0, zero, 1b 755286441Srpaulo nop 756286441Srpaulo j ra 757286441Srpaulo nop 758286441SrpauloEND(atomic_subtract_16) 759286441Srpaulo 760286441Srpaulo/** 761286441Srpaulo * void 762286441Srpaulo * atomic_add_16(uint16_t *a, uint16_t b) 763286441Srpaulo * { 764286441Srpaulo * *a += b; 765286441Srpaulo * } 766286441Srpaulo */ 767286441SrpauloLEAF(atomic_add_16) 768286441Srpaulo .set noreorder 769286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 770286441Srpaulo sll a0, a0, 2 771286441Srpaulo1: 772286441Srpaulo ll t0, 0(a0) 773286441Srpaulo move t1, t0 774286441Srpaulo andi t1, t1, 0xffff # t1 has the original lower 16 bits 775286441Srpaulo addu t1, t1, a1 776286441Srpaulo andi t1, t1, 0xffff # t1 has the new lower 16 bits 777286441Srpaulo srl t0, t0, 16 # preserve original top 16 bits 778286441Srpaulo sll t0, t0, 16 779286441Srpaulo or t0, t0, t1 780286441Srpaulo sc t0, 0(a0) 781286441Srpaulo beq t0, zero, 1b 782286441Srpaulo nop 783286441Srpaulo j ra 784286441Srpaulo nop 785286441SrpauloEND(atomic_add_16) 786286441Srpaulo 787286441Srpaulo/** 788286441Srpaulo * void 789286441Srpaulo * atomic_add_8(uint8_t *a, uint8_t b) 790286441Srpaulo * { 791286441Srpaulo * *a += b; 792286441Srpaulo * } 793286441Srpaulo */ 794286441SrpauloLEAF(atomic_add_8) 795286441Srpaulo .set noreorder 796286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 797286441Srpaulo sll a0, a0, 2 798286441Srpaulo1: 799286441Srpaulo ll t0, 0(a0) 800286441Srpaulo move t1, t0 801286441Srpaulo andi t1, t1, 0xff # t1 has the original lower 8 bits 802286441Srpaulo addu t1, t1, a1 803286441Srpaulo andi t1, t1, 0xff # t1 has the new lower 8 bits 804286441Srpaulo srl t0, t0, 8 # preserve original top 24 bits 805286441Srpaulo sll t0, t0, 8 806286441Srpaulo or t0, t0, t1 807286441Srpaulo sc t0, 0(a0) 808286441Srpaulo beq t0, zero, 1b 809286441Srpaulo nop 810286441Srpaulo j ra 811286441Srpaulo nop 812286441SrpauloEND(atomic_add_8) 813286441Srpaulo 814286441Srpaulo 815286441Srpaulo/** 816286441Srpaulo * void 817286441Srpaulo * atomic_subtract_8(uint8_t *a, uint8_t b) 818286441Srpaulo * { 819286441Srpaulo * *a += b; 820286441Srpaulo * } 821286441Srpaulo */ 822286441SrpauloLEAF(atomic_subtract_8) 823286441Srpaulo .set noreorder 824286441Srpaulo srl a0, a0, 2 # round down address to be 32-bit aligned 825286441Srpaulo sll a0, a0, 2 826286441Srpaulo1: 827286441Srpaulo ll t0, 0(a0) 828286441Srpaulo move t1, t0 829286441Srpaulo andi t1, t1, 0xff # t1 has the original lower 8 bits 830286441Srpaulo subu t1, t1, a1 831286441Srpaulo andi t1, t1, 0xff # t1 has the new lower 8 bits 832286441Srpaulo srl t0, t0, 8 # preserve original top 24 bits 833286441Srpaulo sll t0, t0, 8 834286441Srpaulo or t0, t0, t1 835286441Srpaulo sc t0, 0(a0) 836286441Srpaulo beq t0, zero, 1b 837286441Srpaulo nop 838286441Srpaulo j ra 839286441Srpaulo nop 840286441SrpauloEND(atomic_subtract_8) 841286441Srpaulo 842286441Srpaulo .set noreorder # Noreorder is default style! 843286441Srpaulo 844286441Srpaulo#if defined(DDB) || defined(DEBUG) 845286441Srpaulo 846286441SrpauloLEAF(kdbpeek) 847286441Srpaulo PTR_LA v1, ddberr 848286441Srpaulo and v0, a0, 3 # unaligned ? 849286441Srpaulo GET_CPU_PCPU(t1) 850286441Srpaulo PTR_L t1, PC_CURPCB(t1) 851286441Srpaulo bne v0, zero, 1f 852286441Srpaulo PTR_S v1, U_PCB_ONFAULT(t1) 853286441Srpaulo 854286441Srpaulo lw v0, (a0) 855286441Srpaulo jr ra 856286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 857286441Srpaulo 858289679Skevlo1: 859286441Srpaulo LWHI v0, 0(a0) 860286441Srpaulo LWLO v0, 3(a0) 861286441Srpaulo jr ra 862286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 863286441SrpauloEND(kdbpeek) 864286441Srpaulo 865286441SrpauloLEAF(kdbpeekd) 866286441Srpaulo PTR_LA v1, ddberr 867286441Srpaulo and v0, a0, 3 # unaligned ? 868286441Srpaulo GET_CPU_PCPU(t1) 869286441Srpaulo PTR_L t1, PC_CURPCB(t1) 870286441Srpaulo bne v0, zero, 1f 871286441Srpaulo PTR_S v1, U_PCB_ONFAULT(t1) 872286441Srpaulo 873286441Srpaulo ld v0, (a0) 874286441Srpaulo jr ra 875286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 876286441Srpaulo 877286441Srpaulo1: 878286441Srpaulo REG_LHI v0, 0(a0) 879286441Srpaulo REG_LLO v0, 7(a0) 880286441Srpaulo jr ra 881286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 882286441SrpauloEND(kdbpeekd) 883286441Srpaulo 884286441Srpauloddberr: 885286441Srpaulo jr ra 886286441Srpaulo nop 887286441Srpaulo 888286441Srpaulo#if defined(DDB) 889286441SrpauloLEAF(kdbpoke) 890287965Sadrian PTR_LA v1, ddberr 891286441Srpaulo and v0, a0, 3 # unaligned ? 892287965Sadrian GET_CPU_PCPU(t1) 893286441Srpaulo PTR_L t1, PC_CURPCB(t1) 894286441Srpaulo bne v0, zero, 1f 895286441Srpaulo PTR_S v1, U_PCB_ONFAULT(t1) 896286441Srpaulo 897286441Srpaulo sw a1, (a0) 898286441Srpaulo jr ra 899286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 900286441Srpaulo 901286441Srpaulo1: 902286441Srpaulo SWHI a1, 0(a0) 903286441Srpaulo SWLO a1, 3(a0) 904286441Srpaulo jr ra 905286441Srpaulo PTR_S zero, U_PCB_ONFAULT(t1) 906286441SrpauloEND(kdbpoke) 907286441Srpaulo 908286441Srpaulo .data 909286441Srpaulo .globl esym 910286441Srpauloesym: .word 0 911286441Srpaulo 912286441Srpaulo#endif /* DDB */ 913286441Srpaulo#endif /* DDB || DEBUG */ 914286441Srpaulo 915286441Srpaulo .text 916286441SrpauloLEAF(breakpoint) 917286441Srpaulo break MIPS_BREAK_SOVER_VAL 918286441Srpaulo jr ra 919286441Srpaulo nop 920286441SrpauloEND(breakpoint) 921286441Srpaulo 922286441SrpauloLEAF(setjmp) 923286441Srpaulo mfc0 v0, MIPS_COP_0_STATUS # Later the "real" spl value! 924286441Srpaulo REG_S s0, (SZREG * PCB_REG_S0)(a0) 925286441Srpaulo REG_S s1, (SZREG * PCB_REG_S1)(a0) 926286441Srpaulo REG_S s2, (SZREG * PCB_REG_S2)(a0) 927286441Srpaulo REG_S s3, (SZREG * PCB_REG_S3)(a0) 928286441Srpaulo REG_S s4, (SZREG * PCB_REG_S4)(a0) 929286441Srpaulo REG_S s5, (SZREG * PCB_REG_S5)(a0) 930286441Srpaulo REG_S s6, (SZREG * PCB_REG_S6)(a0) 931286441Srpaulo REG_S s7, (SZREG * PCB_REG_S7)(a0) 932286441Srpaulo REG_S s8, (SZREG * PCB_REG_S8)(a0) 933286441Srpaulo REG_S sp, (SZREG * PCB_REG_SP)(a0) 934286441Srpaulo REG_S ra, (SZREG * PCB_REG_RA)(a0) 935286441Srpaulo REG_S v0, (SZREG * PCB_REG_SR)(a0) 936286441Srpaulo jr ra 937286441Srpaulo li v0, 0 # setjmp return 938286441SrpauloEND(setjmp) 939286441Srpaulo 940286441SrpauloLEAF(longjmp) 941286441Srpaulo REG_L v0, (SZREG * PCB_REG_SR)(a0) 942286441Srpaulo REG_L ra, (SZREG * PCB_REG_RA)(a0) 943286441Srpaulo REG_L s0, (SZREG * PCB_REG_S0)(a0) 944286441Srpaulo REG_L s1, (SZREG * PCB_REG_S1)(a0) 945286441Srpaulo REG_L s2, (SZREG * PCB_REG_S2)(a0) 946286441Srpaulo REG_L s3, (SZREG * PCB_REG_S3)(a0) 947286441Srpaulo REG_L s4, (SZREG * PCB_REG_S4)(a0) 948286441Srpaulo REG_L s5, (SZREG * PCB_REG_S5)(a0) 949286441Srpaulo REG_L s6, (SZREG * PCB_REG_S6)(a0) 950286441Srpaulo REG_L s7, (SZREG * PCB_REG_S7)(a0) 951286441Srpaulo REG_L s8, (SZREG * PCB_REG_S8)(a0) 952286441Srpaulo REG_L sp, (SZREG * PCB_REG_SP)(a0) 953286441Srpaulo mtc0 v0, MIPS_COP_0_STATUS # Later the "real" spl value! 954286441Srpaulo ITLBNOPFIX 955286441Srpaulo jr ra 956286441Srpaulo li v0, 1 # longjmp return 957286441SrpauloEND(longjmp) 958286441Srpaulo 959286441SrpauloLEAF(mips3_ld) 960286441Srpaulo .set push 961286441Srpaulo .set noreorder 962286441Srpaulo .set mips64 963293119Savos#if defined(__mips_o32) 964286441Srpaulo mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts 965286441Srpaulo and t1, t0, ~(MIPS_SR_INT_IE) 966286441Srpaulo mtc0 t1, MIPS_COP_0_STATUS 967286441Srpaulo COP0_SYNC 968286441Srpaulo nop 969286441Srpaulo nop 970286441Srpaulo nop 971286441Srpaulo 972286441Srpaulo ld v0, 0(a0) 973286441Srpaulo#if _BYTE_ORDER == _BIG_ENDIAN 974286441Srpaulo dsll v1, v0, 32 975286441Srpaulo dsra v1, v1, 32 # low word in v1 976286441Srpaulo dsra v0, v0, 32 # high word in v0 977286441Srpaulo#else 978286441Srpaulo dsra v1, v0, 32 # high word in v1 979286441Srpaulo dsll v0, v0, 32 980286441Srpaulo dsra v0, v0, 32 # low word in v0 981286441Srpaulo#endif 982286441Srpaulo 983286441Srpaulo mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 984286441Srpaulo COP0_SYNC 985286441Srpaulo nop 986286441Srpaulo#else /* !__mips_o32 */ 987286441Srpaulo ld v0, 0(a0) 988286441Srpaulo#endif /* !__mips_o32 */ 989286441Srpaulo 990286441Srpaulo jr ra 991286441Srpaulo nop 992286441Srpaulo .set pop 993286441SrpauloEND(mips3_ld) 994286441Srpaulo 995286441SrpauloLEAF(mips3_sd) 996286441Srpaulo .set push 997286441Srpaulo .set mips64 998286441Srpaulo .set noreorder 999286441Srpaulo#if defined(__mips_o32) 1000286441Srpaulo mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts 1001286441Srpaulo and t1, t0, ~(MIPS_SR_INT_IE) 1002286441Srpaulo mtc0 t1, MIPS_COP_0_STATUS 1003286441Srpaulo COP0_SYNC 1004286441Srpaulo nop 1005286441Srpaulo nop 1006286441Srpaulo nop 1007286441Srpaulo 1008286441Srpaulo # NOTE: a1 is padding! 1009286441Srpaulo 1010286441Srpaulo#if _BYTE_ORDER == _BIG_ENDIAN 1011286441Srpaulo dsll a2, a2, 32 # high word in a2 1012286441Srpaulo dsll a3, a3, 32 # low word in a3 1013286441Srpaulo dsrl a3, a3, 32 1014286441Srpaulo#else 1015286441Srpaulo dsll a2, a2, 32 # low word in a2 1016286441Srpaulo dsrl a2, a2, 32 1017286441Srpaulo dsll a3, a3, 32 # high word in a3 1018286441Srpaulo#endif 1019286441Srpaulo or a1, a2, a3 1020286441Srpaulo sd a1, 0(a0) 1021286441Srpaulo 1022286441Srpaulo mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 1023286441Srpaulo COP0_SYNC 1024286441Srpaulo nop 1025286441Srpaulo#else /* !__mips_o32 */ 1026286441Srpaulo sd a1, 0(a0) 1027286441Srpaulo#endif /* !__mips_o32 */ 1028286441Srpaulo 1029286441Srpaulo jr ra 1030286441Srpaulo nop 1031286441Srpaulo .set pop 1032286441SrpauloEND(mips3_sd) 1033286441Srpaulo