xref: /openbsd-src/sys/lib/libkern/arch/arm/memset.S (revision c6b709f57b9f0eb79d5cd435ebd6ead1f648a81f)
1*c6b709f5Sjsg/*	$OpenBSD: memset.S,v 1.4 2015/06/08 14:22:05 jsg Exp $	*/
27c0511a1Sdrahn/*	$NetBSD: memset.S,v 1.1 2000/12/29 20:51:57 bjh21 Exp $	*/
37c0511a1Sdrahn
47c0511a1Sdrahn/*
57c0511a1Sdrahn * Copyright (c) 1995 Mark Brinicombe.
67c0511a1Sdrahn * All rights reserved.
77c0511a1Sdrahn *
87c0511a1Sdrahn * Redistribution and use in source and binary forms, with or without
97c0511a1Sdrahn * modification, are permitted provided that the following conditions
107c0511a1Sdrahn * are met:
117c0511a1Sdrahn * 1. Redistributions of source code must retain the above copyright
127c0511a1Sdrahn *    notice, this list of conditions and the following disclaimer.
137c0511a1Sdrahn * 2. Redistributions in binary form must reproduce the above copyright
147c0511a1Sdrahn *    notice, this list of conditions and the following disclaimer in the
157c0511a1Sdrahn *    documentation and/or other materials provided with the distribution.
167c0511a1Sdrahn * 3. All advertising materials mentioning features or use of this software
177c0511a1Sdrahn *    must display the following acknowledgement:
187c0511a1Sdrahn *	This product includes software developed by Mark Brinicombe.
197c0511a1Sdrahn * 4. The name of the company nor the name of the author may be used to
207c0511a1Sdrahn *    endorse or promote products derived from this software without specific
217c0511a1Sdrahn *    prior written permission.
227c0511a1Sdrahn *
237c0511a1Sdrahn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
247c0511a1Sdrahn * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
257c0511a1Sdrahn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
267c0511a1Sdrahn * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
277c0511a1Sdrahn * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
287c0511a1Sdrahn * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
297c0511a1Sdrahn * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
307c0511a1Sdrahn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
317c0511a1Sdrahn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
327c0511a1Sdrahn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
337c0511a1Sdrahn * SUCH DAMAGE.
347c0511a1Sdrahn */
357c0511a1Sdrahn
367c0511a1Sdrahn#include <machine/asm.h>
377c0511a1Sdrahn
387c0511a1Sdrahn/*
397c0511a1Sdrahn * Sets a block of memory to the specified value
407c0511a1Sdrahn *
417c0511a1Sdrahn * On entry:
427c0511a1Sdrahn *   r0 - dest address
437c0511a1Sdrahn *   r1 - byte to write
447c0511a1Sdrahn *   r2 - number of bytes to write
457c0511a1Sdrahn *
467c0511a1Sdrahn * On exit:
477c0511a1Sdrahn *   r0 - dest address
487c0511a1Sdrahn */
497c0511a1Sdrahn
50*c6b709f5Sjsg.syntax unified
51*c6b709f5Sjsg
527c0511a1SdrahnENTRY(memset)
537c0511a1Sdrahn	stmfd	sp!, {r0}		/* Remember address for return value */
547c0511a1Sdrahn	and	r1, r1, #0x000000ff	/* We write bytes */
557c0511a1Sdrahn
567c0511a1Sdrahn	cmp	r2, #0x00000004		/* Do we have less than 4 bytes */
577c0511a1Sdrahn	blt	Lmemset_lessthanfour
587c0511a1Sdrahn
597c0511a1Sdrahn	/* Ok first we will word align the address */
607c0511a1Sdrahn
617c0511a1Sdrahn	ands	r3, r0, #0x00000003	/* Get the bottom two bits */
627c0511a1Sdrahn	beq	Lmemset_addraligned	/* The address is word aligned */
637c0511a1Sdrahn
647c0511a1Sdrahn	rsb	r3, r3, #0x00000004
657c0511a1Sdrahn	sub	r2, r2, r3
667c0511a1Sdrahn	cmp	r3, #0x00000002
677c0511a1Sdrahn	strb	r1, [r0], #0x0001	/* Set 1 byte */
68*c6b709f5Sjsg	strbge	r1, [r0], #0x0001	/* Set another byte */
69*c6b709f5Sjsg	strbgt	r1, [r0], #0x0001	/* and a third */
707c0511a1Sdrahn
717c0511a1Sdrahn	cmp	r2, #0x00000004
727c0511a1Sdrahn	blt	Lmemset_lessthanfour
737c0511a1Sdrahn
747c0511a1Sdrahn	/* Now we must be word aligned */
757c0511a1Sdrahn
767c0511a1SdrahnLmemset_addraligned:
777c0511a1Sdrahn
787c0511a1Sdrahn	orr	r3, r1, r1, lsl #8	/* Repeat the byte into a word */
797c0511a1Sdrahn	orr	r3, r3, r3, lsl #16
807c0511a1Sdrahn
817c0511a1Sdrahn	/* We know we have at least 4 bytes ... */
827c0511a1Sdrahn
837c0511a1Sdrahn	cmp	r2, #0x00000020		/* If less than 32 then use words */
847c0511a1Sdrahn	blt	Lmemset_lessthan32
857c0511a1Sdrahn
867c0511a1Sdrahn	/* We have at least 32 so lets use quad words */
877c0511a1Sdrahn
887c0511a1Sdrahn	stmfd	sp!, {r4-r6}		/* Store registers */
897c0511a1Sdrahn	mov	r4, r3			/* Duplicate data */
907c0511a1Sdrahn	mov	r5, r3
917c0511a1Sdrahn	mov	r6, r3
927c0511a1Sdrahn
937c0511a1SdrahnLmemset_loop16:
947c0511a1Sdrahn	stmia	r0!, {r3-r6}		/* Store 16 bytes */
957c0511a1Sdrahn	sub	r2, r2, #0x00000010	/* Adjust count */
967c0511a1Sdrahn	cmp	r2, #0x00000010		/* Still got at least 16 bytes ? */
977c0511a1Sdrahn	bgt	Lmemset_loop16
987c0511a1Sdrahn
997c0511a1Sdrahn	ldmfd	sp!, {r4-r6}		/* Restore registers */
1007c0511a1Sdrahn
1017c0511a1Sdrahn	/* Do we need to set some words as well ? */
1027c0511a1Sdrahn
1037c0511a1Sdrahn	cmp	r2, #0x00000004
1047c0511a1Sdrahn	blt	Lmemset_lessthanfour
1057c0511a1Sdrahn
1067c0511a1Sdrahn	/* Have either less than 16 or less than 32 depending on route taken */
1077c0511a1Sdrahn
1087c0511a1SdrahnLmemset_lessthan32:
1097c0511a1Sdrahn
1107c0511a1Sdrahn	/* We have at least 4 bytes so copy as words */
1117c0511a1Sdrahn
1127c0511a1SdrahnLmemset_loop4:
1137c0511a1Sdrahn	str	r3, [r0], #0x0004
1147c0511a1Sdrahn	sub	r2, r2, #0x0004
1157c0511a1Sdrahn	cmp	r2, #0x00000004
1167c0511a1Sdrahn	bge	Lmemset_loop4
1177c0511a1Sdrahn
1187c0511a1SdrahnLmemset_lessthanfour:
1197c0511a1Sdrahn	cmp	r2, #0x00000000
120*c6b709f5Sjsg	ldmfdeq	sp!, {r0}
1217c0511a1Sdrahn	moveq	pc, lr			/* Zero length so exit */
1227c0511a1Sdrahn
1237c0511a1Sdrahn	cmp	r2, #0x00000002
1247c0511a1Sdrahn	strb	r1, [r0], #0x0001	/* Set 1 byte */
125*c6b709f5Sjsg	strbge	r1, [r0], #0x0001	/* Set another byte */
126*c6b709f5Sjsg	strbgt	r1, [r0], #0x0001	/* and a third */
1277c0511a1Sdrahn
1287c0511a1Sdrahn	ldmfd	sp!, {r0}
1297c0511a1Sdrahn	mov	pc, lr			/* Exit */
130