xref: /minix3/common/lib/libc/arch/or1k/string/memset.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*	$NetBSD: memset.S,v 1.1 2014/09/03 19:34:25 matt Exp $ */
2*0a6a1f1dSLionel Sambuc
3*0a6a1f1dSLionel Sambuc/*-
4*0a6a1f1dSLionel Sambuc * Copyright (c) 2014 The NetBSD Foundation, Inc.
5*0a6a1f1dSLionel Sambuc * All rights reserved.
6*0a6a1f1dSLionel Sambuc *
7*0a6a1f1dSLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
8*0a6a1f1dSLionel Sambuc * by Matt Thomas of 3am Software Foundry.
9*0a6a1f1dSLionel Sambuc *
10*0a6a1f1dSLionel Sambuc * Redistribution and use in source and binary forms, with or without
11*0a6a1f1dSLionel Sambuc * modification, are permitted provided that the following conditions
12*0a6a1f1dSLionel Sambuc * are met:
13*0a6a1f1dSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14*0a6a1f1dSLionel Sambuc *    notice, this list of conditions and the following disclaimer.
15*0a6a1f1dSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*0a6a1f1dSLionel Sambuc *    notice, this list of conditions and the following disclaimer in the
17*0a6a1f1dSLionel Sambuc *    documentation and/or other materials provided with the distribution.
18*0a6a1f1dSLionel Sambuc *
19*0a6a1f1dSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*0a6a1f1dSLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*0a6a1f1dSLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*0a6a1f1dSLionel Sambuc * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*0a6a1f1dSLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*0a6a1f1dSLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*0a6a1f1dSLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*0a6a1f1dSLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*0a6a1f1dSLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*0a6a1f1dSLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*0a6a1f1dSLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
30*0a6a1f1dSLionel Sambuc */
31*0a6a1f1dSLionel Sambuc
32*0a6a1f1dSLionel Sambuc#include <machine/asm.h>
33*0a6a1f1dSLionel Sambuc
34*0a6a1f1dSLionel Sambuc
35*0a6a1f1dSLionel Sambuc#if defined(LIBC_SCCS) && !defined(lint)
36*0a6a1f1dSLionel Sambuc__RCSID("$NetBSD: memset.S,v 1.1 2014/09/03 19:34:25 matt Exp $")
37*0a6a1f1dSLionel Sambuc#endif /* LIBC_SCCS && !lint */
38*0a6a1f1dSLionel Sambuc
39*0a6a1f1dSLionel Sambuc/*----------------------------------------------------------------------*/
40*0a6a1f1dSLionel Sambuc/*
41*0a6a1f1dSLionel Sambuc     void bzero(void *b r3, size_t len r4);
42*0a6a1f1dSLionel Sambuc     void * memset(void *b r3, int c r4, size_t len r5);
43*0a6a1f1dSLionel Sambuc*/
44*0a6a1f1dSLionel Sambuc/*----------------------------------------------------------------------*/
45*0a6a1f1dSLionel Sambuc
46*0a6a1f1dSLionel Sambuc
47*0a6a1f1dSLionel Sambuc#ifdef _BZERO
48*0a6a1f1dSLionel Sambuc#define r_fill	r0
49*0a6a1f1dSLionel SambucENTRY(bzero)
50*0a6a1f1dSLionel Sambuc#else
51*0a6a1f1dSLionel Sambuc#define r_fill	r4
52*0a6a1f1dSLionel SambucENTRY(memset)
53*0a6a1f1dSLionel Sambuc#endif
54*0a6a1f1dSLionel Sambuc#ifdef _BZERO
55*0a6a1f1dSLionel Sambuc		l.ori	r5, r4, 0
56*0a6a1f1dSLionel Sambuc		l.or	r4, r0, r0
57*0a6a1f1dSLionel Sambuc#else
58*0a6a1f1dSLionel Sambuc		l.or	r11, r3, r0		/* move start to return value */
59*0a6a1f1dSLionel Sambuc#endif
60*0a6a1f1dSLionel Sambuc		l.sfeqi	r5, 0			/* anything to do? */
61*0a6a1f1dSLionel Sambuc		l.bf	.Lret			/*   no, just return */
62*0a6a1f1dSLionel Sambuc		l.nop
63*0a6a1f1dSLionel Sambuc
64*0a6a1f1dSLionel Sambuc		l.sfgeui r5, 7			/* small buffer? */
65*0a6a1f1dSLionel Sambuc		l.add	r5, r5, r3		/* r5 is end pointer */
66*0a6a1f1dSLionel Sambuc		l.bnf	.Lbyte_fill		/*   yes.  just byte fill */
67*0a6a1f1dSLionel Sambuc		l.nop
68*0a6a1f1dSLionel Sambuc
69*0a6a1f1dSLionel Sambuc#ifndef _BZERO
70*0a6a1f1dSLionel Sambuc		// Let's see the fill type
71*0a6a1f1dSLionel Sambuc		l.sfeqi	r4, 0			/* filling with 0? */
72*0a6a1f1dSLionel Sambuc		l.bf	.Lalignment_check	/* don't to replicate */
73*0a6a1f1dSLionel Sambuc		l.nop
74*0a6a1f1dSLionel Sambuc		l.extbz	r4, r4			/* truncate to 8 bits */
75*0a6a1f1dSLionel Sambuc		l.slli	r13, r4, 8		/* shift left 8 bits */
76*0a6a1f1dSLionel Sambuc		l.or	r4, r4, r13		/* merge the two bytes */
77*0a6a1f1dSLionel Sambuc		l.slli	r13, r4, 16		/* shift left 16 bits */
78*0a6a1f1dSLionel Sambuc		l.or	r4, r4, r13		/* merge the two halves */
79*0a6a1f1dSLionel Sambuc
80*0a6a1f1dSLionel Sambuc.Lalignment_check:
81*0a6a1f1dSLionel Sambuc#endif
82*0a6a1f1dSLionel Sambuc		l.andi	r13, r3, 3		/* get low bits of start */
83*0a6a1f1dSLionel Sambuc		l.sfeqi	r13, 0			/* word aligned? */
84*0a6a1f1dSLionel Sambuc		l.bf	.Lword_fill		/*   yes, start setting */
85*0a6a1f1dSLionel Sambuc		l.nop
86*0a6a1f1dSLionel Sambuc
87*0a6a1f1dSLionel Sambuc		l.add	r5, r5, r13		/* increase length */
88*0a6a1f1dSLionel Sambuc		l.sub	r3, r3, r13		/* mask word aligned */
89*0a6a1f1dSLionel Sambuc		l.slli	r13, r13, 3		/* bytes to bits */
90*0a6a1f1dSLionel Sambuc		l.addi	r15, r13, -8		/* minus one byte */
91*0a6a1f1dSLionel Sambuc
92*0a6a1f1dSLionel Sambuc		l.lwz	r6, 0(r3)		/* get first word */
93*0a6a1f1dSLionel Sambuc		l.movhi	r7, 0xff00		/* 0xff000000 */
94*0a6a1f1dSLionel Sambuc		l.sra	r7, r7, r13		/* shift right align bytes */
95*0a6a1f1dSLionel Sambuc		l.and	r6, r6, r7		/* clear bytes to be filled */
96*0a6a1f1dSLionel Sambuc#ifndef _BZERO
97*0a6a1f1dSLionel Sambuc		l.srl	r7, r_fill, r13		/* clear bytes to preserve */
98*0a6a1f1dSLionel Sambuc		l.or	r6, r6, r7		/* merge existing with new */
99*0a6a1f1dSLionel Sambuc#endif
100*0a6a1f1dSLionel Sambuc		l.sw	0(r3), r6		/* store first word */
101*0a6a1f1dSLionel Sambuc		l.addi	r3, r3, 4		/* advance to next word */
102*0a6a1f1dSLionel Sambuc		l.addi	r5, r5, -4		/* one less word to do */
103*0a6a1f1dSLionel Sambuc
104*0a6a1f1dSLionel Sambuc.Lword_aligned:
105*0a6a1f1dSLionel Sambuc		l.srli	r6, r5, 2		/* clear low two bits of len */
106*0a6a1f1dSLionel Sambuc		l.srli	r6, r6, 2		/* ... */
107*0a6a1f1dSLionel Sambuc		l.sfgeu	r3, r6			/* any more full words? */
108*0a6a1f1dSLionel Sambuc		l.bf	.Lend_fill		/* no, handle the last bytes */
109*0a6a1f1dSLionel Sambuc		l.nop
110*0a6a1f1dSLionel Sambuc
111*0a6a1f1dSLionel Sambuc.Lword_fill:
112*0a6a1f1dSLionel Sambuc		l.sw	0(r3), r_fill		/* store a word */
113*0a6a1f1dSLionel Sambuc		l.addi	r3, r3, 4		/* advance */
114*0a6a1f1dSLionel Sambuc		l.sfgeu	r3, r6			/* any more full words? */
115*0a6a1f1dSLionel Sambuc		l.bnf	.Lword_fill		/*   yes, fill next word */
116*0a6a1f1dSLionel Sambuc		l.nop
117*0a6a1f1dSLionel Sambuc		l.j	.Lend_fill		/* fill any leftover bytes */
118*0a6a1f1dSLionel Sambuc		l.nop
119*0a6a1f1dSLionel Sambuc
120*0a6a1f1dSLionel Sambuc.Lbyte_fill:
121*0a6a1f1dSLionel Sambuc		l.sb	0(r3), r_fill		/* store a byte */
122*0a6a1f1dSLionel Sambuc		l.addi	r3, r3, 1		/* advance */
123*0a6a1f1dSLionel Sambuc.Lend_fill:
124*0a6a1f1dSLionel Sambuc		l.sfeq	r3, r5			/* at the end? */
125*0a6a1f1dSLionel Sambuc		l.bnf	.Lbyte_fill		/*   no, fill next byte */
126*0a6a1f1dSLionel Sambuc		l.nop
127*0a6a1f1dSLionel Sambuc
128*0a6a1f1dSLionel Sambuc.Lret:
129*0a6a1f1dSLionel Sambuc		l.jr	lr			/* return */
130*0a6a1f1dSLionel Sambuc		l.nop
131*0a6a1f1dSLionel Sambuc#ifdef _BZERO
132*0a6a1f1dSLionel SambucEND(bzero)
133*0a6a1f1dSLionel Sambuc#else
134*0a6a1f1dSLionel SambucEND(memset)
135*0a6a1f1dSLionel Sambuc#endif
136