Jens Arnold | 78826de | 2005-01-22 13:18:33 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2005 by Jens Arnold |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Jens Arnold | 78826de | 2005-01-22 13:18:33 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include "config.h" |
| 22 | |
| 23 | .section .icode,"ax",@progbits |
| 24 | |
| 25 | .align 2 |
| 26 | .global _strlen |
| 27 | .type _strlen,@function |
| 28 | |
| 29 | /* Works out the length of a string |
| 30 | * This version is optimized for speed |
| 31 | * |
| 32 | * arguments: |
| 33 | * r4 - start address |
| 34 | * |
| 35 | * return value: |
| 36 | * r0 - string length |
| 37 | * |
| 38 | * register usage: |
| 39 | * r0 - current address |
| 40 | * r1 - current value (byte/long) |
| 41 | * r2 - mask for alignment / zero (for cmp/str) |
| 42 | * r4 - start address |
| 43 | * |
| 44 | */ |
| 45 | |
| 46 | _strlen: |
| 47 | mov r4,r0 /* r0 = start address */ |
| 48 | tst #3,r0 /* long aligned? */ |
| 49 | bt .start_l /* yes, jump directly to the longword loop */ |
| 50 | |
| 51 | /* not long aligned: check the first 3 bytes */ |
| 52 | mov.b @r0+,r1 /* fetch first byte */ |
| 53 | tst r1,r1 /* byte == 0 ? */ |
| 54 | bt .hitzero /* yes, string end found */ |
| 55 | mov.b @r0+,r1 /* fetch second byte */ |
| 56 | mov #3,r2 /* prepare mask: r2 = 0..00000011b */ |
| 57 | tst r1,r1 /* byte == 0 ? */ |
| 58 | bt .hitzero /* yes, string end found */ |
| 59 | mov.b @r0+,r1 /* fetch third byte */ |
| 60 | not r2,r2 /* prepare mask: r2 = 1..11111100b */ |
| 61 | tst r1,r1 /* byte == 0 ? */ |
| 62 | bt .hitzero /* yes, string end found */ |
| 63 | |
| 64 | /* not yet found, fall through into longword loop */ |
| 65 | and r2,r0 /* align down to long bound */ |
| 66 | |
| 67 | /* main loop: check longwords */ |
| 68 | .start_l: |
| 69 | mov #0,r2 /* zero longword for cmp/str */ |
| 70 | .loop_l: |
| 71 | mov.l @r0+,r1 /* fetch long word */ |
| 72 | cmp/str r1,r2 /* any zero byte within? */ |
| 73 | bf .loop_l /* no, loop */ |
| 74 | add #-4,r0 /* set address back to start of this longword */ |
| 75 | |
| 76 | /* the last longword contains the string end: figure out the byte */ |
| 77 | mov.b @r0+,r1 /* fetch first byte */ |
| 78 | tst r1,r1 /* byte == 0 ? */ |
| 79 | bt .hitzero /* yes, string end found */ |
| 80 | mov.b @r0+,r1 /* fetch second byte */ |
| 81 | tst r1,r1 /* byte == 0 ? */ |
| 82 | bt .hitzero /* yes, string end found */ |
| 83 | mov.b @r0+,r1 /* fetch third byte */ |
| 84 | tst r1,r1 /* byte == 0 ? */ |
| 85 | bt .hitzero /* yes, string end found */ |
| 86 | rts /* must be the fourth byte */ |
| 87 | sub r4,r0 /* len = string_end - string_start */ |
| 88 | |
| 89 | .hitzero: |
| 90 | add #-1,r0 /* undo address increment */ |
| 91 | rts |
| 92 | sub r4,r0 /* len = string_end - string_start */ |
| 93 | |
| 94 | .end: |
| 95 | .size _strlen,.end-_strlen |
| 96 | |