~linaro-toolchain-dev/cortex-strings/trunk

« back to all changes in this revision

Viewing changes to src/thumb-2/strcmp.c

  • Committer: Dr. David Alan Gilbert
  • Date: 2011-09-15 14:14:12 UTC
  • Revision ID: david.gilbert@linaro.org-20110915141412-t3icwo8hrgo0rysq
Remove strcmp from src and build (keep tests and reference for now)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2008 ARM Ltd
3
 
 * All rights reserved.
4
 
 *
5
 
 * Redistribution and use in source and binary forms, with or without
6
 
 * modification, are permitted provided that the following conditions
7
 
 * are met:
8
 
 * 1. Redistributions of source code must retain the above copyright
9
 
 *    notice, this list of conditions and the following disclaimer.
10
 
 * 2. Redistributions in binary form must reproduce the above copyright
11
 
 *    notice, this list of conditions and the following disclaimer in the
12
 
 *    documentation and/or other materials provided with the distribution.
13
 
 * 3. The name of the company may not be used to endorse or promote
14
 
 *    products derived from this software without specific prior written
15
 
 *    permission.
16
 
 *
17
 
 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 
 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22
 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 
 */
28
 
 
29
 
/* For GLIBC:
30
 
#include <string.h>
31
 
#include <memcopy.h>
32
 
 
33
 
#undef strcmp
34
 
*/
35
 
 
36
 
#ifdef __ARMEB__
37
 
#define SHFT2LSB "lsl"
38
 
#define SHFT2MSB "lsr"
39
 
#define MSB "0x000000ff"
40
 
#define LSB "0xff000000"
41
 
#else
42
 
#define SHFT2LSB "lsr"
43
 
#define SHFT2MSB "lsl"
44
 
#define MSB "0xff000000"
45
 
#define LSB "0x000000ff"
46
 
#endif
47
 
 
48
 
#ifdef __thumb2__
49
 
#define magic1(REG) "#0x01010101"
50
 
#define magic2(REG) "#0x80808080"
51
 
#else
52
 
#define magic1(REG) #REG
53
 
#define magic2(REG) #REG ", lsl #7"
54
 
#endif
55
 
 
56
 
int 
57
 
__attribute__((naked)) strcmp (const char* s1, const char* s2)
58
 
