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

« back to all changes in this revision

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

  • Committer: Michael Hope
  • Date: 2010-09-02 00:46:57 UTC
  • Revision ID: michael.hope@linaro.org-20100902004657-4q6rn5888130zr3o
Pulled in the routines and packaged them up.

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