devctl.h: update for POSIX-1.2024
[newlib-cygwin.git] / newlib / libc / machine / hppa / strncpy.S
blob37ed8323770080c8a728fc102710d9bf37f49bfc
1 /*
2  *  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
3  *
4  *  To anyone who acknowledges that this file is provided "AS IS"
5  *  without any express or implied warranty:
6  *      permission to use, copy, modify, and distribute this file
7  *  for any purpose is hereby granted without fee, provided that
8  *  the above copyright notice and this notice appears in all
9  *  copies, and that the name of Hewlett-Packard Company not be
10  *  used in advertising or publicity pertaining to distribution
11  *  of the software without specific, written prior permission.
12  *  Hewlett-Packard Company makes no representations about the
13  *  suitability of this software for any purpose.
14  */
16 /* HPUX_ID:     @(#) $Revision$ */
18  * strncpy(s1, s2, n)
19  *
20  * Copy s2 to s1, truncating or null-padding to always copy n bytes
21  * return s1
22  */
24 #include "DEFS.h"
26 #define d_addr  r26
27 #define s_addr  r25
28 #define count   r24
29 #define tmp1    r19
30 #define tmp2    r20
31 #define tmp3    r21
32 #define tmp4    r22
33 #define tmp5    arg3
34 #define save    r1
37 ENTRY(strncpy)
39         combt,=   s_addr,r0,pad_null_bytes1     /* if s2==NULL then pad nulls and exit */
40         copy      d_addr,ret0          /* The return value is defined to be the value of d_addr. DELAY SLOT*/
41         addibt,<,n  -4,count,byteloop     /* If count is <= 4 don't get fancy.*/
43         extru       s_addr,31,2,tmp1   /* Extract the low two bits of the source address.*/
44         extru       d_addr,31,2,tmp5   /* Extract the low two bits of the destination address.*/
45         add         count,tmp5,count   /* pre increment the count by the byte address so that the count is*/
46         comb,<>       tmp5,tmp1,not_aligned /* branch if tmp5<>tmp1. */
47         dep         0,31,2,s_addr      /* Compute the word address of the source.  DELAY SLOT.*/
48 /* aligned*/
49         combt,=         tmp5,r0,skip_mask
50         ldwm        4(0,s_addr),tmp1   /* tmp1 = *s_addr   s_addr += 4 (DELAY SLOT)*/
51         sh3add          tmp5,r0,save    /* compute mask in save*/
52         mtctl           save,11
53         zvdepi          -2,32,save
54         b               skip_mask       /* don't reload tmp1*/
55         or              save,tmp1,tmp1  /* or mask with data*/
57 chunks:
58         ldwm            4(0,s_addr),tmp1 /* get a word*/
60 skip_mask:
61         uxor,nbz        tmp1,r0,save    /* check for null*/
62         b,n             null1
63         addibf,<        -4,count,chunks
64         stbys,b,m   tmp1,4(0,d_addr)   /* store word (delay slot)*/
66 /* back_porch                              last word to store*/
67          addibt,=,n  4,count,done       /* if count = 0 we're, of course, done !*/
68          ldws        0(s_addr),tmp1     /* load up the back_porch*/
69          add         d_addr,count,d_addr/* final store address  is +1 too high !*/
70          sh3add         count,r0, save  /* setup right mask based on count*/
71          mtctl          save,r11
72          zvdepi         -2,32,save      /*save now has left-hand mask*/
73          uaddcm         r0,save,save    /*form right hand mask */
74          or             tmp1,save,tmp1  /*and insert data*/
75          uxor,nbz       tmp1,r0,save    /* check for null*/
76          b,n            null2
77          bv             0(r2)
78          stbys,e        tmp1,0(d_addr)  /* done */
80 /* Begin non_aligned code. */
81 not_aligned:
82         sub,>=       tmp5,tmp1,tmp3     /* compute the shift amt.and skip load if tmp5 > tmp1.*/
83         ldwm         4(0,s_addr),tmp1   /* load up the first word from the source. tmp1 = *s_addr++*/
84         zdep         tmp3,28,29,tmp4    /* compute the number of bits to shift */
85         mtctl        tmp4,11            /* load the shift count into cr11 = shift count register.*/
86         addibt,<,n   -4,count,chkchnk2 /* first step in pre adjustment of count for looping.*/
88         ldwm        4(0,s_addr),tmp2    /* get either first or second word from source. */
89         combt,=         tmp5,r0,skip_mask2 /* don't mask if whole word is valid*/
90         vshd        tmp1,tmp2,tmp3      /* position data !  (delay slot)*/
91         sh3add          tmp5,r0,save    /* setup r1*/
92         mtctl           save,r11        /* setup mask in save*/
93         zvdepi          -2,32,save
94         or              save, tmp3, tmp3
95         mtctl           tmp4,11            /* re-load the shift count into cr11 */
96         b               skip_mask2
97         copy            r0, tmp5        /* zero out tmp5 so we don't try to mask again*/
99 chunk2:
100         ldwm        4(0,s_addr),tmp2
101         vshd        tmp1,tmp2,tmp3 
103 skip_mask2:
104         uxor,nbz        tmp3, r0, save
105         b,n             null3
106         stbys,b,m   tmp3,4(0,d_addr)    /* store ! */
108         ldwm        4(0,s_addr),tmp1    /* get 2nd word ! */
109         vshd        tmp2,tmp1,tmp3      /* position data ! */
110         uxor,nbz        tmp3, r0, save
111         b,n             null4
113         addibf,<    -8,count,chunk2    /* If count is still >= 8 do another loop.*/
114         stbys,b,m   tmp3,4(0,d_addr)    /* store !*/
116 chkchnk2:
117         addibt,<,n  4,count,bp_0       /* if we don't have 4 bytes left then do the back porch (bp_0)*/
119 subchnk2: /* we have less than 8 chars to copy*/
121         ldwm        4(0,s_addr),tmp2    /* get next word !*/
122         combt,=         tmp5,r0,skip_mask3
123         vshd        tmp1,tmp2,tmp3      /* position data !*/
124         sh3add          tmp5,r0,save    /* setup r1*/
125         mtctl           save,r11        /* setup mask in save*/
126         zvdepi          -2,32,save
127         or              save, tmp3, tmp3
128         mtctl           tmp4,11         /* restore shift value again */
129         copy            r0, tmp5        /* zero out tmp5 so we don't try to mask again*/
130 skip_mask3:
131         uxor,nbz        tmp3,r0,save
132         b,n             null4
133         b               bp_1 /* we now have less than 4 bytes to move*/
134         stbys,b,m   tmp3,4(0,d_addr)    /* store !*/
136 bp_0:    
137         copy        tmp1,tmp2           /* switch registers used in the shift process.*/
138         addibt,<=,n  4,count,done        /* if count = -4 this implies that count = 0 -> done */
140 bp_1:
141         ldwm        4(0,s_addr),tmp1    /* get final word !        */
142         vshd        tmp2,tmp1,tmp3      /* position data !*/
143         uxor,sbz        tmp3,r0,save    /* if some-byte-zero */
144         b               no_null         /* don't goto no_null-find which null instead */
145         add             d_addr,count,d_addr     /* get d_addr ready for stbys,e */
146         extru,<>        save,7,8,r0
147         b               found_null5
148         copy            r0, tmp5
149         extru,<>        save,15,8,r0
150         b               found_null5
151         ldil            0x1FE000,tmp5           /* setup mask (FF000000)*/
152         extru,<>        save,23,8,r0
153         b               found_null5
154         ldil            0x1FFFE0,tmp5           /* setup mask (FFFF0000)*/
155         ldo             -1(r0),tmp5             /* setup mask (FFFFFFFF)*/
156 found_null5:
157         and             tmp3,tmp5,tmp3  /* zero out tmp5 based on mask in tmp5*/
158 no_null:
159         bv              0(r2)           /* were done*/
160         stbys,e     tmp3,0(0,d_addr)    /* store the data !*/
162 /* here we do ye old byte-at-a-time moves.*/
163 byteloop: 
164         addibt,=,n     4,count,done
165         comb,=    0,s_addr,done
166         stbs      r0,0(d_addr)          /* store null in case s_addr == NULL */
167         ldbs,ma     1(s_addr),tmp1
168 encore:
169         combt,=,n       tmp1,r0, pad_null_bytes1
170         stbs,ma     tmp1,1(d_addr) 
171         addibf,=,n  -1,count,encore
172         ldbs,ma     1(s_addr),tmp1
173         b,n             done
175 pnb_1:
176         addibt,=,n      4,count,done /* if count was already 0 then we're done*/
178 pad_null_bytes1:
179         combt,=,n       count,r0,done   /* if count==0 then exit */
180 pad_null_bytes2:
181         addibf,=        -1,count,pad_null_bytes2
182         stbs,ma         r0,1(d_addr)
183         b,n             done
185 pad_nulls:
186         addibf,<=,n     -4,count,pad_nulls
187         stwm            r0,4(d_addr)
188         b,n             pnb_1
191 null1:
192         extru,<>        save,7,8,r0
193         b               found_null1
194         copy            r0, tmp5
195         extru,<>        save,15,8,r0
196         b               found_null1
197         ldil            0x1FE000,tmp5           /* setup mask (FF000000)*/
198         extru,<>        save,23,8,r0
199         b               found_null1
200         ldil            0x1FFFE0,tmp5           /* setup mask (FFFF0000)*/
201         ldo             -1(r0),tmp5             /* setup mask (FFFFFFFF)*/
202 found_null1:
203         and             tmp1,tmp5,tmp1          /*zero out tmp1 according to mask*/
204         b               pad_nulls               /* nullify remaining count bytes*/
205         stbys,b,m       tmp1,4(0,d_addr)        /* first word (account for alignment)*/
208 null2:  /* back porch case. We have less than 4 bytes to go.*/
209         extru,<>        save,7,8,r0     /* is null in 1st byte? */
210         b               found_null2
211         copy            r0, tmp5
212         extru,<>        save,15,8,r0    /* is null in 2nd byte? */
213         b               found_null2
214         ldil            0x1FE000,tmp5           /* setup mask (FF000000)*/
215         b               found_null2     /* null must be in 3rd byte */
216         ldil            0x1FFFE0,tmp5           /* setup mask (FFFF0000)*/
217 found_null2:    
218         and             tmp1,tmp5,tmp1          /*zero out tmp1 according to mask*/
219         bv              0(r2)                   /* we're done*/
220         stbys,e         tmp1,0(0,d_addr)        /* last word (back porch)*/
222 null3:  /* not_aligned case where null is found in first of two words--adjust count*/
223         extru,<>        save,7,8,r0
224         b               found_null3
225         copy            r0, tmp5
226         extru,<>        save,15,8,r0
227         b               found_null3
228         ldil            0x1FE000,tmp5           /* setup mask (FF000000)*/
229         extru,<>        save,23,8,r0
230         b               found_null3
231         ldil            0x1FFFE0,tmp5           /* setup mask (FFFF0000)*/
232         ldo             -1(r0),tmp5             /* setup mask (FFFFFFFF)*/
233 found_null3:
234         addi            4,count,count           /* fix count since null is in first of two words*/
235         and             tmp3,tmp5,tmp3          /*zero out tmp3 according to mask*/
236         b               pad_nulls               /* nullify remaining count bytes*/
237         stbys,b,m       tmp3,4(d_addr)
239 null4:  /* not_aligned case where null is found in second of two words*/
240         extru,<>        save,7,8,r0
241         b               found_null4
242         copy            r0, tmp5
243         extru,<>        save,15,8,r0
244         b               found_null4
245         ldil            0x1FE000,tmp5           /* setup mask (FF000000)*/
246         extru,<>        save,23,8,r0
247         b               found_null4
248         ldil            0x1FFFE0,tmp5           /* setup mask (FFFF0000)*/
249         ldo             -1(r0),tmp5             /* setup mask (FFFFFFFF)*/
250 found_null4:
251         and             tmp3,tmp5,tmp3          /*zero out tmp4 according to mask*/
252         b               pad_nulls               /* nullify remaining count bytes*/
253         stbys,b,m       tmp3,4(d_addr)
255 done:    
256 EXIT(strncpy)