Linux Audio

Check our new training course

Loading...
v4.17
  1/*
  2 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  3 * Copyright (C) 2008-2009 PetaLogix
  4 * Copyright (C) 2007 John Williams
  5 *
  6 * Reasonably optimised generic C-code for memcpy on Microblaze
  7 * This is generic C code to do efficient, alignment-aware memmove.
  8 *
  9 * It is based on demo code originally Copyright 2001 by Intel Corp, taken from
 10 * http://www.embedded.com/showArticle.jhtml?articleID=19205567
 11 *
 12 * Attempts were made, unsuccessfully, to contact the original
 13 * author of this code (Michael Morrow, Intel).  Below is the original
 14 * copyright notice.
 15 *
 16 * This software has been developed by Intel Corporation.
 17 * Intel specifically disclaims all warranties, express or
 18 * implied, and all liability, including consequential and
 19 * other indirect damages, for the use of this program, including
 20 * liability for infringement of any proprietary rights,
 21 * and including the warranties of merchantability and fitness
 22 * for a particular purpose. Intel does not assume any
 23 * responsibility for and errors which may appear in this program
 24 * not any responsibility to update it.
 25 */
 26
 27#include <linux/export.h>
 28#include <linux/types.h>
 29#include <linux/stddef.h>
 30#include <linux/compiler.h>
 31#include <linux/string.h>
 32
 33#ifdef __HAVE_ARCH_MEMMOVE
 34#ifndef CONFIG_OPT_LIB_FUNCTION
 35void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 36{
 37	const char *src = v_src;
 38	char *dst = v_dst;
 39
 40	if (!c)
 41		return v_dst;
 42
 43	/* Use memcpy when source is higher than dest */
 44	if (v_dst <= v_src)
 45		return memcpy(v_dst, v_src, c);
 46
 47	/* copy backwards, from end to beginning */
 48	src += c;
 49	dst += c;
 50
 51	/* Simple, byte oriented memmove. */
 52	while (c--)
 53		*--dst = *--src;
 54
 55	return v_dst;
 56}
 57#else /* CONFIG_OPT_LIB_FUNCTION */
 58void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 59{
 60	const char *src = v_src;
 61	char *dst = v_dst;
 62	const uint32_t *i_src;
 63	uint32_t *i_dst;
 64
 65	if (!c)
 66		return v_dst;
 67
 68	/* Use memcpy when source is higher than dest */
 69	if (v_dst <= v_src)
 70		return memcpy(v_dst, v_src, c);
 71
 72	/* The following code tries to optimize the copy by using unsigned
 73	 * alignment. This will work fine if both source and destination are
 74	 * aligned on the same boundary. However, if they are aligned on
 75	 * different boundaries shifts will be necessary. This might result in
 76	 * bad performance on MicroBlaze systems without a barrel shifter.
 77	 */
 78	/* FIXME this part needs more test */
 79	/* Do a descending copy - this is a bit trickier! */
 80	dst += c;
 81	src += c;
 82
 83	if (c >= 4) {
 84		unsigned  value, buf_hold;
 85
 86		/* Align the destination to a word boundary. */
 87		/* This is done in an endian independent manner. */
 88
 89		switch ((unsigned long)dst & 3) {
 90		case 3:
 91			*--dst = *--src;
 92			--c;
 
 93		case 2:
 94			*--dst = *--src;
 95			--c;
 
 96		case 1:
 97			*--dst = *--src;
 98			--c;
 99		}
100
101		i_dst = (void *)dst;
102		/* Choose a copy scheme based on the source */
103		/* alignment relative to dstination. */
104		switch ((unsigned long)src & 3) {
105		case 0x0:	/* Both byte offsets are aligned */
106
107			i_src  = (const void *)src;
108
109			for (; c >= 4; c -= 4)
110				*--i_dst = *--i_src;
111
112			src  = (const void *)i_src;
113			break;
114		case 0x1:	/* Unaligned - Off by 1 */
115			/* Word align the source */
116			i_src = (const void *) (((unsigned)src + 4) & ~3);
117#ifndef __MICROBLAZEEL__
118			/* Load the holding buffer */
119			buf_hold = *--i_src >> 24;
120
121			for (; c >= 4; c -= 4) {
122				value = *--i_src;
123				*--i_dst = buf_hold << 8 | value;
124				buf_hold = value >> 24;
125			}
126#else
127			/* Load the holding buffer */
128			buf_hold = (*--i_src & 0xFF) << 24;
129
130			for (; c >= 4; c -= 4) {
131				value = *--i_src;
132				*--i_dst = buf_hold |
133						((value & 0xFFFFFF00) >> 8);
134				buf_hold = (value  & 0xFF) << 24;
135			}
136#endif
137			/* Realign the source */
138			src = (const void *)i_src;
139			src += 1;
140			break;
141		case 0x2:	/* Unaligned - Off by 2 */
142			/* Word align the source */
143			i_src = (const void *) (((unsigned)src + 4) & ~3);
144#ifndef __MICROBLAZEEL__
145			/* Load the holding buffer */
146			buf_hold = *--i_src >> 16;
147
148			for (; c >= 4; c -= 4) {
149				value = *--i_src;
150				*--i_dst = buf_hold << 16 | value;
151				buf_hold = value >> 16;
152			}
153#else
154			/* Load the holding buffer */
155			buf_hold = (*--i_src & 0xFFFF) << 16;
156
157			for (; c >= 4; c -= 4) {
158				value = *--i_src;
159				*--i_dst = buf_hold |
160						((value & 0xFFFF0000) >> 16);
161				buf_hold = (value & 0xFFFF) << 16;
162			}
163#endif
164			/* Realign the source */
165			src = (const void *)i_src;
166			src += 2;
167			break;
168		case 0x3:	/* Unaligned - Off by 3 */
169			/* Word align the source */
170			i_src = (const void *) (((unsigned)src + 4) & ~3);
171#ifndef __MICROBLAZEEL__
172			/* Load the holding buffer */
173			buf_hold = *--i_src >> 8;
174
175			for (; c >= 4; c -= 4) {
176				value = *--i_src;
177				*--i_dst = buf_hold << 24 | value;
178				buf_hold = value >> 8;
179			}
180#else
181			/* Load the holding buffer */
182			buf_hold = (*--i_src & 0xFFFFFF) << 8;
183
184			for (; c >= 4; c -= 4) {
185				value = *--i_src;
186				*--i_dst = buf_hold |
187						((value & 0xFF000000) >> 24);
188				buf_hold = (value & 0xFFFFFF) << 8;
189			}
190#endif
191			/* Realign the source */
192			src = (const void *)i_src;
193			src += 3;
194			break;
195		}
196		dst = (void *)i_dst;
197	}
198
199	/* simple fast copy, ... unless a cache boundary is crossed */
200	/* Finish off any remaining bytes */
201	switch (c) {
202	case 4:
203		*--dst = *--src;
 
204	case 3:
205		*--dst = *--src;
 
206	case 2:
207		*--dst = *--src;
 
208	case 1:
209		*--dst = *--src;
210	}
211	return v_dst;
212}
213#endif /* CONFIG_OPT_LIB_FUNCTION */
214EXPORT_SYMBOL(memmove);
215#endif /* __HAVE_ARCH_MEMMOVE */
v6.9.4
  1/*
  2 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  3 * Copyright (C) 2008-2009 PetaLogix
  4 * Copyright (C) 2007 John Williams
  5 *
  6 * Reasonably optimised generic C-code for memcpy on Microblaze
  7 * This is generic C code to do efficient, alignment-aware memmove.
  8 *
  9 * It is based on demo code originally Copyright 2001 by Intel Corp, taken from
 10 * http://www.embedded.com/showArticle.jhtml?articleID=19205567
 11 *
 12 * Attempts were made, unsuccessfully, to contact the original
 13 * author of this code (Michael Morrow, Intel).  Below is the original
 14 * copyright notice.
 15 *
 16 * This software has been developed by Intel Corporation.
 17 * Intel specifically disclaims all warranties, express or
 18 * implied, and all liability, including consequential and
 19 * other indirect damages, for the use of this program, including
 20 * liability for infringement of any proprietary rights,
 21 * and including the warranties of merchantability and fitness
 22 * for a particular purpose. Intel does not assume any
 23 * responsibility for and errors which may appear in this program
 24 * not any responsibility to update it.
 25 */
 26
 27#include <linux/export.h>
 28#include <linux/types.h>
 29#include <linux/stddef.h>
 30#include <linux/compiler.h>
 31#include <linux/string.h>
 32
 33#ifdef CONFIG_OPT_LIB_FUNCTION
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 34void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 35{
 36	const char *src = v_src;
 37	char *dst = v_dst;
 38	const uint32_t *i_src;
 39	uint32_t *i_dst;
 40
 41	if (!c)
 42		return v_dst;
 43
 44	/* Use memcpy when source is higher than dest */
 45	if (v_dst <= v_src)
 46		return memcpy(v_dst, v_src, c);
 47
 48	/* The following code tries to optimize the copy by using unsigned
 49	 * alignment. This will work fine if both source and destination are
 50	 * aligned on the same boundary. However, if they are aligned on
 51	 * different boundaries shifts will be necessary. This might result in
 52	 * bad performance on MicroBlaze systems without a barrel shifter.
 53	 */
 54	/* FIXME this part needs more test */
 55	/* Do a descending copy - this is a bit trickier! */
 56	dst += c;
 57	src += c;
 58
 59	if (c >= 4) {
 60		unsigned  value, buf_hold;
 61
 62		/* Align the destination to a word boundary. */
 63		/* This is done in an endian independent manner. */
 64
 65		switch ((unsigned long)dst & 3) {
 66		case 3:
 67			*--dst = *--src;
 68			--c;
 69			fallthrough;
 70		case 2:
 71			*--dst = *--src;
 72			--c;
 73			fallthrough;
 74		case 1:
 75			*--dst = *--src;
 76			--c;
 77		}
 78
 79		i_dst = (void *)dst;
 80		/* Choose a copy scheme based on the source */
 81		/* alignment relative to destination. */
 82		switch ((unsigned long)src & 3) {
 83		case 0x0:	/* Both byte offsets are aligned */
 84
 85			i_src  = (const void *)src;
 86
 87			for (; c >= 4; c -= 4)
 88				*--i_dst = *--i_src;
 89
 90			src  = (const void *)i_src;
 91			break;
 92		case 0x1:	/* Unaligned - Off by 1 */
 93			/* Word align the source */
 94			i_src = (const void *) (((unsigned)src + 4) & ~3);
 95#ifndef __MICROBLAZEEL__
 96			/* Load the holding buffer */
 97			buf_hold = *--i_src >> 24;
 98
 99			for (; c >= 4; c -= 4) {
100				value = *--i_src;
101				*--i_dst = buf_hold << 8 | value;
102				buf_hold = value >> 24;
103			}
104#else
105			/* Load the holding buffer */
106			buf_hold = (*--i_src & 0xFF) << 24;
107
108			for (; c >= 4; c -= 4) {
109				value = *--i_src;
110				*--i_dst = buf_hold |
111						((value & 0xFFFFFF00) >> 8);
112				buf_hold = (value  & 0xFF) << 24;
113			}
114#endif
115			/* Realign the source */
116			src = (const void *)i_src;
117			src += 1;
118			break;
119		case 0x2:	/* Unaligned - Off by 2 */
120			/* Word align the source */
121			i_src = (const void *) (((unsigned)src + 4) & ~3);
122#ifndef __MICROBLAZEEL__
123			/* Load the holding buffer */
124			buf_hold = *--i_src >> 16;
125
126			for (; c >= 4; c -= 4) {
127				value = *--i_src;
128				*--i_dst = buf_hold << 16 | value;
129				buf_hold = value >> 16;
130			}
131#else
132			/* Load the holding buffer */
133			buf_hold = (*--i_src & 0xFFFF) << 16;
134
135			for (; c >= 4; c -= 4) {
136				value = *--i_src;
137				*--i_dst = buf_hold |
138						((value & 0xFFFF0000) >> 16);
139				buf_hold = (value & 0xFFFF) << 16;
140			}
141#endif
142			/* Realign the source */
143			src = (const void *)i_src;
144			src += 2;
145			break;
146		case 0x3:	/* Unaligned - Off by 3 */
147			/* Word align the source */
148			i_src = (const void *) (((unsigned)src + 4) & ~3);
149#ifndef __MICROBLAZEEL__
150			/* Load the holding buffer */
151			buf_hold = *--i_src >> 8;
152
153			for (; c >= 4; c -= 4) {
154				value = *--i_src;
155				*--i_dst = buf_hold << 24 | value;
156				buf_hold = value >> 8;
157			}
158#else
159			/* Load the holding buffer */
160			buf_hold = (*--i_src & 0xFFFFFF) << 8;
161
162			for (; c >= 4; c -= 4) {
163				value = *--i_src;
164				*--i_dst = buf_hold |
165						((value & 0xFF000000) >> 24);
166				buf_hold = (value & 0xFFFFFF) << 8;
167			}
168#endif
169			/* Realign the source */
170			src = (const void *)i_src;
171			src += 3;
172			break;
173		}
174		dst = (void *)i_dst;
175	}
176
177	/* simple fast copy, ... unless a cache boundary is crossed */
178	/* Finish off any remaining bytes */
179	switch (c) {
180	case 4:
181		*--dst = *--src;
182		fallthrough;
183	case 3:
184		*--dst = *--src;
185		fallthrough;
186	case 2:
187		*--dst = *--src;
188		fallthrough;
189	case 1:
190		*--dst = *--src;
191	}
192	return v_dst;
193}
 
194EXPORT_SYMBOL(memmove);
195#endif /* CONFIG_OPT_LIB_FUNCTION */