166458Sdfr/*- 266458Sdfr * Copyright (c) 1998 Doug Rabson 366458Sdfr * All rights reserved. 466458Sdfr * 566458Sdfr * Redistribution and use in source and binary forms, with or without 666458Sdfr * modification, are permitted provided that the following conditions 766458Sdfr * are met: 866458Sdfr * 1. Redistributions of source code must retain the above copyright 966458Sdfr * notice, this list of conditions and the following disclaimer. 1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1166458Sdfr * notice, this list of conditions and the following disclaimer in the 1266458Sdfr * documentation and/or other materials provided with the distribution. 1366458Sdfr * 1466458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1566458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1666458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1766458Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1866458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1966458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2066458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2166458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2266458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2366458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2466458Sdfr * SUCH DAMAGE. 2566458Sdfr * 2666458Sdfr * $FreeBSD$ 2766458Sdfr */ 28139790Simp/*- 2966458Sdfr * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 3066458Sdfr * All rights reserved. 3166458Sdfr * 3266458Sdfr * Author: Chris G. Demetriou 3366458Sdfr * 3466458Sdfr * Permission to use, copy, modify and distribute this software and 3566458Sdfr * its documentation is hereby granted, provided that both the copyright 3666458Sdfr * notice and this permission notice appear in all copies of the 3766458Sdfr * software, derivative works or modified versions, and any portions 3866458Sdfr * thereof, and that both notices appear in supporting documentation. 3966458Sdfr * 4066458Sdfr * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 4166458Sdfr * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 4266458Sdfr * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 4366458Sdfr * 4466458Sdfr * Carnegie Mellon requests users of this software to return to 4566458Sdfr * 4666458Sdfr * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 4766458Sdfr * School of Computer Science 4866458Sdfr * Carnegie Mellon University 4966458Sdfr * Pittsburgh PA 15213-3890 5066458Sdfr * 5166458Sdfr * any improvements or extensions that they make and grant Carnegie the 5266458Sdfr * rights to redistribute these changes. 5366458Sdfr */ 5466458Sdfr 5566458Sdfr#include <machine/asm.h> 5683893Sdfr#include <machine/ia64_cpu.h> 5766458Sdfr#include <assym.s> 5866458Sdfr 5966458Sdfr .text 6066458Sdfr 61115341SmarcelENTRY(fusufault, 0) 62115341Smarcel{ .mib 63115341Smarcel st8.rel [r15]=r0 // Clear onfault. 64115341Smarcel add ret0=-1,r0 65115341Smarcel br.ret.sptk rp 66115341Smarcel ;; 67115341Smarcel} 68115341SmarcelEND(fusufault) 69115341Smarcel 7066458Sdfr/* 71163449Sdavidxu * casuword(u_long *p, u_long old, u_long new) 72115341Smarcel * Perform a compare-exchange in user space. 7366458Sdfr */ 74163449SdavidxuENTRY(casuword, 3) 75115341Smarcel{ .mlx 76246715Smarcel ld8.acq r15=[r13] // r15 = curthread 77219741Smarcel movl r14=VM_MAXUSER_ADDRESS 78115341Smarcel ;; 79115341Smarcel} 80115341Smarcel{ .mib 81246715Smarcel add r15=TD_PCB,r15 82115341Smarcel cmp.geu p6,p0=in0,r14 83115341Smarcel(p6) br.dpnt.few 1f 84115341Smarcel ;; 85115341Smarcel} 86115341Smarcel{ .mlx 87246715Smarcel ld8 r15=[r15] // r15 = PCB 88115341Smarcel movl r14=fusufault 89115341Smarcel ;; 90115341Smarcel} 91115341Smarcel{ .mmi 92115341Smarcel mov ar.ccv=in1 93115341Smarcel add r15=PCB_ONFAULT,r15 94246715Smarcel nop 0 95115341Smarcel ;; 96115341Smarcel} 97115341Smarcel{ .mmi 98115341Smarcel st8 [r15]=r14 // Set onfault 99115341Smarcel ;; 100115341Smarcel cmpxchg8.rel ret0=[in0],in2,ar.ccv 101115341Smarcel nop 0 102115341Smarcel ;; 103115341Smarcel} 104204184Smarcel{ .mib 105115341Smarcel st8.rel [r15]=r0 // Clear onfault 106115341Smarcel nop 0 107115341Smarcel br.ret.sptk rp 108115341Smarcel ;; 109115341Smarcel} 110115341Smarcel1: 111204184Smarcel{ .mib 112115341Smarcel add ret0=-1,r0 113115341Smarcel nop 0 114115341Smarcel br.ret.sptk rp 115115341Smarcel ;; 116115341Smarcel} 117163449SdavidxuEND(casuword) 11866458Sdfr 119115341Smarcel/* 120163449Sdavidxu * casuword32(uint32_t *p, uint32_t old, uint32_t new) 121161675Sdavidxu * Perform a 32-bit compare-exchange in user space. 122161675Sdavidxu */ 123161675SdavidxuENTRY(casuword32, 3) 124161675Sdavidxu{ .mlx 125219741Smarcel movl r14=VM_MAXUSER_ADDRESS 126161675Sdavidxu ;; 127161675Sdavidxu} 128161675Sdavidxu{ .mib 129246715Smarcel ld8.acq r15=[r13] // r15 = curthread 130161675Sdavidxu cmp.geu p6,p0=in0,r14 131161675Sdavidxu(p6) br.dpnt.few 1f 132161675Sdavidxu ;; 133161675Sdavidxu} 134161675Sdavidxu{ .mlx 135161675Sdavidxu add r15=TD_PCB,r15 136161675Sdavidxu movl r14=fusufault 137161675Sdavidxu ;; 138161675Sdavidxu} 139161675Sdavidxu{ .mmi 140161675Sdavidxu ld8 r15=[r15] // r15 = PCB 141161675Sdavidxu ;; 142161675Sdavidxu mov ar.ccv=in1 143161675Sdavidxu add r15=PCB_ONFAULT,r15 144161675Sdavidxu ;; 145161675Sdavidxu} 146161675Sdavidxu{ .mmi 147161675Sdavidxu st8 [r15]=r14 // Set onfault 148161675Sdavidxu ;; 149161675Sdavidxu cmpxchg4.rel ret0=[in0],in2,ar.ccv 150161675Sdavidxu nop 0 151161675Sdavidxu ;; 152161675Sdavidxu} 153204184Smarcel{ .mib 154161675Sdavidxu st8.rel [r15]=r0 // Clear onfault 155161675Sdavidxu nop 0 156161675Sdavidxu br.ret.sptk rp 157161675Sdavidxu ;; 158161675Sdavidxu} 159161675Sdavidxu1: 160204184Smarcel{ .mib 161161675Sdavidxu add ret0=-1,r0 162161675Sdavidxu nop 0 163161675Sdavidxu br.ret.sptk rp 164161675Sdavidxu ;; 165161675Sdavidxu} 166161675SdavidxuEND(casuword32) 167161675Sdavidxu 168161675Sdavidxu/* 169115341Smarcel * subyte(void *addr, int byte) 170115341Smarcel * suword16(void *addr, int word) 171115341Smarcel * suword32(void *addr, int word) 172115341Smarcel * suword64|suword(void *addr, long word) 173115341Smarcel * Store in user space 174115341Smarcel */ 175115341Smarcel 176115341SmarcelENTRY(subyte, 2) 177115341Smarcel{ .mlx 178219741Smarcel movl r14=VM_MAXUSER_ADDRESS 17966633Sdfr ;; 180115341Smarcel} 181115341Smarcel{ .mib 182246715Smarcel ld8.acq r15=[r13] // r15 = curthread 183115341Smarcel cmp.geu p6,p0=in0,r14 184115341Smarcel(p6) br.dpnt.few 1f 18566633Sdfr ;; 186115341Smarcel} 187115341Smarcel{ .mlx 188115341Smarcel add r15=TD_PCB,r15 189115341Smarcel movl r14=fusufault 19066633Sdfr ;; 191115341Smarcel} 192115341Smarcel{ .mmi 193115341Smarcel ld8 r15=[r15] // r15 = PCB 19466633Sdfr ;; 195115341Smarcel nop 0 196115341Smarcel add r15=PCB_ONFAULT,r15 19766633Sdfr ;; 198115341Smarcel} 199115341Smarcel{ .mmi 200115341Smarcel st8 [r15]=r14 // Set onfault 20166633Sdfr ;; 202115341Smarcel st1.rel [in0]=in1 203115341Smarcel nop 0 20466633Sdfr ;; 205115341Smarcel} 206115341Smarcel{ .mib 207115341Smarcel st8.rel [r15]=r0 // Clear onfault 208115341Smarcel mov ret0=r0 209115341Smarcel br.ret.sptk rp 210115341Smarcel ;; 211115341Smarcel} 212115341Smarcel1: 213204184Smarcel{ .mib 214115341Smarcel add ret0=-1,r0 215115341Smarcel nop 0 216115341Smarcel br.ret.sptk rp 217115341Smarcel ;; 218115341Smarcel} 219115341SmarcelEND(subyte) 22066458Sdfr 221115341SmarcelENTRY(suword16, 2) 222115341Smarcel{ .mlx 223219741Smarcel movl r14=VM_MAXUSER_ADDRESS 224115341Smarcel ;; 225115341Smarcel} 226115341Smarcel{ .mib 227246715Smarcel ld8.acq r15=[r13] // r15 = curthread 228115341Smarcel cmp.geu p6,p0=in0,r14 229115341Smarcel(p6) br.dpnt.few 1f 230115341Smarcel ;; 231115341Smarcel} 232115341Smarcel{ .mlx 233115341Smarcel add r15=TD_PCB,r15 234115341Smarcel movl r14=fusufault 235115341Smarcel ;; 236115341Smarcel} 237115341Smarcel{ .mmi 238115341Smarcel ld8 r15=[r15] // r15 = PCB 239115341Smarcel ;; 240115341Smarcel nop 0 241115341Smarcel add r15=PCB_ONFAULT,r15 242115341Smarcel ;; 243115341Smarcel} 244115341Smarcel{ .mmi 245115341Smarcel st8 [r15]=r14 // Set onfault 246115341Smarcel ;; 247115341Smarcel st2.rel [in0]=in1 248115341Smarcel nop 0 249115341Smarcel ;; 250115341Smarcel} 251115341Smarcel{ .mib 252115341Smarcel st8.rel [r15]=r0 // Clear onfault 253115341Smarcel mov ret0=r0 254115341Smarcel br.ret.sptk rp 255115341Smarcel ;; 256115341Smarcel} 257115341Smarcel1: 258204184Smarcel{ .mib 259115341Smarcel add ret0=-1,r0 260115341Smarcel nop 0 261115341Smarcel br.ret.sptk rp 262115341Smarcel ;; 263115341Smarcel} 264115341SmarcelEND(suword16) 265115341Smarcel 26698473SpeterENTRY(suword32, 2) 267115341Smarcel{ .mlx 268219741Smarcel movl r14=VM_MAXUSER_ADDRESS 26994377Sdfr ;; 270115341Smarcel} 271115341Smarcel{ .mib 272246715Smarcel ld8.acq r15=[r13] // r15 = curthread 273115341Smarcel cmp.geu p6,p0=in0,r14 274115341Smarcel(p6) br.dpnt.few 1f 27594377Sdfr ;; 276115341Smarcel} 277115341Smarcel{ .mlx 278115341Smarcel add r15=TD_PCB,r15 279115341Smarcel movl r14=fusufault 28094377Sdfr ;; 281115341Smarcel} 282115341Smarcel{ .mmi 283115341Smarcel ld8 r15=[r15] // r15 = PCB 28494377Sdfr ;; 285115341Smarcel nop 0 286115341Smarcel add r15=PCB_ONFAULT,r15 28794377Sdfr ;; 288115341Smarcel} 289115341Smarcel{ .mmi 290115341Smarcel st8 [r15]=r14 // Set onfault 29194377Sdfr ;; 292115341Smarcel st4.rel [in0]=in1 293115341Smarcel nop 0 29494377Sdfr ;; 295115341Smarcel} 296115341Smarcel{ .mib 297115341Smarcel st8.rel [r15]=r0 // Clear onfault 298115341Smarcel mov ret0=r0 299115341Smarcel br.ret.sptk rp 300115341Smarcel ;; 301115341Smarcel} 302115341Smarcel1: 303204184Smarcel{ .mib 304115341Smarcel add ret0=-1,r0 305115341Smarcel nop 0 306115341Smarcel br.ret.sptk rp 307115341Smarcel ;; 308115341Smarcel} 30998473SpeterEND(suword32) 31066458Sdfr 311115341SmarcelENTRY(suword64, 2) 312115341SmarcelXENTRY(suword) 313115341Smarcel{ .mlx 314219741Smarcel movl r14=VM_MAXUSER_ADDRESS 31566633Sdfr ;; 316115341Smarcel} 317115341Smarcel{ .mib 318246715Smarcel ld8.acq r15=[r13] // r15 = curthread 319115341Smarcel cmp.geu p6,p0=in0,r14 320115341Smarcel(p6) br.dpnt.few 1f 32166633Sdfr ;; 322115341Smarcel} 323115341Smarcel{ .mlx 324115341Smarcel add r15=TD_PCB,r15 325115341Smarcel movl r14=fusufault 32666633Sdfr ;; 327115341Smarcel} 328115341Smarcel{ .mmi 329115341Smarcel ld8 r15=[r15] // r15 = PCB 33066633Sdfr ;; 331115341Smarcel nop 0 332115341Smarcel add r15=PCB_ONFAULT,r15 33366633Sdfr ;; 334115341Smarcel} 335115341Smarcel{ .mmi 336115341Smarcel st8 [r15]=r14 // Set onfault 33766633Sdfr ;; 338115341Smarcel st8.rel [in0]=in1 339115341Smarcel nop 0 34066633Sdfr ;; 341115341Smarcel} 342115341Smarcel{ .mib 343115341Smarcel st8.rel [r15]=r0 // Clear onfault 344115341Smarcel mov ret0=r0 345115341Smarcel br.ret.sptk rp 346115341Smarcel ;; 347115341Smarcel} 348115341Smarcel1: 349204184Smarcel{ .mib 350115341Smarcel add ret0=-1,r0 351115341Smarcel nop 0 352115341Smarcel br.ret.sptk rp 353115341Smarcel ;; 354115341Smarcel} 355115341SmarcelEND(suword64) 35666458Sdfr 357115341Smarcel/* 358115341Smarcel * fubyte(void *addr, int byte) 359115341Smarcel * fuword16(void *addr, int word) 360115341Smarcel * fuword32(void *addr, int word) 361115341Smarcel * fuword64|fuword(void *addr, long word) 362115341Smarcel * Fetch from user space 363115341Smarcel */ 36466458Sdfr 365115341SmarcelENTRY(fubyte, 1) 366115341Smarcel{ .mlx 367219741Smarcel movl r14=VM_MAXUSER_ADDRESS 368115341Smarcel ;; 369115341Smarcel} 370115341Smarcel{ .mib 371246715Smarcel ld8.acq r15=[r13] // r15 = curthread 372115341Smarcel cmp.geu p6,p0=in0,r14 373115341Smarcel(p6) br.dpnt.few 1f 374115341Smarcel ;; 375115341Smarcel} 376115341Smarcel{ .mlx 377115341Smarcel add r15=TD_PCB,r15 378115341Smarcel movl r14=fusufault 379115341Smarcel ;; 380115341Smarcel} 381115341Smarcel{ .mmi 382115341Smarcel ld8 r15=[r15] // r15 = PCB 383115341Smarcel ;; 384115341Smarcel nop 0 385115341Smarcel add r15=PCB_ONFAULT,r15 386115341Smarcel ;; 387115341Smarcel} 388115341Smarcel{ .mmi 389115341Smarcel st8 [r15]=r14 // Set onfault 390115341Smarcel ;; 391115341Smarcel mf 392115341Smarcel nop 0 393115341Smarcel ;; 394115341Smarcel} 395115341Smarcel{ .mmb 396115341Smarcel ld1 ret0=[in0] 397115341Smarcel st8.rel [r15]=r0 // Clear onfault 398115341Smarcel br.ret.sptk rp 399115341Smarcel ;; 400115341Smarcel} 401115341Smarcel1: 402204184Smarcel{ .mib 403115341Smarcel add ret0=-1,r0 404115341Smarcel nop 0 405115341Smarcel br.ret.sptk rp 406115341Smarcel ;; 407115341Smarcel} 408115341SmarcelEND(fubyte) 40966458Sdfr 410115341SmarcelENTRY(fuword16, 2) 411115341Smarcel{ .mlx 412219741Smarcel movl r14=VM_MAXUSER_ADDRESS 41366633Sdfr ;; 414115341Smarcel} 415115341Smarcel{ .mib 416246715Smarcel ld8.acq r15=[r13] // r15 = curthread 417115341Smarcel cmp.geu p6,p0=in0,r14 418115341Smarcel(p6) br.dpnt.few 1f 41966633Sdfr ;; 420115341Smarcel} 421115341Smarcel{ .mlx 422115341Smarcel add r15=TD_PCB,r15 423115341Smarcel movl r14=fusufault 42466633Sdfr ;; 425115341Smarcel} 426115341Smarcel{ .mmi 427115341Smarcel ld8 r15=[r15] // r15 = PCB 42866633Sdfr ;; 429115341Smarcel nop 0 430115341Smarcel add r15=PCB_ONFAULT,r15 43166633Sdfr ;; 432115341Smarcel} 433115341Smarcel{ .mmi 434115341Smarcel st8 [r15]=r14 // Set onfault 43566633Sdfr ;; 436115341Smarcel mf 437115341Smarcel nop 0 43866633Sdfr ;; 439115341Smarcel} 440115341Smarcel{ .mmb 441115341Smarcel ld2 ret0=[in0] 442115341Smarcel st8.rel [r15]=r0 // Clear onfault 443115341Smarcel br.ret.sptk rp 444115341Smarcel ;; 445115341Smarcel} 446115341Smarcel1: 447204184Smarcel{ .mib 448115341Smarcel add ret0=-1,r0 449115341Smarcel nop 0 450115341Smarcel br.ret.sptk rp 451115341Smarcel ;; 452115341Smarcel} 453115341SmarcelEND(fuword16) 45466458Sdfr 455115341SmarcelENTRY(fuword32, 2) 456115341Smarcel{ .mlx 457219741Smarcel movl r14=VM_MAXUSER_ADDRESS 45894377Sdfr ;; 459115341Smarcel} 460115341Smarcel{ .mib 461246715Smarcel ld8.acq r15=[r13] // r15 = curthread 462115341Smarcel cmp.geu p6,p0=in0,r14 463115341Smarcel(p6) br.dpnt.few 1f 46494377Sdfr ;; 465115341Smarcel} 466115341Smarcel{ .mlx 467115341Smarcel add r15=TD_PCB,r15 468115341Smarcel movl r14=fusufault 46994377Sdfr ;; 470115341Smarcel} 471115341Smarcel{ .mmi 472115341Smarcel ld8 r15=[r15] // r15 = PCB 47394377Sdfr ;; 474115341Smarcel nop 0 475115341Smarcel add r15=PCB_ONFAULT,r15 47694377Sdfr ;; 477115341Smarcel} 478115341Smarcel{ .mmi 479115341Smarcel st8 [r15]=r14 // Set onfault 48094377Sdfr ;; 481115341Smarcel mf 482115341Smarcel nop 0 48394377Sdfr ;; 484115341Smarcel} 485115341Smarcel{ .mmb 486115341Smarcel ld4 ret0=[in0] 487115341Smarcel st8.rel [r15]=r0 // Clear onfault 488115341Smarcel br.ret.sptk rp 489115341Smarcel ;; 490115341Smarcel} 491115341Smarcel1: 492204184Smarcel{ .mib 493115341Smarcel add ret0=-1,r0 494115341Smarcel nop 0 495115341Smarcel br.ret.sptk rp 496115341Smarcel ;; 497115341Smarcel} 49898473SpeterEND(fuword32) 49994377Sdfr 500115341SmarcelENTRY(fuword64, 2) 501115341SmarcelXENTRY(fuword) 502115341Smarcel{ .mlx 503219741Smarcel movl r14=VM_MAXUSER_ADDRESS 50466633Sdfr ;; 505115341Smarcel} 506115341Smarcel{ .mib 507246715Smarcel ld8.acq r15=[r13] // r15 = curthread 508115341Smarcel cmp.geu p6,p0=in0,r14 509115341Smarcel(p6) br.dpnt.few 1f 51066633Sdfr ;; 511115341Smarcel} 512115341Smarcel{ .mlx 513115341Smarcel add r15=TD_PCB,r15 514115341Smarcel movl r14=fusufault 51566633Sdfr ;; 516115341Smarcel} 517115341Smarcel{ .mmi 518115341Smarcel ld8 r15=[r15] // r15 = PCB 51966633Sdfr ;; 520115341Smarcel nop 0 521115341Smarcel add r15=PCB_ONFAULT,r15 52266633Sdfr ;; 523115341Smarcel} 524115341Smarcel{ .mmi 525115341Smarcel st8 [r15]=r14 // Set onfault 52666633Sdfr ;; 527115341Smarcel mf 528115341Smarcel nop 0 52966633Sdfr ;; 530115341Smarcel} 531115341Smarcel{ .mmb 532115341Smarcel ld8 ret0=[in0] 533115341Smarcel st8.rel [r15]=r0 // Clear onfault 534115341Smarcel br.ret.sptk rp 535115341Smarcel ;; 536115341Smarcel} 537115341Smarcel1: 538204184Smarcel{ .mib 539115341Smarcel add ret0=-1,r0 540115341Smarcel nop 0 541115341Smarcel br.ret.sptk rp 542115341Smarcel ;; 543115341Smarcel} 544115341SmarcelEND(fuword64) 54566458Sdfr 546115341Smarcel/* 547115341Smarcel * fuswintr(void *addr) 548115341Smarcel * suswintr(void *addr) 549115341Smarcel */ 550115341Smarcel 551115341SmarcelENTRY(fuswintr, 1) 552204184Smarcel{ .mib 553115341Smarcel add ret0=-1,r0 554115341Smarcel nop 0 555115341Smarcel br.ret.sptk rp 556115341Smarcel ;; 557115341Smarcel} 558115341SmarcelEND(fuswintr) 559115341Smarcel 560115341SmarcelENTRY(suswintr, 0) 561204184Smarcel{ .mib 562115341Smarcel add ret0=-1,r0 563115341Smarcel nop 0 564115341Smarcel br.ret.sptk rp 565115341Smarcel ;; 566115341Smarcel} 567115341SmarcelEND(suswintr) 568115341Smarcel 56966458Sdfr/**************************************************************************/ 57066458Sdfr 57166458Sdfr/* 57266458Sdfr * Copy a null-terminated string within the kernel's address space. 57366458Sdfr * If lenp is not NULL, store the number of chars copied in *lenp 57466458Sdfr * 57566458Sdfr * int copystr(char *from, char *to, size_t len, size_t *lenp); 57666458Sdfr */ 57766633SdfrENTRY(copystr, 4) 57866486Sdfr mov r14=in2 // r14 = i = len 57966486Sdfr cmp.eq p6,p0=r0,in2 58066486Sdfr(p6) br.cond.spnt.few 2f // if (len == 0), bail out 58166458Sdfr 58266486Sdfr1: ld1 r15=[in0],1 // read one byte 58366486Sdfr ;; 58466486Sdfr st1 [in1]=r15,1 // write that byte 58566486Sdfr add in2=-1,in2 // len-- 58666486Sdfr ;; 58766486Sdfr cmp.eq p6,p0=r0,r15 58866486Sdfr cmp.ne p7,p0=r0,in2 58966486Sdfr ;; 59066486Sdfr(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 59166486Sdfr(p7) br.cond.sptk.few 1b // if (len != 0) copy more 59266458Sdfr 59366486Sdfr2: cmp.eq p6,p0=r0,in3 59466486Sdfr(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 59567020Sdfr sub r14=r14,in2 // *lenp = (i - len) 59666486Sdfr ;; 59766486Sdfr st8 [in3]=r14 59866486Sdfr 59966486Sdfr3: cmp.eq p6,p0=r0,r15 60066486Sdfr(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 60166458Sdfr 60266486Sdfr mov ret0=ENAMETOOLONG // *from != '\0'; error. 60366486Sdfr br.ret.sptk.few rp 60466458Sdfr 60566486Sdfr4: mov ret0=0 // return 0. 60666486Sdfr br.ret.sptk.few rp 60766486SdfrEND(copystr) 60866458Sdfr 60966633SdfrENTRY(copyinstr, 4) 61085682Sdfr .prologue 61185682Sdfr .regstk 4, 3, 4, 0 61285682Sdfr .save ar.pfs,loc0 61366486Sdfr alloc loc0=ar.pfs,4,3,4,0 61485682Sdfr .save rp,loc1 61566486Sdfr mov loc1=rp 61685682Sdfr .body 61766458Sdfr 618219741Smarcel movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 61966486Sdfr ;; 62066633Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 62166486Sdfr ;; 62266486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 623246715Smarcel ld8.acq r15=[r13] 62466486Sdfr movl r14=copyerr // set up fault handler. 62566486Sdfr ;; 62683366Sjulian add r15=TD_PCB,r15 // find pcb 62766486Sdfr ;; 62866486Sdfr ld8 r15=[r15] 62966486Sdfr ;; 63083366Sjulian add loc2=PCB_ONFAULT,r15 63166486Sdfr ;; 63266486Sdfr st8 [loc2]=r14 63366486Sdfr ;; 63466486Sdfr mov out0=in0 63566486Sdfr mov out1=in1 63666486Sdfr mov out2=in2 63766486Sdfr mov out3=in3 63866486Sdfr ;; 63966486Sdfr br.call.sptk.few rp=copystr // do the copy. 64066486Sdfr st8 [loc2]=r0 // kill the fault handler. 64167020Sdfr mov ar.pfs=loc0 // restore ar.pfs 64266486Sdfr mov rp=loc1 // restore ra. 64366486Sdfr br.ret.sptk.few rp // ret0 left over from copystr 64466486SdfrEND(copyinstr) 64566458Sdfr 64666458Sdfr/* 64766486Sdfr * Not the fastest bcopy in the world. 64866458Sdfr */ 64966633SdfrENTRY(bcopy, 3) 65066486Sdfr mov ret0=r0 // return zero for copy{in,out} 65166486Sdfr ;; 65266486Sdfr cmp.le p6,p0=in2,r0 // bail if len <= 0 65366486Sdfr(p6) br.ret.spnt.few rp 65466458Sdfr 65566486Sdfr sub r14=in1,in0 ;; // check for overlap 65666486Sdfr cmp.ltu p6,p0=r14,in2 // dst-src < len 65766486Sdfr(p6) br.cond.spnt.few 5f 65866458Sdfr 65966486Sdfr extr.u r14=in0,0,3 // src & 7 66066486Sdfr extr.u r15=in1,0,3 ;; // dst & 7 66166486Sdfr cmp.eq p6,p0=r14,r15 // different alignment? 66266486Sdfr(p6) br.cond.spnt.few 2f // branch if same alignment 66366458Sdfr 66466486Sdfr1: ld1 r14=[in0],1 ;; // copy bytewise 66566486Sdfr st1 [in1]=r14,1 66666486Sdfr add in2=-1,in2 ;; // len-- 66766486Sdfr cmp.ne p6,p0=r0,in2 66866486Sdfr(p6) br.cond.dptk.few 1b // loop 66966486Sdfr br.ret.sptk.few rp // done 67066458Sdfr 67166486Sdfr2: cmp.eq p6,p0=r14,r0 // aligned? 67266486Sdfr(p6) br.cond.sptk.few 4f 67366458Sdfr 67466486Sdfr3: ld1 r14=[in0],1 ;; // copy bytewise 67566486Sdfr st1 [in1]=r14,1 67666486Sdfr extr.u r15=in0,0,3 // src & 7 67766486Sdfr add in2=-1,in2 ;; // len-- 67866486Sdfr cmp.eq p6,p0=r0,in2 // done? 67966486Sdfr cmp.eq p7,p0=r0,r15 ;; // aligned now? 68066486Sdfr(p6) br.ret.spnt.few rp // return if done 68166486Sdfr(p7) br.cond.spnt.few 4f // go to main copy 68266486Sdfr br.cond.sptk.few 3b // more bytes to copy 68366458Sdfr 68466486Sdfr // At this point, in2 is non-zero 68566458Sdfr 68666486Sdfr4: mov r14=8 ;; 68766486Sdfr cmp.ltu p6,p0=in2,r14 ;; // len < 8? 68866486Sdfr(p6) br.cond.spnt.few 1b // byte copy the end 68966486Sdfr ld8 r15=[in0],8 ;; // copy word 69066486Sdfr st8 [in1]=r15,8 69166486Sdfr add in2=-8,in2 ;; // len -= 8 69266486Sdfr cmp.ne p6,p0=r0,in2 // done? 69366486Sdfr(p6) br.cond.spnt.few 4b // again 69466458Sdfr 69566486Sdfr br.ret.sptk.few rp // return 69666458Sdfr 69766486Sdfr // Don't bother optimising overlap case 69866458Sdfr 69966486Sdfr5: add in0=in0,in2 70066486Sdfr add in1=in1,in2 ;; 70166486Sdfr add in0=-1,in0 70266486Sdfr add in1=-1,in1 ;; 70366458Sdfr 70466486Sdfr6: ld1 r14=[in0],-1 ;; 70566486Sdfr st1 [in1]=r14,-1 70666486Sdfr add in2=-1,in2 ;; 70766486Sdfr cmp.ne p6,p0=r0,in2 70866486Sdfr(p6) br.cond.spnt.few 6b 70966458Sdfr 71066486Sdfr br.ret.sptk.few rp 71166486SdfrEND(bcopy) 71266458Sdfr 71366633SdfrENTRY(memcpy,3) 71466486Sdfr mov r14=in0 ;; 71566486Sdfr mov in0=in1 ;; 71666486Sdfr mov in1=r14 71766486Sdfr br.cond.sptk.few bcopy 71866486SdfrEND(memcpy) 71966486Sdfr 72066633SdfrENTRY(copyin, 3) 72185682Sdfr .prologue 722115084Smarcel .regstk 3, 3, 3, 0 72385682Sdfr .save ar.pfs,loc0 724115084Smarcel alloc loc0=ar.pfs,3,3,3,0 72585682Sdfr .save rp,loc1 72666486Sdfr mov loc1=rp 72785682Sdfr .body 72866458Sdfr 729219741Smarcel movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 73066486Sdfr ;; 73167020Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 73266486Sdfr ;; 73366486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 734246715Smarcel ld8.acq r15=[r13] 73566486Sdfr movl r14=copyerr // set up fault handler. 73666486Sdfr ;; 73783366Sjulian add r15=TD_PCB,r15 // find pcb 73866486Sdfr ;; 73966486Sdfr ld8 r15=[r15] 74066486Sdfr ;; 74183366Sjulian add loc2=PCB_ONFAULT,r15 74266486Sdfr ;; 74366486Sdfr st8 [loc2]=r14 74466486Sdfr ;; 74566486Sdfr mov out0=in0 74666486Sdfr mov out1=in1 74766486Sdfr mov out2=in2 74866486Sdfr ;; 74966486Sdfr br.call.sptk.few rp=bcopy // do the copy. 75066486Sdfr st8 [loc2]=r0 // kill the fault handler. 75167020Sdfr mov ar.pfs=loc0 // restore ar.pfs 75266486Sdfr mov rp=loc1 // restore ra. 75366486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 75466486SdfrEND(copyin) 75566458Sdfr 75666633SdfrENTRY(copyout, 3) 75785682Sdfr .prologue 758115084Smarcel .regstk 3, 3, 3, 0 75985682Sdfr .save ar.pfs,loc0 760115084Smarcel alloc loc0=ar.pfs,3,3,3,0 76185682Sdfr .save rp,loc1 76266486Sdfr mov loc1=rp 76385682Sdfr .body 76466458Sdfr 765219741Smarcel movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 76666486Sdfr ;; 76767020Sdfr cmp.geu p6,p0=in1,loc2 // is in user space. 76866486Sdfr ;; 76966486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 770246715Smarcel ld8.acq r15=[r13] 77166486Sdfr movl r14=copyerr // set up fault handler. 77266486Sdfr ;; 77383366Sjulian add r15=TD_PCB,r15 // find pcb 77466486Sdfr ;; 77566486Sdfr ld8 r15=[r15] 77666486Sdfr ;; 77783366Sjulian add loc2=PCB_ONFAULT,r15 77866486Sdfr ;; 77966486Sdfr st8 [loc2]=r14 78066486Sdfr ;; 78166486Sdfr mov out0=in0 78266486Sdfr mov out1=in1 78366486Sdfr mov out2=in2 78466486Sdfr ;; 78566486Sdfr br.call.sptk.few rp=bcopy // do the copy. 78666486Sdfr st8 [loc2]=r0 // kill the fault handler. 78767020Sdfr mov ar.pfs=loc0 // restore ar.pfs 78866486Sdfr mov rp=loc1 // restore ra. 78966486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 79066486SdfrEND(copyout) 79166458Sdfr 79266633SdfrENTRY(copyerr, 0) 793246715Smarcel ld8.acq r14=[r13] ;; 79483366Sjulian add r14=TD_PCB,r14 ;; // curthread->td_addr 79566486Sdfr ld8 r14=[r14] ;; 79683366Sjulian add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 79766486Sdfr st8 [r14]=r0 // reset fault handler 79866458Sdfr 79966486Sdfr mov ret0=EFAULT // return EFAULT 80066486Sdfr br.ret.sptk.few rp 80166486SdfrEND(copyerr) 802121410Smarcel 803134287Smarcel#if defined(GPROF) 804134287Smarcel/* 805134287Smarcel * Important registers: 806134287Smarcel * r8 structure return address 807134287Smarcel * rp our return address 808134287Smarcel * in0 caller's ar.pfs 809134287Smarcel * in1 caller's gp 810134287Smarcel * in2 caller's rp 811134287Smarcel * in3 GOT entry 812134287Smarcel * ar.pfs our pfs 813134287Smarcel */ 814134287SmarcelENTRY_NOPROFILE(_mcount, 4) 815134287Smarcel alloc loc0 = ar.pfs, 4, 3, 2, 0 816134287Smarcel mov loc1 = r8 817134287Smarcel mov loc2 = rp 818134287Smarcel ;; 819134287Smarcel mov out0 = in2 820134287Smarcel mov out1 = rp 821134287Smarcel br.call.sptk rp = __mcount 822134287Smarcel ;; 823134287Smarcel1: 824134287Smarcel mov gp = in1 825134287Smarcel mov r14 = ip 826134287Smarcel mov b7 = loc2 827134287Smarcel ;; 828134287Smarcel add r14 = 2f - 1b, r14 829134287Smarcel mov ar.pfs = loc0 830134287Smarcel mov rp = in2 831134287Smarcel ;; 832134287Smarcel mov b7 = r14 833134287Smarcel mov b6 = loc2 834134287Smarcel mov r8 = loc1 835134287Smarcel mov r14 = in0 836134287Smarcel br.ret.sptk b7 837134287Smarcel ;; 838134287Smarcel2: 839134287Smarcel mov ar.pfs = r14 840134287Smarcel br.sptk b6 841134287Smarcel ;; 842134287SmarcelEND(_mcount) 843134287Smarcel#endif 844