1/* Copyright (c) 2009 Dmitry Xmelkov 2 All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in 11 the documentation and/or other materials provided with the 12 distribution. 13 * Neither the name of the copyright holders nor the names of 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 POSSIBILITY OF SUCH DAMAGE. 28*/ 29 30/* $Id: strtok_rP.S 2503 2016-02-07 22:59:47Z joerg_wunsch $ */ 31 32#if !defined(__AVR_TINY__) 33 34#if !defined(__DOXYGEN__) 35 36#include "asmdef.h" 37 38/* char *strtok_r (char *s, const char *delim, char **last) 39 { 40 char *p = *last; 41 const char *q; 42 char c, d; 43 44 if (!s) { 45 if (!p) return s; // end of string 46 s = p; // continue parsing 47 } 48 49 p = s; 50 for (;;) { // skip delimeters 51 s = p; // space optimization (vs. s = p-1) 52 if (!(c = *p++)) { 53 s = 0; 54 p = 0; 55 goto ret; 56 } 57 q = delim; 58 do { 59 if (!(d = *q++)) 60 goto find_end; 61 } while (d != c); 62 } 63 64 find_end: 65 do { 66 q = delim; 67 do { 68 d = *q++; 69 if (c == d) { 70 *--p = 0; 71 p++; 72 goto ret; 73 } 74 } while (d); 75 } while ((c = *p++) != 0); 76 p = 0; // stop parsing 77 ret: 78 *last = p; 79 return s; 80 } 81 */ 82 83#define str_hi r25 84#define str_lo r24 85#define dlm_lo r22 86#define lst_lo r20 87 88ENTRY strtok_rP 89 90/* Two variants below are different in registers to load chars. In case 91 of enhanced core it is convinient to use <R0,R1> pair as zero word. 92 In classic case it is optimal to load delimeter char (flash) to R0. 93 */ 94 95/* -------------------------------------------------------------------- */ 96#if __AVR_HAVE_LPMX__ 97 98# define dlm_ch r18 /* delimeter character */ 99# define str_ch r0 /* string character */ 100 101 X_movw ZL, lst_lo 102 ld XL, Z+ ; X = *last 103 ld XH, Z 104 ; check str 105 sbiw str_lo, 0 106 brne 1f 107 sbiw XL, 0 108 breq .Lret ; end of string 109 X_movw str_lo, XL ; continue parsing 110 111 ; skip delimeters 1121: X_movw XL, str_lo ; p = str 1132: X_movw str_lo, XL 114 ld str_ch, X+ 115 tst str_ch 116 brne 3f 117 X_movw str_lo, str_ch ; <r0,r1> 118 rjmp .Lclr 1193: X_movw ZL, dlm_lo 1204: lpm dlm_ch, Z+ 121 tst dlm_ch 122 breq 5f ; goto find 123 cp dlm_ch, str_ch 124 brne 4b 125 rjmp 2b ; skip 1 byte 126 127 ; find new token end 1285: X_movw ZL, dlm_lo 1296: lpm dlm_ch, Z+ 130 cp dlm_ch, str_ch ; str_ch != 0 131 brne 7f 132 st -X, __zero_reg__ 133 adiw XL, 1 134 rjmp .Lret 1357: tst dlm_ch 136 brne 6b 137 ; next str byte 138 ld str_ch, X+ 139 tst str_ch 140 brne 5b 141 142 ; stop parsing 143.Lclr: X_movw XL, str_ch ; <r0,r1> 144 ; save last pointer 145.Lret: X_movw ZL, lst_lo ; *last = X 146 st Z+, XL 147 st Z, XH 148 ret 149 150/* -------------------------------------------------------------------- */ 151#else /* !__AVR_HAVE_LPMX__ */ 152 153# define dlm_ch r0 /* delimeter character */ 154# define str_ch r18 /* string character */ 155 156 X_movw ZL, lst_lo 157 ld XL, Z+ ; X = *last 158 ld XH, Z 159 ; check str 160 sbiw str_lo, 0 161 brne 1f 162 sbiw XL, 0 163 breq .Lret ; end of string 164 X_movw str_lo, XL ; continue parsing 165 166 ; skip delimeters 1671: X_movw XL, str_lo ; p = str 1682: X_movw str_lo, XL 169 ld str_ch, X+ 170 tst str_ch 171 brne 3f 172 clr str_lo ; return value 173 clr str_hi 174 rjmp .Lclr 1753: X_movw ZL, dlm_lo 1764: lpm ; lpm r0,Z 177 adiw ZL, 1 178 tst dlm_ch 179 breq 5f ; goto find 180 cp dlm_ch, str_ch 181 brne 4b 182 rjmp 2b ; skip 1 byte 183 184 ; find new token end 1855: X_movw ZL, dlm_lo 1866: lpm ; lpm r0,Z 187 adiw ZL, 1 188 cp dlm_ch, str_ch ; str_ch != 0 189 brne 7f 190 st -X, __zero_reg__ 191 adiw XL, 1 192 rjmp .Lret 1937: tst dlm_ch 194 brne 6b 195 ; next str byte 196 ld str_ch, X+ 197 tst str_ch 198 brne 5b 199 200 ; stop parsing 201.Lclr: clr XL 202 clr XH 203 ; save last pointer 204.Lret: X_movw ZL, lst_lo ; *last = X 205 st Z+, XL 206 st Z, XH 207 ret 208 209/* -------------------------------------------------------------------- */ 210#endif /* !__AVR_HAVE_LPMX__ */ 211 212ENDFUNC 213 214#endif /* not __DOXYGEN__ */ 215 216#endif /* !defined(__AVR_TINY__) */ 217