2002-12-10 Theodore A. Roth * libc/string/strstr.S: Index: libc/string/strstr.S =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/string/strstr.S,v retrieving revision 1.3 diff -u -r1.3 strstr.S --- libc/string/strstr.S 9 Sep 2002 22:22:39 -0000 1.3 +++ libc/string/strstr.S 10 Dec 2002 19:47:36 -0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, Jochen Pernsteiner +/* Copyright (c) 2002, Philip Soeberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,8 +30,8 @@ strstr.S Search string contained in a string - Contributors: - Created by Jochen Pernsteiner + Contributed by: + Philip Soeberg */ #include "macros.inc" @@ -40,7 +40,12 @@ #define s1_lo r24 #define s2_hi r23 #define s2_lo r22 -#define tmp r21 + +#define chr1_lo r18 /* first char of str1 (updated in loop) */ +#define chr1_hi r19 /* second char of str1 (updated in loop) */ +#define chr2_lo r20 /* first char of str2 (updated in loop) */ +#define chr2_hi r21 /* second char of str2 (updated in loop) */ + #define ret_hi r25 #define ret_lo r24 @@ -49,44 +54,76 @@ \brief Locate a substring. The strstr() function finds the first occurrence of the substring \c s2 - in the string s1. The terminating `\0' characters are not + in the string s1. The terminating '\0' characters are not compared. \returns The strstr() function returns a pointer to the beginning of the - substring, or NULL if the substring is not found. */ + substring, or NULL if the substring is not found. If \c s2 points to a + string of zero length, the function returns s1. */ .text .global _U(strstr) .type _U(strstr), @function _U(strstr): - LOAD_X(s1_lo, s1_hi) - LOAD_Z(s2_lo, s2_hi) - ld tmp, Z+ - tst tmp - breq .strstr_ret - clr ret_lo - clr ret_hi -.strstr_loop: - ld __tmp_reg__, X+ - tst __tmp_reg__ - breq .strstr_ret0 - cp __tmp_reg__, tmp - brne .strstr_loop - adiw ret_lo, 1 - ld tmp, Z+ - tst tmp - brne .strstr_loop - sub XL, ret_lo - sbc XH, ret_hi - mov ret_lo, XL - mov ret_hi, XH - ret -.strstr_ret0: - clr ret_lo - clr ret_hi + ;; Store temp registers + push r18 + push r19 + push r20 + push r21 + + LOAD_X(s1_lo, s1_hi) + LOAD_Z(s2_lo, s2_hi) + ld chr2_lo, Z+ + tst chr2_lo ; is str2 empty? + breq .strstr_empty_str2 + +.strstr_findstart: + LOAD_Z(s2_lo, s2_hi) ; reset Z pointer + ld chr2_lo, Z+ ; fetch first char + +.strstr_findstart_loop: ; Find first char + ld chr1_lo, X+ + tst chr1_lo ; Is str1 @ end? + breq .strstr_no_match ; then return + cp chr1_lo, chr2_lo ; Is chr1 == chr2? + + mov ret_lo, XL ; store return value + mov ret_hi, XH + + brne .strstr_findstart_loop ; If, then start checking string + +.strstr_stringloop: + ld chr2_lo, Z+ + tst chr2_lo + breq .strstr_match + ld chr1_lo, X + tst chr1_lo + breq .strstr_no_match + cp chr1_lo, chr2_lo + brne .strstr_findstart + adiw XL, 1 ; Increment X with one + rjmp .strstr_stringloop + +;; Empty str2 string, return str1 (ANSI mandated!) +.strstr_empty_str2: + mov ret_lo, s1_lo + mov ret_hi, s1_hi + rjmp .strstr_ret + +.strstr_no_match: + clr ret_lo + clr ret_hi + rjmp .strstr_ret + +.strstr_match: + sbiw ret_lo, 1 + .strstr_ret: - ret + pop r21 ; Restore temp register + pop r20 + pop r19 + pop r18 + ret .strstr_end: .size _U(strstr), .strstr_end - _U(strstr) -