blob: b77105e826c4b9363aaa84283fba11a6c11b71f6 [file] [log] [blame]
Prashant Patilfcb877a2017-03-16 18:07:00 +05301/*
2 * Copyright (c) 2017 Imagination Technologies.
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with
15 * the distribution.
16 * * Neither the name of Imagination Technologies nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <string.h>
34
35#define op_t unsigned long int
36
37#if !defined(UNALIGNED_INSTR_SUPPORT)
38/* does target have unaligned lw/ld/ualw/uald instructions? */
39#define UNALIGNED_INSTR_SUPPORT 0
40#if __mips_isa_rev < 6 && !__mips1
41#undef UNALIGNED_INSTR_SUPPORT
42#define UNALIGNED_INSTR_SUPPORT 1
43#endif
44#endif
45
46#if !defined(HW_UNALIGNED_SUPPORT)
47/* Does target have hardware support for unaligned accesses? */
48#define HW_UNALIGNED_SUPPORT 0
49#if __mips_isa_rev >= 6
50#undef HW_UNALIGNED_SUPPORT
51#define HW_UNALIGNED_SUPPORT 1
52#endif
53#endif
54
55#if __mips64
56typedef struct
57{
58 op_t B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8;
59} bits_t;
60#else
61typedef struct
62{
63 op_t B0:8, B1:8, B2:8, B3:8;
64} bits_t;
65#endif
66
67typedef union
68{
69 op_t v;
70 bits_t b;
71} bitfields_t;
72
73#if !HW_UNALIGNED_SUPPORT && UNALIGNED_INSTR_SUPPORT
74/* for MIPS GCC, there are no unaligned builtins - so this struct forces
75 the compiler to treat the pointer access as unaligned. */
76struct ulw
77{
78 op_t uli;
79} __attribute__ ((packed));
80#endif /* !HW_UNALIGNED_SUPPORT && UNALIGNED_INSTR_SUPPORT */
81
82#define DO_BYTE(i, ptdst) { \
83 *(ptdst+i) = a.b.B##i; \
84 if(a.b.B##i == '\0') \
85 return ret; \
86}
87
88#if __mips64
89#define DO_BYTES(val, dst) { \
90 bitfields_t a; \
91 char *tdst = (char *)(dst); \
92 a.v = val; \
93 DO_BYTE(0, tdst) \
94 DO_BYTE(1, tdst) \
95 DO_BYTE(2, tdst) \
96 DO_BYTE(3, tdst) \
97 DO_BYTE(4, tdst) \
98 DO_BYTE(5, tdst) \
99 DO_BYTE(6, tdst) \
100 DO_BYTE(7, tdst) \
101}
102#else
103#define DO_BYTES(val, dst) { \
104 bitfields_t a; \
105 char *tdst = (char *)(dst); \
106 a.v = val; \
107 DO_BYTE(0, tdst) \
108 DO_BYTE(1, tdst) \
109 DO_BYTE(2, tdst) \
110 DO_BYTE(3, tdst) \
111}
112#endif
113
114#define DO_WORD_ALIGNED(dst, src) { \
115 op_t val = *(src); \
116 if ((((val - mask_1) & ~val) & mask_128) != 0) { \
117 DO_BYTES(val, dst); \
118 } else *(dst) = val; \
119}
120
121#if !HW_UNALIGNED_SUPPORT
122#if UNALIGNED_INSTR_SUPPORT
123#define DO_WORD_UNALIGNED(dst, src) { \
124 op_t val = *(src); \
125 if ((((val - mask_1) & ~val) & mask_128) != 0) { \
126 DO_BYTES(val, dst); \
127 } else { \
128 struct ulw *a = (struct ulw *)(dst); \
129 a->uli = val; \
130 } \
131}
132#else
133#define DO_WORD_UNALIGNED(dst, src) { \
134 op_t val = *(src); \
135 if ((((val - mask_1) & ~val) & mask_128) != 0) { \
136 DO_BYTES(val, dst); \
137 } else { \
138 char *pdst = (char *) dst; \
139 const char *psrc = (const char *) src; \
140 for (; (*pdst = *psrc) != '\0'; ++psrc, ++pdst); \
141 return ret; \
142 } \
143}
144#endif /* UNALIGNED_INSTR_SUPPORT */
145
146#define PROCESS_UNALIGNED_WORDS(a, b) { \
147 while (1) { \
148 DO_WORD_UNALIGNED(a, b); \
149 DO_WORD_UNALIGNED(a + 1, b + 1); \
150 DO_WORD_UNALIGNED(a + 2, b + 2); \
151 DO_WORD_UNALIGNED(a + 3, b + 3); \
152 a += 4; \
153 b += 4; \
154 } \
155}
156#endif /* HW_UNALIGNED_SUPPORT */
157
158#define PROCESS_ALIGNED_WORDS(a, b) { \
159 while (1) { \
160 DO_WORD_ALIGNED(a, b); \
161 DO_WORD_ALIGNED(a + 1, b + 1); \
162 DO_WORD_ALIGNED(a + 2, b + 2); \
163 DO_WORD_ALIGNED(a + 3, b + 3); \
164 a += 4; \
165 b += 4; \
166 } \
167}
168
169char *
George Burgess IV90242352018-02-06 12:51:31 -0800170strcpy (char *to, const char *from)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530171{
172 char *ret = to;
173 op_t mask_1, mask_128;
174 const op_t *src;
175 op_t *dst;
176
177 for (; (*to = *from) != '\0' && ((size_t) from % sizeof (op_t)) != 0; ++from, ++to);
178
179 if(*to != '\0') {
180 __asm__ volatile (
181 "li %0, 0x01010101 \n\t"
182 : "=r" (mask_1)
183 );
184#if __mips64
185 mask_1 |= mask_1 << 32;
186#endif
187 mask_128 = mask_1 << 7;
188
189 src = (const op_t *) from;
190 dst = (op_t *) to;
191
192#if HW_UNALIGNED_SUPPORT
193 PROCESS_ALIGNED_WORDS(dst, src);
194#else
195 if (((unsigned long) dst) % sizeof (op_t) == 0) {
196 PROCESS_ALIGNED_WORDS(dst, src);
197 } else {
198 PROCESS_UNALIGNED_WORDS(dst, src);
199 }
200#endif
201 }
202
203 return ret;
204}