18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
38c2ecf20Sopenharmony_ci * Copyright (C) 2004 Microtronix Datacom Ltd
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
68c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
78c2ecf20Sopenharmony_ci * for more details.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/types.h>
118c2ecf20Sopenharmony_ci#include <linux/string.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_civoid *memset(void *s, int c, size_t count)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	int destptr, charcnt, dwordcnt, fill8reg, wrkrega;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	if (!count)
188c2ecf20Sopenharmony_ci		return s;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	c &= 0xFF;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	if (count <= 8) {
238c2ecf20Sopenharmony_ci		char *xs = (char *) s;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci		while (count--)
268c2ecf20Sopenharmony_ci			*xs++ = c;
278c2ecf20Sopenharmony_ci		return s;
288c2ecf20Sopenharmony_ci	}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	__asm__ __volatile__ (
318c2ecf20Sopenharmony_ci		/* fill8 %3, %5 (c & 0xff) */
328c2ecf20Sopenharmony_ci		"	slli	%4, %5, 8\n"
338c2ecf20Sopenharmony_ci		"	or	%4, %4, %5\n"
348c2ecf20Sopenharmony_ci		"	slli    %3, %4, 16\n"
358c2ecf20Sopenharmony_ci		"	or	%3, %3, %4\n"
368c2ecf20Sopenharmony_ci		/* Word-align %0 (s) if necessary */
378c2ecf20Sopenharmony_ci		"	andi	%4, %0, 0x01\n"
388c2ecf20Sopenharmony_ci		"	beq	%4, zero, 1f\n"
398c2ecf20Sopenharmony_ci		"	addi	%1, %1, -1\n"
408c2ecf20Sopenharmony_ci		"	stb	%3, 0(%0)\n"
418c2ecf20Sopenharmony_ci		"	addi	%0, %0, 1\n"
428c2ecf20Sopenharmony_ci		"1:	mov	%2, %1\n"
438c2ecf20Sopenharmony_ci		/* Dword-align %0 (s) if necessary */
448c2ecf20Sopenharmony_ci		"	andi	%4, %0, 0x02\n"
458c2ecf20Sopenharmony_ci		"	beq	%4, zero, 2f\n"
468c2ecf20Sopenharmony_ci		"	addi	%1, %1, -2\n"
478c2ecf20Sopenharmony_ci		"	sth	%3, 0(%0)\n"
488c2ecf20Sopenharmony_ci		"	addi	%0, %0, 2\n"
498c2ecf20Sopenharmony_ci		"	mov	%2, %1\n"
508c2ecf20Sopenharmony_ci		/* %1 and %2 are how many more bytes to set */
518c2ecf20Sopenharmony_ci		"2:	srli	%2, %2, 2\n"
528c2ecf20Sopenharmony_ci		/* %2 is how many dwords to set */
538c2ecf20Sopenharmony_ci		"3:	stw	%3, 0(%0)\n"
548c2ecf20Sopenharmony_ci		"	addi	%0, %0, 4\n"
558c2ecf20Sopenharmony_ci		"	addi    %2, %2, -1\n"
568c2ecf20Sopenharmony_ci		"	bne	%2, zero, 3b\n"
578c2ecf20Sopenharmony_ci		/* store residual word and/or byte if necessary */
588c2ecf20Sopenharmony_ci		"	andi	%4, %1, 0x02\n"
598c2ecf20Sopenharmony_ci		"	beq	%4, zero, 4f\n"
608c2ecf20Sopenharmony_ci		"	sth	%3, 0(%0)\n"
618c2ecf20Sopenharmony_ci		"	addi	%0, %0, 2\n"
628c2ecf20Sopenharmony_ci		/* store residual byte if necessary */
638c2ecf20Sopenharmony_ci		"4:	andi	%4, %1, 0x01\n"
648c2ecf20Sopenharmony_ci		"	beq	%4, zero, 5f\n"
658c2ecf20Sopenharmony_ci		"	stb	%3, 0(%0)\n"
668c2ecf20Sopenharmony_ci		"5:\n"
678c2ecf20Sopenharmony_ci		: "=r" (destptr),	/* %0  Output */
688c2ecf20Sopenharmony_ci		  "=r" (charcnt),	/* %1  Output */
698c2ecf20Sopenharmony_ci		  "=r" (dwordcnt),	/* %2  Output */
708c2ecf20Sopenharmony_ci		  "=r" (fill8reg),	/* %3  Output */
718c2ecf20Sopenharmony_ci		  "=&r" (wrkrega)	/* %4  Output only */
728c2ecf20Sopenharmony_ci		: "r" (c),		/* %5  Input */
738c2ecf20Sopenharmony_ci		  "0" (s),		/* %0  Input/Output */
748c2ecf20Sopenharmony_ci		  "1" (count)		/* %1  Input/Output */
758c2ecf20Sopenharmony_ci		: "memory"		/* clobbered */
768c2ecf20Sopenharmony_ci	);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return s;
798c2ecf20Sopenharmony_ci}
80