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