1/*******************************************************************************
2 *
3 * Copyright (c) 1993 Intel Corporation
4 *
5 * Intel hereby grants you permission to copy, modify, and distribute this
6 * software and its documentation.  Intel grants this permission provided
7 * that the above copyright notice appears in all copies and that both the
8 * copyright notice and this permission notice appear in supporting
9 * documentation.  In addition, Intel grants this permission provided that
10 * you prominently mark as "not part of the original" any modifications
11 * made to this software or documentation, and that the name of Intel
12 * Corporation not be used in advertising or publicity pertaining to
13 * distribution of the software or the documentation without specific,
14 * written prior permission.
15 *
16 * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR
17 * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY
18 * OR FITNESS FOR A PARTICULAR PURPOSE.  Intel makes no guarantee or
19 * representations regarding the use of, or the results of the use of,
20 * the software and documentation in terms of correctness, accuracy,
21 * reliability, currentness, or otherwise; and you rely on the software,
22 * documentation and results solely at your own risk.
23 *
24 * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
25 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
26 * OF ANY KIND.  IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM
27 * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER.
28 *
29 ******************************************************************************/
30
31#include <picolibc.h>
32
33	.file "strcpy.s"
34#ifdef	__PIC
35	.pic
36#endif
37#ifdef	__PID
38	.pid
39#endif
40/*
41 * (c) copyright 1988,1993 Intel Corp., all rights reserved
42 */
43/*
44	procedure strcpy  (optimized assembler version for the 80960K series)
45	procedure strcat  (optimized assembler version for the 80960K series)
46
47	dest_addr = strcpy (dest_addr, src_addr)
48
49	copy the null terminated string pointed to by src_addr to
50	the string space pointed to by dest_addr.  Return the original
51	dest_addr.
52
53	This routine will fail if the source and destination string
54	overlap (in particular, if the end of the source is overlapped
55	by the beginning of the destination).  The behavior is undefined.
56	This is acceptable according to the draft C standard.
57
58	Undefined behavior will also occur if the end of the source string
59	(i.e. the terminating null byte) is in the last two words of the
60	program's allocated memory space.  This is so because strcpy fetches
61	ahead.  Disallowing the fetch ahead would impose a severe performance
62	penalty.
63
64	Strategy:
65
66	Fetch the source string and store the destination string by words
67	until the null byte is encountered.  When the word with the null
68	byte is reached, store it by bytes up through the null byte only.
69
70	Tactics:
71
72	1) Do NOT try to fetch and store the words in a word aligned manner
73	because, in my judgement, the performance degradation experienced due
74 	to non-aligned accesses does NOT outweigh the time and complexity added
75	by the preamble and convoluted body that would be necessary to assure
76	alignment.  This is supported by the intuition that most source and
77	destination strings will be word aligned to begin with.
78
79
80	procedure strcat
81
82	dest_addr = strcat (dest_addr, src_addr)
83
84	Appends the string pointed to by src_addr to the string pointed
85	to by dest_addr.  The first character of the source string is
86	copied to the location initially occupied by the trailing null
87	byte of the destination string.  Thereafter, characters are copied
88	from the source to the destination up thru the null byte that
89	trails the source string.
90
91	See the strcpy routine, above, for its caveats, as they apply here too.
92
93	Strategy:
94
95	Skip to the end (null byte) of the destination string, and then drop
96	into the strcpy code.
97
98	Tactics:
99
100	Skipping to the null byte is Ldone by reading the destination string
101	in long-words and scanbyte'ing them, then examining the bytes of the
102	word that contains the null byte, until the address of the null byte is
103	known.  Then we drop into the strcpy routine.  It is probable (approx.
104	three out of four times) that the destination string as strcpy sees
105	it will NOT be word aligned (i.e. that the null byte won't be the
106	last byte of a word).  But it is not worth the complication to that
107	routine to force word aligned memory accesses to be gaurenteed.
108*/
109	.globl _strcpy, _strcat
110	.globl __strcpy, __strcat
111	.leafproc _strcpy,__strcpy
112	.leafproc _strcat,__strcat
113	.align    2
114_strcat:
115#ifndef __PIC
116 	lda	Lrett,g14
117#else
118 	lda	Lrett-(.+8)(ip),g14
119#endif
120__strcat:
121	mov	g14,g13		# preserve return address
122	ldl	(g0),g4		# fetch first two words
123	addo	8,g0,g2		# post-increment src word pointer
124	lda	0xff,g3		# byte extraction mask
125
126Lsearch_for_word_with_null_byte:
127	scanbyte 0,g4		# check for null byte
128	mov	g5,g7		# copy second word
129	bo.f	Lsearch_for_null	# branch if null found
130	scanbyte 0,g7		# check for null byte
131	ldl	(g2),g4		# fetch next pair of word of src
132	addo	8,g2,g2		# post-increment src word pointer
133	bno	Lsearch_for_word_with_null_byte	# branch if null not found yet
134
135	subo	4,g2,g2		# back up the byte pointer
136	mov	g7,g4		# move word with null to search word
137Lsearch_for_null:
138	subo	9,g2,g5		# back up the byte pointer
139Lsearch_for_null.a:
140	and	g4,g3,g6	# extract byte
141	cmpo	0,g6		# is it null?
142	addo	1,g5,g5		# bump src byte ptr
143	shro	8,g4,g4		# shift word to position next byte
144	bne	Lsearch_for_null.a
145	b	Lend_of_dest_found
146
147_strcpy:
148#ifndef __PIC
149 	lda	Lrett,g14
150#else
151 	lda	Lrett-(.+8)(ip),g14
152#endif
153__strcpy:
154	mov	g0, g5
155Lend_of_dest_found:
156	ld	(g1), g2	# fetch first word of source
157	mov	g14,g6		# preserve return address
158	lda	0xff, g3	# byte extraction mask = 0xff;
159Lwloop:				# word copying loop
160	addo	4, g1, g1	# post-increment source ptr
161	scanbyte 0, g2		# does source word contain null byte?
162	mov	g2, g4		# save a copy of the source word
163	be	Lcloop		# branch if null present
164	ld	(g1), g2	# pre-fetch next word of source
165	st	g4, (g5)	# store current word
166	addo	4, g5, g5	# post-increment dest ptr
167	b	Lwloop
168
169Lcloop:				# character copying loop
170	and	g3, g4, g14	# extract next char
171	shro	8, g4, g4	# position word for next byte extraction
172	cmpo	0, g14 		# is it null?
173	stob	g14, (g5)	# store the byte
174	addo	1, g5, g5	# post-increment dest ptr
175	bne	Lcloop		# quit if null encountered
176
177	bx	(g6)		# g0 = dest string address; g14 = 0
178Lrett:
179	ret
180