1#!/bin/sh 2# 3# If your shell doesn't support functions (true for some BSD users), 4# you might try using GNU's bash. 5# 6#ident "@(#) m88k-move.sh 1-Sep-92" 7# 8# This file provided by Data General, February 1990. 9# 10# This script generates the necessary movstr library functions 11# for the m88100. These functions are called from the expansion 12# of movstrsi. There are eight modules created by this script, 13# each with multiple entry points. One module, moveSI64n 14# implements a word aligned loop; the other modules, moveXINx 15# implement a straight line copy of N bytes in mode XI. 16# 17# By analysis of the best memcpy function, it can be determined 18# what appear to be certain magic numbers. For example, a 19# memcpy of 13 bytes, where the pointers are determined at run 20# time to be word aligned takes 28 cycles. A call to 21# __movstrQI13x13 also takes 28 cycles. The break even point 22# for a HImode copy is 38 bytes. Just to be on the safe side, 23# these are bumped to 16 and 48 respectively. 24# 25# The smaller, odd-remainder modules are provided to help 26# mitigate the overhead of copying the last bytes. 27# 28# Changes to these functions should not be taken lightly if you 29# want to be able to link programs built with older movstr 30# parameters. 31# 32#.Revision History 33# 34# 1-Sep-92 Stan Cox Added moveDI96x, moveDI41x through moveDI47x. 35# 2-Jan-92 Tom Wood Renamed files to comply with SVR3 14 char limit. 36# 26-Oct-90 Tom Wood Delete movstr.h; moved to out-m88k.c. 37# 17-Oct-90 Tom Wood Files are named *.asm rather than *.s. 38# 11-Sep-90 Jeffrey Friedl 39# On my BSD 4.3 awk and my GNU-awk, only the 40# first character of an argument to -F is passed 41# through, so I can't get this to work. 42# 5-Sep-90 Ray Essick/Tom Wood 43# Added a -no-tdesc option. 44# 27-Aug-90 Vince Guarna/Tom Wood 45# Version 3 assembler syntax (-abi). 46# 16-Aug-90 Ron Guilmette 47# Avoid problems on a Sparc. The common 48# denominator among shells seems to be '...\' 49# rather than '...\\'. 50# 15-Aug-90 Ron Guilmette 51# Avoid awk syntax errors on a Sun by not using 52# the `!' operator. 53# 22-Feb-90 Tom Wood Created. 54# 20-Jun-90 Tom Wood Emit file directives. 55# 56#.End]=--------------------------------------------------------------*/ 57 58usage() { 59 echo "usage: $0 [ -abi ] [ -no-tdesc ]" 1>&2 60 exit 1 61} 62 63awk_flag="-F:"; 64awk_begin="BEGIN { " 65ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt=""; 66do_file() { 67 echo " file $1"; 68} 69 70while [ $# -gt 0 ] ; do 71 case $1 in 72 -no-tdesc) awk_begin="$awk_begin no_tdesc=1;" 73 nt=";";; 74 -abi) awk_begin="$awk_begin abi=1;" 75 ps="#"; us=""; tf="a"; la=".L"; fb="16"; 76 do_file() { 77 echo ' version "03.00"'; 78 echo " file $1"; 79 };; 80 *) usage;; 81 esac 82 shift 83done 84 85rm -f move?I*[xn].s move?I*[xn].asm 86 87#.Implementation_continued[=----------------------------------------------- 88# 89# This generates the word aligned loop. The loop is entered 90# from the callable entry points ___movstrSI64nN, where at 91# least N bytes will be copied. r2 is the destination pointer 92# offset by 4, r3 is the source pointer offset by 4, r6 is the 93# loop count. Thus, the total bytes moved is 64 * r6 + N. The 94# first value is preloaded into r4 or r5 (r4 if N/4 is odd; 95# r5 if N/4 is even). Upon returning, r2 and r3 have been 96# updated and may be used for the remainder bytes to move. 97# 98# The code for this loop is generated by the awk program 99# following. Edit *it*, not what it generates! 100# 101#.End]=------------------------------------------------------------------*/ 102 103gen_movstrN() { 104 awk $awk_flag "$awk_begin"' 105 if (abi) { 106 ps="#"; us=""; tf="a"; la=".L"; fb=16; 107 } else { 108 ps=""; us="_"; tf="x"; la="@L"; fb=8; 109 } 110 } 111 NR == 1 && NF == 4 { 112 mode = $1; suffix = $2; align = $3; count = $4; 113 ld = align; st = 0; 114 115 printf "; The following was calculated using awk.\n"; 116 printf "\ttext\n"; 117 printf "\talign\t%d\n", fb; 118 printf "%sloop%s%d:\n", la, mode, count * align; 119 printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; 120 printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; 121 printf "\tsubu\t%sr6,%sr6,1\n", ps, ps; 122 for (r = count + 1; r >= 1; r--) { 123 evenp = r % 2; 124 name = sprintf("__%smovstr%s%dn%d", us, mode, count * align, r * align); 125 if (r > 1) { 126 printf "\tglobal\t%s\n", name; 127 printf "%s:\n", name; 128 } 129 if (r > 2) { 130 printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; 131 printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; 132 } else if (r == 2) { 133 printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; 134 printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align; 135 printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; 136 printf "\tjmp.n\t%sr1\n", ps; 137 } else { 138 printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; 139 } 140 ld += align; st += align; 141 } 142 if (!no_tdesc) { 143 printf "%send%s%d:\n", la, mode, count * align; 144 printf "\tsection\t.tdesc,\"%s\"\n", tf; 145 printf "\tword\t0x42,1,%sloop%s%d", la, mode, count * align; 146 printf ",%send%s%d\n", la, mode, count * align; 147 printf "\tword\t0x0100001f,0,1,0\n"; 148 printf "\ttext\n"; 149 } 150 printf "; End of awk generated code.\n"; 151 exit; 152 }' 153} 154 155(do_file '"movstrSI64n.s"'; 156 echo 'SI::4:16' | gen_movstrN) > moveSI64n.asm 157 158#.Implementation_continued[=----------------------------------------------- 159# 160# This generates the even-remainder, straight-line modules. 161# The code is entered from the callable entry points 162# ___movstrXINxM, where exactly M bytes will be copied in XI 163# mode. r2 is the destination pointer, r3 is the source 164# pointer, neither being offset. The first value is preloaded 165# into r4 or r5 (r4 if M-N/B is even; r5 if M-N/B is odd, where 166# B is the mode size of XI). Upon returning, r2 and r3 have not 167# been changed. 168# 169# The code for these cases is generated by the awk program 170# following. Edit *it*, not what it generates! 171# 172#.End]=------------------------------------------------------------------*/ 173 174gen_movstrX0() { 175 awk $awk_flag "$awk_begin"' 176 if (abi) { 177 ps="#"; us=""; tf="a"; la=".L"; fb=16; 178 } else { 179 ps=""; us="_"; tf="x"; la="@L"; fb=8; 180 } 181 } 182 NR == 1 && NF == 4 { 183 mode = $1; suffix = $2; align = $3; bytes = $4; 184 ld = align; st = 0; count = bytes / align; 185 reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; 186 printf "; The following was calculated using awk.\n"; 187 printf "\ttext\n"; 188 printf "\talign\t%d\n", fb; 189 for (r = count; r >= 1; r--) { 190 evenp = r % 2; 191 name = sprintf("__%smovstr%s%dx%d", us, mode, count * align, r * align); 192 if (r > 1) { 193 printf "\tglobal\t%s\n", name; 194 printf "%s:\n", name; 195 } 196 if (r == 1) 197 printf "\tjmp.n\t%sr1\n", ps; 198 else 199 printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, reg[evenp], ps, ld; 200 printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, reg[1-evenp], ps, st; 201 ld += align; st += align; 202 } 203 if (!no_tdesc) { 204 printf "%send%s%dx:\n", la, mode, count * align; 205 printf "\tsection\t.tdesc,\"%s\"\n", tf; 206 printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, count * align, count * align; 207 printf ",%send%s%dx\n", la, mode, count * align; 208 printf "\tword\t0x0100001f,0,1,0\n"; 209 printf "\ttext\n"; 210 } 211 printf "; End of awk generated code.\n" 212 exit; 213 }' 214} 215 216(do_file '"movstrQI16x.s"'; 217 echo 'QI:.b:1:16' | gen_movstrX0) > moveQI16x.asm 218(do_file '"movstrHI48x.s"'; 219 echo 'HI:.h:2:48' | gen_movstrX0) > moveHI48x.asm 220(do_file '"movstrSI96x.s"'; 221 echo 'SI::4:96' | gen_movstrX0) > moveSI96x.asm 222(do_file '"movstrDI96x.s"'; 223 echo 'DI:.d:8:96' | gen_movstrX0) > moveDI96x.asm 224 225#.Implementation_continued[=----------------------------------------------- 226# 227# This generates the odd-remainder, straight-line modules. The 228# interface is the same as that for the even-remainder modules. 229# 230#.End]=------------------------------------------------------------------*/ 231 232gen_movstrXr() { 233 awk $awk_flag "$awk_begin"' 234 if (abi) { 235 ps="#"; us=""; tf="a"; la=".L"; fb=16; 236 } else { 237 ps=""; us="_"; tf="x"; la="@L"; fb=8; 238 } 239 } 240 NR == 1 && NF == 4 { 241 mode = $1; rem = $2; most = $3; count = $4; 242 suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d"; 243 244 prev = align = most; 245 ld = align; st = 0; total = count - rem - most; 246 evenp = int(total/align) % 2; 247 reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; 248 printf "; The following was calculated using awk.\n"; 249 printf "\ttext\n"; 250 printf "\talign\t%d\n", fb; 251 for (bytes = total; bytes >= 0; bytes -= align) { 252 if (bytes < align) { 253 if (bytes >= 4) align = 4; 254 else if (bytes >= 2) align = 2; 255 else align = 1; 256 } 257 name = sprintf("__%smovstr%s%dx%d", us, mode, total + most, bytes + most); 258 if (bytes > most) { 259 printf "\tglobal\t%s\n", name; 260 printf "%s:\n", name; 261 } 262 if (bytes == 0) 263 printf "\tjmp.n\t%sr1\n", ps; 264 else 265 printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, reg[evenp], ps, ld; 266 printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, reg[1-evenp], ps, st; 267 ld += align; st += prev; prev = align; 268 evenp = 1 - evenp; 269 } 270 if (!no_tdesc) { 271 printf "%send%s%dx:\n", la, mode, total + most; 272 printf "\tsection\t.tdesc,\"%s\"\n", tf; 273 printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, total + most, total + most; 274 printf ",%send%s%dx\n", la, mode, total + most; 275 printf "\tword\t0x0100001f,0,1,0\n"; 276 printf "\ttext\n"; 277 } 278 printf "; End of awk generated code.\n" 279 exit; 280 }' 281} 282 283(do_file '"movstrDI47x.s"'; 284 echo 'DI:1:8:48' | gen_movstrXr) > moveDI47x.asm 285(do_file '"movstrDI46x.s"'; 286 echo 'DI:2:8:48' | gen_movstrXr) > moveDI46x.asm 287(do_file '"movstrDI45x.s"'; 288 echo 'DI:3:8:48' | gen_movstrXr) > moveDI45x.asm 289(do_file '"movstrDI44x.s"'; 290 echo 'DI:4:8:48' | gen_movstrXr) > moveDI44x.asm 291(do_file '"movstrDI43x.s"'; 292 echo 'DI:5:8:48' | gen_movstrXr) > moveDI43x.asm 293(do_file '"movstrDI42x.s"'; 294 echo 'DI:6:8:48' | gen_movstrXr) > moveDI42x.asm 295(do_file '"movstrDI41x.s"'; 296 echo 'DI:7:8:48' | gen_movstrXr) > moveDI41x.asm 297 298(do_file '"movstrSI47x.s"'; 299 echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm 300(do_file '"movstrSI46x.s"'; 301 echo 'SI:2:4:48' | gen_movstrXr) > moveSI46x.asm 302(do_file '"movstrSI45x.s"'; 303 echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm 304 305(do_file '"movstrHI15x.s"'; 306 echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm 307