{
59
 
  asm(
60
 
#if !(defined(__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
61
 
      (defined (__thumb__) && !defined (__thumb2__)))
62
 
      "pld      [r0, #0]\n\t"
63
 
      "pld      [r1, #0]\n\t"
64
 
      "eor      r2, r0, r1\n\t"
65
 
      "tst      r2, #3\n\t"
66
 
      /* Strings not at same byte offset from a word boundary.  */
67
 
      "bne      strcmp_unaligned\n\t"
68
 
      "ands     r2, r0, #3\n\t"
69
 
      "bic      r0, r0, #3\n\t"
70
 
      "bic      r1, r1, #3\n\t"
71
 
      "ldr      ip, [r0], #4\n\t"
72
 
      "it       eq\n\t"
73
 
      "ldreq    r3, [r1], #4\n\t"
74
 
      "beq      1f\n\t"
75
 
      /* Although s1 and s2 have identical initial alignment, they are
76
 
         not currently word aligned.  Rather than comparing bytes,
77
 
         make sure that any bytes fetched from before the addressed
78
 
         bytes are forced to 0xff.  Then they will always compare
79
 
         equal.  */
80
 
      "eor      r2, r2, #3\n\t"
81
 
      "lsl      r2, r2, #3\n\t"
82
 
      "mvn      r3, #"MSB"\n\t"
83
 
      SHFT2LSB" r2, r3, r2\n\t"
84
 
      "ldr      r3, [r1], #4\n\t"
85
 
      "orr      ip, ip, r2\n\t"
86
 
      "orr      r3, r3, r2\n"
87
 
 "1:\n\t"
88
 
#ifndef __thumb2__
89
 
      /* Load the 'magic' constant 0x01010101.  */
90
 
      "str      r4, [sp, #-4]!\n\t"
91
 
      "mov      r4, #1\n\t"
92
 
      "orr      r4, r4, r4, lsl #8\n\t"
93
 
      "orr      r4, r4, r4, lsl #16\n"
94
 
#endif
95
 
      ".p2align 2\n"
96
 
 "4:\n\t"
97
 
      "pld      [r0, #8]\n\t"
98
 
      "pld      [r1, #8]\n\t"
99
 
      "sub      r2, ip, "magic1(r4)"\n\t"
100
 
      "cmp      ip, r3\n\t"
101
 
      "itttt    eq\n\t"
102
 
      /* check for any zero bytes in first word */
103
 
      "biceq    r2, r2, ip\n\t"
104
 
      "tsteq    r2, "magic2(r4)"\n\t"
105
 
      "ldreq    ip, [r0], #4\n\t"
106
 
      "ldreq    r3, [r1], #4\n\t"
107
 
      "beq      4b\n"
108
 
 "2:\n\t"
109
 
      /* There's a zero or a different byte in the word */
110
 
      SHFT2MSB" r0, ip, #24\n\t"
111
 
      SHFT2LSB" ip, ip, #8\n\t"
112
 
      "cmp      r0, #1\n\t"
113
 
      "it       cs\n\t"
114
 
      "cmpcs    r0, r3, "SHFT2MSB" #24\n\t"
115
 
      "it       eq\n\t"
116
 
      SHFT2LSB"eq r3, r3, #8\n\t"
117
 
      "beq      2b\n\t"
118
 
      /* On a big-endian machine, r0 contains the desired byte in bits
119
 
         0-7; on a little-endian machine they are in bits 24-31.  In
120
 
         both cases the other bits in r0 are all zero.  For r3 the
121
 
         interesting byte is at the other end of the word, but the
122
 
         other bits are not necessarily zero.  We need a signed result
123
 
         representing the differnece in the unsigned bytes, so for the
124
 
         little-endian case we can't just shift the interesting bits
125
 
         up.  */
126
 
#ifdef __ARMEB__
127
 
      "sub      r0, r0, r3, lsr #24\n\t"
128
 
#else
129
 
      "and      r3, r3, #255\n\t"
130
 
#ifdef __thumb2__
131
 
      /* No RSB instruction in Thumb2 */
132
 
      "lsr      r0, r0, #24\n\t"
133
 
      "sub      r0, r0, r3\n\t"
134
 
#else
135
 
      "rsb      r0, r3, r0, lsr #24\n\t"
136
 
#endif
137
 
#endif
138
 
#ifndef __thumb2__
139
 
      "ldr      r4, [sp], #4\n\t"
140
 
#endif
141
 
      "BX LR"
142
 
#elif (defined (__thumb__) && !defined (__thumb2__))
143
 
  "1:\n\t"
144
 
      "ldrb     r2, [r0]\n\t"
145
 
      "ldrb     r3, [r1]\n\t"
146
 
      "add      r0, r0, #1\n\t"
147
 
      "add      r1, r1, #1\n\t"
148
 
      "cmp      r2, #0\n\t"
149
 
      "beq      2f\n\t"
150
 
      "cmp      r2, r3\n\t"
151
 
      "beq      1b\n\t"
152
 
  "2:\n\t"
153
 
      "sub      r0, r2, r3\n\t"
154
 
      "bx       lr"
155
 
#else
156
 
 "3:\n\t"
157
 
      "ldrb     r2, [r0], #1\n\t"
158
 
      "ldrb     r3, [r1], #1\n\t"
159
 
      "cmp      r2, #1\n\t"
160
 
      "it       cs\n\t"
161
 
      "cmpcs    r2, r3\n\t"
162
 
      "beq      3b\n\t"
163
 
      "sub      r0, r2, r3\n\t"
164
 
      "BX LR"
165
 
#endif
166
 
      );
167
 
}
168
 
 
169
 
#if !(defined(__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
170
 
      (defined (__thumb__) && !defined (__thumb2__)))
171
 
static int __attribute__((naked, used)) 
172
 
strcmp_unaligned(const char* s1, const char* s2)
173
 
