1*f14fb602SLionel Sambuc/* $NetBSD: bcopy.S,v 1.4 2011/08/27 13:23:52 bouyer Exp $ */ 2b6cbf720SGianluca Guida 3b6cbf720SGianluca Guida/* 4b6cbf720SGianluca Guida * Mach Operating System 5b6cbf720SGianluca Guida * Copyright (c) 1993 Carnegie Mellon University 6b6cbf720SGianluca Guida * All Rights Reserved. 7b6cbf720SGianluca Guida * 8b6cbf720SGianluca Guida * Permission to use, copy, modify and distribute this software and its 9b6cbf720SGianluca Guida * documentation is hereby granted, provided that both the copyright 10b6cbf720SGianluca Guida * notice and this permission notice appear in all copies of the 11b6cbf720SGianluca Guida * software, derivative works or modified versions, and any portions 12b6cbf720SGianluca Guida * thereof, and that both notices appear in supporting documentation. 13b6cbf720SGianluca Guida * 14b6cbf720SGianluca Guida * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15b6cbf720SGianluca Guida * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16b6cbf720SGianluca Guida * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17b6cbf720SGianluca Guida * 18b6cbf720SGianluca Guida * Carnegie Mellon requests users of this software to return to 19b6cbf720SGianluca Guida * 20b6cbf720SGianluca Guida * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21b6cbf720SGianluca Guida * School of Computer Science 22b6cbf720SGianluca Guida * Carnegie Mellon University 23b6cbf720SGianluca Guida * Pittsburgh PA 15213-3890 24b6cbf720SGianluca Guida * 25b6cbf720SGianluca Guida * any improvements or extensions that they make and grant Carnegie Mellon 26b6cbf720SGianluca Guida * the rights to redistribute these changes. 27b6cbf720SGianluca Guida */ 28b6cbf720SGianluca Guida 29b6cbf720SGianluca Guida/* 30b6cbf720SGianluca Guida * File: mips_bcopy.s 31b6cbf720SGianluca Guida * Author: Chris Maeda 32b6cbf720SGianluca Guida * Date: June 1993 33b6cbf720SGianluca Guida * 34b6cbf720SGianluca Guida * Fast copy routine. Derived from aligned_block_copy. 35b6cbf720SGianluca Guida */ 36b6cbf720SGianluca Guida 37b6cbf720SGianluca Guida 38b6cbf720SGianluca Guida#include <mips/asm.h> 39b6cbf720SGianluca Guida#ifndef _LOCORE 40b6cbf720SGianluca Guida#define _LOCORE /* XXX not really, just assembly-code source */ 41b6cbf720SGianluca Guida#endif 42b6cbf720SGianluca Guida#include <machine/endian.h> 43b6cbf720SGianluca Guida 44b6cbf720SGianluca Guida 45b6cbf720SGianluca Guida#if defined(LIBC_SCCS) && !defined(lint) 46b6cbf720SGianluca Guida#if 0 47b6cbf720SGianluca Guida RCSID("from: @(#)mips_bcopy.s 2.2 CMU 18/06/93") 48b6cbf720SGianluca Guida#else 49*f14fb602SLionel Sambuc RCSID("$NetBSD: bcopy.S,v 1.4 2011/08/27 13:23:52 bouyer Exp $") 50b6cbf720SGianluca Guida#endif 51b6cbf720SGianluca Guida#endif /* LIBC_SCCS and not lint */ 52b6cbf720SGianluca Guida 53b6cbf720SGianluca Guida/* 54b6cbf720SGianluca Guida * bcopy(caddr_t src, caddr_t dst, unsigned int len) 55b6cbf720SGianluca Guida * 56b6cbf720SGianluca Guida * a0 src address 57b6cbf720SGianluca Guida * a1 dst address 58b6cbf720SGianluca Guida * a2 length 59b6cbf720SGianluca Guida */ 60b6cbf720SGianluca Guida 61b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE) 62b6cbf720SGianluca Guida#ifdef MEMCOPY 63b6cbf720SGianluca Guida#define FUNCTION memcpy 64b6cbf720SGianluca Guida#else 65b6cbf720SGianluca Guida#define FUNCTION memmove 66b6cbf720SGianluca Guida#endif 67b6cbf720SGianluca Guida#define SRCREG a1 68b6cbf720SGianluca Guida#define DSTREG a0 69b6cbf720SGianluca Guida#else 70b6cbf720SGianluca Guida#define FUNCTION bcopy 71b6cbf720SGianluca Guida#define SRCREG a0 72b6cbf720SGianluca Guida#define DSTREG a1 73b6cbf720SGianluca Guida#endif 74b6cbf720SGianluca Guida 75b6cbf720SGianluca Guida#define SIZEREG a2 76b6cbf720SGianluca Guida 77b6cbf720SGianluca GuidaLEAF(FUNCTION) 78b6cbf720SGianluca Guida .set noat 79b6cbf720SGianluca Guida .set noreorder 80b6cbf720SGianluca Guida 81b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE) 82b6cbf720SGianluca Guida /* set up return value, while we still can */ 83b6cbf720SGianluca Guida move v0,DSTREG 84b6cbf720SGianluca Guida#endif 85b6cbf720SGianluca Guida /* 86b6cbf720SGianluca Guida * Make sure we can copy forwards. 87b6cbf720SGianluca Guida */ 88b6cbf720SGianluca Guida sltu t0,SRCREG,DSTREG # t0 == SRCREG < DSTREG 89b6cbf720SGianluca Guida bne t0,zero,6f # copy backwards 90b6cbf720SGianluca Guida 91b6cbf720SGianluca Guida /* 92b6cbf720SGianluca Guida * There are four alignment cases (with frequency) 93b6cbf720SGianluca Guida * (Based on measurements taken with a DECstation 5000/200 94b6cbf720SGianluca Guida * inside a Mach kernel.) 95b6cbf720SGianluca Guida * 96b6cbf720SGianluca Guida * aligned -> aligned (mostly) 97b6cbf720SGianluca Guida * unaligned -> aligned (sometimes) 98b6cbf720SGianluca Guida * aligned,unaligned -> unaligned (almost never) 99b6cbf720SGianluca Guida * 100b6cbf720SGianluca Guida * Note that we could add another case that checks if 101b6cbf720SGianluca Guida * the destination and source are unaligned but the 102b6cbf720SGianluca Guida * copy is alignable. eg if src and dest are both 103b6cbf720SGianluca Guida * on a halfword boundary. 104b6cbf720SGianluca Guida */ 105b6cbf720SGianluca Guida andi t1,DSTREG,(SZREG-1) # get last bits of dest 106b6cbf720SGianluca Guida bne t1,zero,3f # dest unaligned 107b6cbf720SGianluca Guida andi t0,SRCREG,(SZREG-1) # get last bits of src 108b6cbf720SGianluca Guida bne t0,zero,5f 109b6cbf720SGianluca Guida 110b6cbf720SGianluca Guida /* 111b6cbf720SGianluca Guida * Forward aligned->aligned copy, 8 words at a time. 112b6cbf720SGianluca Guida */ 113b6cbf720SGianluca Guida98: 114b6cbf720SGianluca Guida li AT,-(SZREG*8) 115b6cbf720SGianluca Guida and t0,SIZEREG,AT # count truncated to multiples 116b6cbf720SGianluca Guida PTR_ADDU a3,SRCREG,t0 # run fast loop up to this addr 117b6cbf720SGianluca Guida sltu AT,SRCREG,a3 # any work to do? 118b6cbf720SGianluca Guida beq AT,zero,2f 119b6cbf720SGianluca Guida PTR_SUBU SIZEREG,t0 120b6cbf720SGianluca Guida 121b6cbf720SGianluca Guida /* 122b6cbf720SGianluca Guida * loop body 123b6cbf720SGianluca Guida */ 124b6cbf720SGianluca Guida1: # cp 125b6cbf720SGianluca Guida REG_L t3,(0*SZREG)(SRCREG) 126b6cbf720SGianluca Guida REG_L v1,(1*SZREG)(SRCREG) 127b6cbf720SGianluca Guida REG_L t0,(2*SZREG)(SRCREG) 128b6cbf720SGianluca Guida REG_L t1,(3*SZREG)(SRCREG) 129b6cbf720SGianluca Guida PTR_ADDU SRCREG,SZREG*8 130b6cbf720SGianluca Guida REG_S t3,(0*SZREG)(DSTREG) 131b6cbf720SGianluca Guida REG_S v1,(1*SZREG)(DSTREG) 132b6cbf720SGianluca Guida REG_S t0,(2*SZREG)(DSTREG) 133b6cbf720SGianluca Guida REG_S t1,(3*SZREG)(DSTREG) 134b6cbf720SGianluca Guida REG_L t1,(-1*SZREG)(SRCREG) 135b6cbf720SGianluca Guida REG_L t0,(-2*SZREG)(SRCREG) 136b6cbf720SGianluca Guida REG_L v1,(-3*SZREG)(SRCREG) 137b6cbf720SGianluca Guida REG_L t3,(-4*SZREG)(SRCREG) 138b6cbf720SGianluca Guida PTR_ADDU DSTREG,SZREG*8 139b6cbf720SGianluca Guida REG_S t1,(-1*SZREG)(DSTREG) 140b6cbf720SGianluca Guida REG_S t0,(-2*SZREG)(DSTREG) 141b6cbf720SGianluca Guida REG_S v1,(-3*SZREG)(DSTREG) 142b6cbf720SGianluca Guida bne SRCREG,a3,1b 143b6cbf720SGianluca Guida REG_S t3,(-4*SZREG)(DSTREG) 144b6cbf720SGianluca Guida 145b6cbf720SGianluca Guida /* 146b6cbf720SGianluca Guida * Copy a word at a time, no loop unrolling. 147b6cbf720SGianluca Guida */ 148b6cbf720SGianluca Guida2: # wordcopy 149b6cbf720SGianluca Guida andi t2,SIZEREG,(SZREG-1) # get byte count / SZREG 150b6cbf720SGianluca Guida PTR_SUBU t2,SIZEREG,t2 # t2 = words to copy * SZREG 151b6cbf720SGianluca Guida beq t2,zero,3f 152b6cbf720SGianluca Guida PTR_ADDU t0,SRCREG,t2 # stop at t0 153b6cbf720SGianluca Guida PTR_SUBU SIZEREG,SIZEREG,t2 154b6cbf720SGianluca Guida1: 155b6cbf720SGianluca Guida REG_L t3,0(SRCREG) 156b6cbf720SGianluca Guida PTR_ADDU SRCREG,SZREG 157b6cbf720SGianluca Guida REG_S t3,0(DSTREG) 158b6cbf720SGianluca Guida bne SRCREG,t0,1b 159b6cbf720SGianluca Guida PTR_ADDU DSTREG,SZREG 160b6cbf720SGianluca Guida 161b6cbf720SGianluca Guida3: # bytecopy 162b6cbf720SGianluca Guida beq SIZEREG,zero,4f # nothing left to do? 163b6cbf720SGianluca Guida nop 164b6cbf720SGianluca Guida1: 165b6cbf720SGianluca Guida lb t3,0(SRCREG) 166b6cbf720SGianluca Guida PTR_ADDU SRCREG,1 167b6cbf720SGianluca Guida sb t3,0(DSTREG) 168b6cbf720SGianluca Guida PTR_SUBU SIZEREG,1 169b6cbf720SGianluca Guida bgtz SIZEREG,1b 170b6cbf720SGianluca Guida PTR_ADDU DSTREG,1 171b6cbf720SGianluca Guida 172b6cbf720SGianluca Guida4: # copydone 173*f14fb602SLionel Sambuc .set at #-mfix-loongson2f-btb 174b6cbf720SGianluca Guida j ra 175b6cbf720SGianluca Guida nop 176*f14fb602SLionel Sambuc .set noat 177b6cbf720SGianluca Guida 178b6cbf720SGianluca Guida /* 179b6cbf720SGianluca Guida * Copy from unaligned source to aligned dest. 180b6cbf720SGianluca Guida */ 181b6cbf720SGianluca Guida5: # destaligned 182b6cbf720SGianluca Guida andi t0,SIZEREG,(SZREG-1) # t0 = bytecount mod SZREG 183b6cbf720SGianluca Guida PTR_SUBU a3,SIZEREG,t0 # number of words to transfer 184b6cbf720SGianluca Guida beq a3,zero,3b 185b6cbf720SGianluca Guida nop 186b6cbf720SGianluca Guida move SIZEREG,t0 # this many to do after we are done 187b6cbf720SGianluca Guida PTR_ADDU a3,SRCREG,a3 # stop point 188b6cbf720SGianluca Guida 189b6cbf720SGianluca Guida1: 190b6cbf720SGianluca Guida REG_LHI t3,0(SRCREG) 191b6cbf720SGianluca Guida REG_LLO t3,SZREG-1(SRCREG) 192b6cbf720SGianluca Guida PTR_ADDI SRCREG,SZREG 193b6cbf720SGianluca Guida REG_S t3,0(DSTREG) 194b6cbf720SGianluca Guida bne SRCREG,a3,1b 195b6cbf720SGianluca Guida PTR_ADDI DSTREG,SZREG 196b6cbf720SGianluca Guida 197b6cbf720SGianluca Guida b 3b 198b6cbf720SGianluca Guida nop 199b6cbf720SGianluca Guida 200b6cbf720SGianluca Guida6: # backcopy -- based on above 201b6cbf720SGianluca Guida PTR_ADDU SRCREG,SIZEREG 202b6cbf720SGianluca Guida PTR_ADDU DSTREG,SIZEREG 203b6cbf720SGianluca Guida andi t1,DSTREG,SZREG-1 # get last 3 bits of dest 204b6cbf720SGianluca Guida bne t1,zero,3f 205b6cbf720SGianluca Guida andi t0,SRCREG,SZREG-1 # get last 3 bits of src 206b6cbf720SGianluca Guida bne t0,zero,5f 207b6cbf720SGianluca Guida 208b6cbf720SGianluca Guida /* 209b6cbf720SGianluca Guida * Forward aligned->aligned copy, 8*4 bytes at a time. 210b6cbf720SGianluca Guida */ 211b6cbf720SGianluca Guida li AT,(-8*SZREG) 212b6cbf720SGianluca Guida and t0,SIZEREG,AT # count truncated to multiple of 32 213b6cbf720SGianluca Guida beq t0,zero,2f # any work to do? 214b6cbf720SGianluca Guida PTR_SUBU SIZEREG,t0 215b6cbf720SGianluca Guida PTR_SUBU a3,SRCREG,t0 216b6cbf720SGianluca Guida 217b6cbf720SGianluca Guida /* 218b6cbf720SGianluca Guida * loop body 219b6cbf720SGianluca Guida */ 220b6cbf720SGianluca Guida1: # cp 221b6cbf720SGianluca Guida REG_L t3,(-4*SZREG)(SRCREG) 222b6cbf720SGianluca Guida REG_L v1,(-3*SZREG)(SRCREG) 223b6cbf720SGianluca Guida REG_L t0,(-2*SZREG)(SRCREG) 224b6cbf720SGianluca Guida REG_L t1,(-1*SZREG)(SRCREG) 225b6cbf720SGianluca Guida PTR_SUBU SRCREG,8*SZREG 226b6cbf720SGianluca Guida REG_S t3,(-4*SZREG)(DSTREG) 227b6cbf720SGianluca Guida REG_S v1,(-3*SZREG)(DSTREG) 228b6cbf720SGianluca Guida REG_S t0,(-2*SZREG)(DSTREG) 229b6cbf720SGianluca Guida REG_S t1,(-1*SZREG)(DSTREG) 230b6cbf720SGianluca Guida REG_L t1,(3*SZREG)(SRCREG) 231b6cbf720SGianluca Guida REG_L t0,(2*SZREG)(SRCREG) 232b6cbf720SGianluca Guida REG_L v1,(1*SZREG)(SRCREG) 233b6cbf720SGianluca Guida REG_L t3,(0*SZREG)(SRCREG) 234b6cbf720SGianluca Guida PTR_SUBU DSTREG,8*SZREG 235b6cbf720SGianluca Guida REG_S t1,(3*SZREG)(DSTREG) 236b6cbf720SGianluca Guida REG_S t0,(2*SZREG)(DSTREG) 237b6cbf720SGianluca Guida REG_S v1,(1*SZREG)(DSTREG) 238b6cbf720SGianluca Guida bne SRCREG,a3,1b 239b6cbf720SGianluca Guida REG_S t3,(0*SZREG)(DSTREG) 240b6cbf720SGianluca Guida 241b6cbf720SGianluca Guida /* 242b6cbf720SGianluca Guida * Copy a word at a time, no loop unrolling. 243b6cbf720SGianluca Guida */ 244b6cbf720SGianluca Guida2: # wordcopy 245b6cbf720SGianluca Guida andi t2,SIZEREG,SZREG-1 # get byte count / 4 246b6cbf720SGianluca Guida PTR_SUBU t2,SIZEREG,t2 # t2 = number of words to copy 247b6cbf720SGianluca Guida beq t2,zero,3f 248b6cbf720SGianluca Guida PTR_SUBU t0,SRCREG,t2 # stop at t0 249b6cbf720SGianluca Guida PTR_SUBU SIZEREG,SIZEREG,t2 250b6cbf720SGianluca Guida1: 251b6cbf720SGianluca Guida REG_L t3,-SZREG(SRCREG) 252b6cbf720SGianluca Guida PTR_SUBU SRCREG,SZREG 253b6cbf720SGianluca Guida REG_S t3,-SZREG(DSTREG) 254b6cbf720SGianluca Guida bne SRCREG,t0,1b 255b6cbf720SGianluca Guida PTR_SUBU DSTREG,SZREG 256b6cbf720SGianluca Guida 257b6cbf720SGianluca Guida3: # bytecopy 258b6cbf720SGianluca Guida beq SIZEREG,zero,4f # nothing left to do? 259b6cbf720SGianluca Guida nop 260b6cbf720SGianluca Guida1: 261b6cbf720SGianluca Guida lb t3,-1(SRCREG) 262b6cbf720SGianluca Guida PTR_SUBU SRCREG,1 263b6cbf720SGianluca Guida sb t3,-1(DSTREG) 264b6cbf720SGianluca Guida PTR_SUBU SIZEREG,1 265b6cbf720SGianluca Guida bgtz SIZEREG,1b 266b6cbf720SGianluca Guida PTR_SUBU DSTREG,1 267b6cbf720SGianluca Guida 268b6cbf720SGianluca Guida4: # copydone 269*f14fb602SLionel Sambuc .set at #-mfix-loongson2f-btb 270b6cbf720SGianluca Guida j ra 271b6cbf720SGianluca Guida nop 272*f14fb602SLionel Sambuc .set noat 273b6cbf720SGianluca Guida 274b6cbf720SGianluca Guida /* 275b6cbf720SGianluca Guida * Copy from unaligned source to aligned dest. 276b6cbf720SGianluca Guida */ 277b6cbf720SGianluca Guida5: # destaligned 278b6cbf720SGianluca Guida andi t0,SIZEREG,SZREG-1 # t0 = bytecount mod 4 279b6cbf720SGianluca Guida PTR_SUBU a3,SIZEREG,t0 # number of words to transfer 280b6cbf720SGianluca Guida beq a3,zero,3b 281b6cbf720SGianluca Guida nop 282b6cbf720SGianluca Guida move SIZEREG,t0 # this many to do after we are done 283b6cbf720SGianluca Guida PTR_SUBU a3,SRCREG,a3 # stop point 284b6cbf720SGianluca Guida 285b6cbf720SGianluca Guida1: 286b6cbf720SGianluca Guida REG_LHI t3,-SZREG(SRCREG) 287b6cbf720SGianluca Guida REG_LLO t3,-1(SRCREG) 288b6cbf720SGianluca Guida PTR_SUBU SRCREG,SZREG 289b6cbf720SGianluca Guida REG_S t3,-SZREG(DSTREG) 290b6cbf720SGianluca Guida bne SRCREG,a3,1b 291b6cbf720SGianluca Guida PTR_SUBU DSTREG,SZREG 292b6cbf720SGianluca Guida 293b6cbf720SGianluca Guida b 3b 294b6cbf720SGianluca Guida nop 295b6cbf720SGianluca Guida 296b6cbf720SGianluca Guida .set reorder 297b6cbf720SGianluca Guida .set at 298b6cbf720SGianluca Guida END(FUNCTION) 299