1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
/*
* (c) Copyright 1986 HEWLETT-PACKARD COMPANY
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of Hewlett-Packard Company not be
* used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission.
* Hewlett-Packard Company makes no representations about the
* suitability of this software for any purpose.
*/
/* HPUX_ID: @(#) $Revision$ */
/*
* strcat(s1, s2)
*
* Concatenate s2 on the end of s1. S1's space must be large enough.
* Return s1.
*/
#include "DEFS.h"
#define d_addr r26
#define s_addr r25
#define tmp6 r24
#define tmp1 r19
#define tmp2 r20
#define tmp3 r21
#define tmp4 r22
#define tmp5 arg3
#define save r1
ENTRY(strcat)
comb,= r0,s_addr,done /* quit if s2=NULL */
copy d_addr,ret0 /* The return value is the value of d_addr. DELAY SLOT*/
/* First look for end of s1 (d_addr) */
extru d_addr,31,2,tmp1 /* Extract the low two bits of the dest address. */
combt,= tmp1,r0,dont_mask
dep 0,31,2,d_addr /*set word alignment */
ldwm 4(d_addr),tmp2
sh3add tmp1,r0,save /* build mask based on tmp1 */
mtctl save,11
zvdepi -2,32,save
or save,tmp2,tmp2
uxor,nbz tmp2,r0,save
search:
b,n found_end /* nullified under uxor conditions above and below */
dont_mask:
ldwm 4(d_addr),tmp2
comib,tr r0,r0,search
uxor,nbz tmp2,r0,save
found_end: /* at this point d_addr points to word */
extru,<> save,7,8,r0 /* following word with null */
addib,tr,n -4,d_addr,begin_copy /*set d_addr to end of s1 */
extru,<> save,15,8,r0
addib,tr,n -3,d_addr,begin_copy
extru,<> save,23,8,r0
addi -1,d_addr,d_addr
addi -1,d_addr,d_addr
begin_copy:
extru s_addr,31,2,tmp1 /* Extract the low two bits of the source address. */
extru d_addr,31,2,tmp6 /* Extract the low two bits of the destination address. */
sub,= tmp6,tmp1,tmp3 /* Compute the shift quantity and don't branch if tmp6=tmp1. */
b not_aligned /* Not_aligned says that shifts Will be needed. */
dep 0,31,2,s_addr /* Compute the word address of the source. DELAY SLOT. */
/* aligned */
combt,= tmp6,r0,skip_mask
ldwm 4(0,s_addr),tmp1 /* tmp1 = *s_addr s_addr += 4 (DELAY SLOT) */
sh3add tmp6,r0,save
mtctl save,r11
zvdepi -2,32,save
or save,tmp1,tmp1
uxor,nbz tmp1,r0,save
b,n first_null /* special case: null in first word */
b,n skip_mask2
chunks:
b,n null_found /* delay slot for uxor below */
skip_mask2:
stbys,b,m tmp1,4(d_addr)
ldwm 4(s_addr),tmp1
skip_mask:
comib,tr 0,0,chunks
uxor,nbz tmp1,r0,save
/* Begin non_aligned code. */
not_aligned:
sh3add,>= tmp3,r0,tmp4 /* compute the shift amt.and skip load if tmp6 > tmp1. */
ldwm 4(0,s_addr),tmp1 /* load up the first word from the source. tmp1 = *s_addr++ */
ldwm 4(0,s_addr),tmp2 /* get either first or second word from source. */
combt,= tmp6,r0,chunk2 /* don't mask if whole word is valid */
mtctl tmp4,11 /* load the shift count into cr11 = shift count register. */
vshd tmp1,tmp2,tmp3 /* position data ! (delay slot) */
sh3add tmp6,r0,save /* setup r1 */
mtctl save,r11 /* set-up cr11 for mask */
zvdepi -2,32,save
or save, tmp3, tmp3
uxor,nbz tmp3,r0,save
b,n first_null2
b did_mask
mtctl tmp4,11 /* re-load the shift count into cr11 */
chunk2:
vshd tmp1,tmp2,tmp3
uxor,nbz tmp3, r0, save
b,n null_found
did_mask:
stbys,b,m tmp3,4(0,d_addr) /* store ! */
ldwm 4(0,s_addr),tmp1 /* get next word ! */
vshd tmp2,tmp1,tmp3 /* position data ! */
uxor,nbz tmp3, r0, save
b,n null_found
stwm tmp3,4(d_addr)
comib,tr 0,0,chunk2
ldwm 4(s_addr),tmp2
null_found: /* adjust d_addr and store final word */
extru,<> save,7,8,r0
addib,tr,n 1,d_addr,store_final
extru,<> save,15,8,r0
addib,tr,n 2,d_addr,store_final
extru,<> save,23,8,r0
addib,tr 3,d_addr,store_final2
bv 0(r2)
stw save,0(d_addr)
store_final:
bv 0(r2)
store_final2:
stbys,e save,0(d_addr) /* delay slot */
first_null: /* null found in first word of aligned (wrt d_addr) */
addi -4,s_addr,s_addr
ldbx tmp6(s_addr),tmp4
add tmp6,s_addr,s_addr
comib,= 0,tmp4,done
stbs,ma tmp4,1(d_addr)
ldbs 1(s_addr),tmp4
comib,= 0,tmp4,done
stbs,ma tmp4,1(d_addr)
bv 0(r2) /* done */
stbs 0,0(d_addr)
first_null2: /* null found in first word of non-aligned (wrt d_addr) */
addibt,= -1,tmp6,check3 /* check last 3 bytes of word */
extru save,15,8,tmp4
addibt,=,n -1,tmp6,check2 /* check last 2 bytes */
bv 0(r2)
stbys,b save, 0(d_addr)
check3:
combt,= tmp4,r0,done
stbs,ma tmp4,1(d_addr)
check2:
extru,<> save,23,8,tmp4
bv 0(r2)
stbs,ma tmp4,1(d_addr)
bv 0(r2)
stbs r0,0(d_addr)
done:
EXIT(strcat)
|