{
174
 
#if 0
175
 
  /* The assembly code below is based on the following alogrithm.  */
176
 
#ifdef __ARMEB__
177
 
#define RSHIFT <<
178
 
#define LSHIFT >>
179
 
#else
180
 
#define RSHIFT >>
181
 
#define LSHIFT <<
182
 
#endif
183
 
 
184
 
#define body(shift)                                                     \
185
 
  mask = 0xffffffffU RSHIFT shift;                                      \
186
 
  w1 = *wp1++;                                                          \
187
 
  w2 = *wp2++;                                                          \
188
 
  do                                                                    \
189
 
    {                                                                   \
190
 
      t1 = w1 & mask;                                                   \
191
 
      if (__builtin_expect(t1 != w2 RSHIFT shift, 0))                   \
192
 
        {                                                               \
193
 
          w2 RSHIFT= shift;                                             \
194
 
          break;                                                        \
195
 
        }                                                               \
196
 
      if (__builtin_expect(((w1 - b1) & ~w1) & (b1 << 7), 0))           \
197
 
        {                                                               \
198
 
          /* See comment in assembler below re syndrome on big-endian */\
199
 
          if ((((w1 - b1) & ~w1) & (b1 << 7)) & mask)                   \
200
 
            w2 RSHIFT= shift;                                           \
201
 
          else                                                          \
202
 
            {                                                           \
203
 
              w2 = *wp2;                                                \
204
 
              t1 = w1 RSHIFT (32 - shift);                              \
205
 
              w2 = (w2 LSHIFT (32 - shift)) RSHIFT (32 - shift);        \
206
 
            }                                                           \
207
 
          break;                                                        \
208
 
        }                                                               \
209
 
      w2 = *wp2++;                                                      \
210
 
      t1 ^= w1;                                                         \
211
 
      if (__builtin_expect(t1 != w2 LSHIFT (32 - shift), 0))            \
212
 
        {                                                               \
213
 
          t1 = w1 >> (32 - shift);                                      \
214
 
          w2 = (w2 << (32 - shift)) RSHIFT (32 - shift);                \
215
 
          break;                                                        \
216
 
        }                                                               \
217
 
      w1 = *wp1++;                                                      \
218
 
    } while (1)
219
 
 
220
 
  const unsigned* wp1;
221
 
  const unsigned* wp2;
222
 
  unsigned w1, w2;
223
 
  unsigned mask;
224
 
  unsigned shift;
225
 
  unsigned b1 = 0x01010101;
226
 
  char c1, c2;
227
 
  unsigned t1;
228
 
 
229
 
  while (((unsigned) s1) & 3)
230
 
    {
231
 
      c1 = *s1++;
232
 
      c2 = *s2++;
233
 
      if (c1 == 0 || c1 != c2)
234
 
        return c1 - (int)c2;
235
 
    }
236
 
  wp1 = (unsigned*) (((unsigned)s1) & ~3);
237
 
  wp2 = (unsigned*) (((unsigned)s2) & ~3);
238
 
  t1 = ((unsigned) s2) & 3;
239
 
  if (t1 == 1)
240
 
    {
241
 
      body(8);
242
 
    }
243
 
  else if (t1 == 2)
244
 
    {
245
 
      body(16);
246
 
    }
247
 
  else
248
 
    {
249
 
      body (24);
250
 
    }
251
 
  
252
 
  do
253
 
    {
254
 
#ifdef __ARMEB__
255
 
      c1 = (char) t1 >> 24;
256
 
      c2 = (char) w2 >> 24;
257
 
#else
258
 
      c1 = (char) t1;
259
 
      c2 = (char) w2;
260
 
#endif
261
 
      t1 RSHIFT= 8;
262
 
      w2 RSHIFT= 8;
263
 
    } while (c1 != 0 && c1 == c2);
264
 
  return c1 - c2;
265
 
#endif
266
 
 
267
 
  asm("wp1 .req r0\n\t"
268
 
      "wp2 .req r1\n\t"
269
 
      "b1  .req r2\n\t"
270
 
      "w1  .req r4\n\t"
271
 
      "w2  .req r5\n\t"
272
 
      "t1  .req ip\n\t"
273
 
      "@ r3 is scratch\n"
274
 
 
275
 
      /* First of all, compare bytes until wp1(sp1) is word-aligned. */
276
 
 "1:\n\t"
277
 
      "tst      wp1, #3\n\t"
278
 
      "beq      2f\n\t"
279
 
      "ldrb     r2, [wp1], #1\n\t"
280
 
      "ldrb     r3, [wp2], #1\n\t"
281
 
      "cmp      r2, #1\n\t"
282
 
      "it       cs\n\t"
283
 
      "cmpcs    r2, r3\n\t"
284
 
      "beq      1b\n\t"
285
 
      "sub      r0, r2, r3\n\t"
286
 
      "BX LR\n"
287
 
 
288
 
 "2:\n\t"
289
 
      "str      r5, [sp, #-4]!\n\t"
290
 
      "str      r4, [sp, #-4]!\n\t"
291
 
      //      "stmfd    sp!, {r4, r5}\n\t"
292
 
      "mov      b1, #1\n\t"
293
 
      "orr      b1, b1, b1, lsl #8\n\t"
294
 
      "orr      b1, b1, b1, lsl #16\n\t"
295
 
 
296
 
      "and      t1, wp2, #3\n\t"
297
 
      "bic      wp2, wp2, #3\n\t"
298
 
      "ldr      w1, [wp1], #4\n\t"
299
 
      "ldr      w2, [wp2], #4\n\t"
300
 
      "cmp      t1, #2\n\t"
301
 
      "beq      2f\n\t"
302
 
      "bhi      3f\n"
303
 
 
304
 
      /* Critical inner Loop: Block with 3 bytes initial overlap */
305
 
      ".p2align 2\n"
306
 
 "1:\n\t"
307
 
      "bic      t1, w1, #"MSB"\n\t"
308
 
      "cmp      t1, w2, "SHFT2LSB" #8\n\t"
309
 
      "sub      r3, w1, b1\n\t"
310
 
      "bic      r3, r3, w1\n\t"
311
 
      "bne      4f\n\t"
312
 
      "ands     r3, r3, b1, lsl #7\n\t"
313
 
      "it       eq\n\t"
314
 
      "ldreq    w2, [wp2], #4\n\t"
315
 
      "bne      5f\n\t"
316
 
      "eor      t1, t1, w1\n\t"
317
 
      "cmp      t1, w2, "SHFT2MSB" #24\n\t"
318
 
      "bne      6f\n\t"
319
 
      "ldr      w1, [wp1], #4\n\t"
320
 
      "b        1b\n"
321
 
 "4:\n\t"
322
 
      SHFT2LSB" w2, w2, #8\n\t"
323
 
      "b        8f\n"
324
 
 
325
 
 "5:\n\t"
326
 
#ifdef __ARMEB__
327
 
      /* The syndrome value may contain false ones if the string ends
328
 
         with the bytes 0x01 0x00 */
329
 
      "tst      w1, #0xff000000\n\t"
330
 
      "itt      ne\n\t"
331
 
      "tstne    w1, #0x00ff0000\n\t"
332
 
      "tstne    w1, #0x0000ff00\n\t"
333
 
      "beq      7f\n\t"
334
 
#else
335
 
      "bics     r3, r3, #0xff000000\n\t"
336
 
      "bne      7f\n\t"
337
 
#endif
338
 
      "ldrb     w2, [wp2]\n\t"
339
 
      SHFT2LSB" t1, w1, #24\n\t"
340
 
#ifdef __ARMEB__
341
 
      "lsl      w2, w2, #24\n\t"
342
 
#endif
343
 
      "b        8f\n"
344
 
 
345
 
 "6:\n\t"
346
 
      SHFT2LSB" t1, w1, #24\n\t"
347
 
      "and      w2, w2, #"LSB"\n\t"
348
 
      "b        8f\n"
349
 
 
350
 
      /* Critical inner Loop: Block with 2 bytes initial overlap */
351
 
      ".p2align 2\n"
352
 
 "2:\n\t"
353
 
      SHFT2MSB" t1, w1, #16\n\t"
354
 
      "sub      r3, w1, b1\n\t"
355
 
      SHFT2LSB" t1, t1, #16\n\t"
356
 
      "bic      r3, r3, w1\n\t"
357
 
      "cmp      t1, w2, "SHFT2LSB" #16\n\t"
358
 
      "bne      4f\n\t"
359
 
      "ands     r3, r3, b1, lsl #7\n\t"
360
 
      "it       eq\n\t"
361
 
      "ldreq    w2, [wp2], #4\n\t"
362
 
      "bne      5f\n\t"
363
 
      "eor      t1, t1, w1\n\t"
364
 
      "cmp      t1, w2, "SHFT2MSB" #16\n\t"
365
 
      "bne      6f\n\t"
366
 
      "ldr      w1, [wp1], #4\n\t"
367
 
      "b        2b\n"
368
 
 
369
 
 "5:\n\t"
370
 
#ifdef __ARMEB__
371
 
      /* The syndrome value may contain false ones if the string ends
372
 
         with the bytes 0x01 0x00 */
373
 
      "tst      w1, #0xff000000\n\t"
374
 
      "it       ne\n\t"
375
 
      "tstne    w1, #0x00ff0000\n\t"
376
 
      "beq      7f\n\t"
377
 
#else
378
 
      "lsls     r3, r3, #16\n\t"
379
 
      "bne      7f\n\t"
380
 
#endif
381
 
      "ldrh     w2, [wp2]\n\t"
382
 
      SHFT2LSB" t1, w1, #16\n\t"
383
 
#ifdef __ARMEB__
384
 
      "lsl      w2, w2, #16\n\t"
385
 
#endif
386
 
      "b        8f\n"
387
 
 
388
 
 "6:\n\t"
389
 
      SHFT2MSB" w2, w2, #16\n\t"
390
 
      SHFT2LSB" t1, w1, #16\n\t"
391
 
 "4:\n\t"
392
 
      SHFT2LSB" w2, w2, #16\n\t"
393
 
      "b        8f\n\t"
394
 
 
395
 
      /* Critical inner Loop: Block with 1 byte initial overlap */
396
 
      ".p2align 2\n"
397
 
 "3:\n\t"
398
 
      "and      t1, w1, #"LSB"\n\t"
399
 
      "cmp      t1, w2, "SHFT2LSB" #24\n\t"
400
 
      "sub      r3, w1, b1\n\t"
401
 
      "bic      r3, r3, w1\n\t"
402
 
      "bne      4f\n\t"
403
 
      "ands     r3, r3, b1, lsl #7\n\t"
404
 
      "it       eq\n\t"
405
 
      "ldreq    w2, [wp2], #4\n\t"
406
 
      "bne      5f\n\t"
407
 
      "eor      t1, t1, w1\n\t"
408
 
      "cmp      t1, w2, "SHFT2MSB" #8\n\t"
409
 
      "bne      6f\n\t"
410
 
      "ldr      w1, [wp1], #4\n\t"
411
 
      "b        3b\n"
412
 
 "4:\n\t"
413
 
      SHFT2LSB" w2, w2, #24\n\t"
414
 
      "b        8f\n"
415
 
 "5:\n\t"
416
 
      /* The syndrome value may contain false ones if the string ends
417
 
         with the bytes 0x01 0x00 */
418
 
      "tst      w1, #"LSB"\n\t"
419
 
      "beq      7f\n\t"
420
 
      "ldr      w2, [wp2], #4\n"
421
 
 "6:\n\t"
422
 
      SHFT2LSB" t1, w1, #8\n\t"
423
 
      "bic      w2, w2, #"MSB"\n\t"
424
 
      "b        8f\n"
425
 
 "7:\n\t"
426
 
      "mov      r0, #0\n\t"
427
 
      //      "ldmfd    sp!, {r4, r5}\n\t"
428
 
      "ldr      r4, [sp], #4\n\t"
429
 
      "ldr      r5, [sp], #4\n\t"
430
 
      "BX LR\n"
431
 
 "8:\n\t"
432
 
      "and      r2, t1, #"LSB"\n\t"
433
 
      "and      r0, w2, #"LSB"\n\t"
434
 
      "cmp      r0, #1\n\t"
435
 
      "it       cs\n\t"
436
 
      "cmpcs    r0, r2\n\t"
437
 
      "itt      eq\n\t"
438
 
      SHFT2LSB"eq       t1, t1, #8\n\t"
439
 
      SHFT2LSB"eq       w2, w2, #8\n\t"
440
 
      "beq      8b\n\t"
441
 
      "sub      r0, r2, r0\n\t"
442
 
      //      "ldmfd    sp!, {r4, r5}\n\t"
443
 
      "ldr      r4, [sp], #4\n\t"
444
 
      "ldr      r5, [sp], #4\n\t"
445
 
      "BX LR");
446
 
}
447
 
 
448
 
#endif
449
 
 
450
 
/* For GLIBC: libc_hidden_builtin_def (strcmp) */