| #!/bin/sh |
| # |
| # If your shell doesn't support functions (true for some BSD users), |
| # you might try using GNU's bash. |
| # |
| #ident "@(#) m88k-move.sh 1-Sep-92" |
| # |
| # This file provided by Data General, February 1990. |
| # |
| # This script generates the necessary movstr library functions |
| # for the m88100. These functions are called from the expansion |
| # of movstrsi. There are eight modules created by this script, |
| # each with multiple entry points. One module, moveSI64n |
| # implements a word aligned loop; the other modules, moveXINx |
| # implement a straight line copy of N bytes in mode XI. |
| # |
| # By analysis of the best memcpy function, it can be determined |
| # what appear to be certain magic numbers. For example, a |
| # memcpy of 13 bytes, where the pointers are determined at run |
| # time to be word aligned takes 28 cycles. A call to |
| # __movstrQI13x13 also takes 28 cycles. The break even point |
| # for a HImode copy is 38 bytes. Just to be on the safe side, |
| # these are bumped to 16 and 48 respectively. |
| # |
| # The smaller, odd-remainder modules are provided to help |
| # mitigate the overhead of copying the last bytes. |
| # |
| # Changes to these functions should not be taken lightly if you |
| # want to be able to link programs built with older movstr |
| # parameters. |
| # |
| #.Revision History |
| # |
| # 1-Sep-92 Stan Cox Added moveDI96x, moveDI41x through moveDI47x. |
| # 2-Jan-92 Tom Wood Renamed files to comply with SVR3 14 char limit. |
| # 26-Oct-90 Tom Wood Delete movstr.h; moved to out-m88k.c. |
| # 17-Oct-90 Tom Wood Files are named *.asm rather than *.s. |
| # 11-Sep-90 Jeffrey Friedl |
| # On my BSD 4.3 awk and my GNU-awk, only the |
| # first character of an argument to -F is passed |
| # through, so I can't get this to work. |
| # 5-Sep-90 Ray Essick/Tom Wood |
| # Added a -no-tdesc option. |
| # 27-Aug-90 Vince Guarna/Tom Wood |
| # Version 3 assembler syntax (-abi). |
| # 16-Aug-90 Ron Guilmette |
| # Avoid problems on a Sparc. The common |
| # denominator among shells seems to be '...\' |
| # rather than '...\\'. |
| # 15-Aug-90 Ron Guilmette |
| # Avoid awk syntax errors on a Sun by not using |
| # the `!' operator. |
| # 22-Feb-90 Tom Wood Created. |
| # 20-Jun-90 Tom Wood Emit file directives. |
| # |
| #.End]=--------------------------------------------------------------*/ |
| |
| usage() { |
| echo "usage: $0 [ -abi ] [ -no-tdesc ]" 1>&2 |
| exit 1 |
| } |
| |
| awk_flag="-F:"; |
| awk_begin="BEGIN { " |
| ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt=""; |
| do_file() { |
| echo " file $1"; |
| } |
| |
| while [ $# -gt 0 ] ; do |
| case $1 in |
| -no-tdesc) awk_begin="$awk_begin no_tdesc=1;" |
| nt=";";; |
| -abi) awk_begin="$awk_begin abi=1;" |
| ps="#"; us=""; tf="a"; la=".L"; fb="16"; |
| do_file() { |
| echo ' version "03.00"'; |
| echo " file $1"; |
| };; |
| *) usage;; |
| esac |
| shift |
| done |
| |
| rm -f move?I*[xn].s move?I*[xn].asm |
| |
| #.Implementation_continued[=----------------------------------------------- |
| # |
| # This generates the word aligned loop. The loop is entered |
| # from the callable entry points ___movstrSI64nN, where at |
| # least N bytes will be copied. r2 is the destination pointer |
| # offset by 4, r3 is the source pointer offset by 4, r6 is the |
| # loop count. Thus, the total bytes moved is 64 * r6 + N. The |
| # first value is is preloaded into r4 or r5 (r4 if N/4 is odd; |
| # r5 if N/4 is even). Upon returning, r2 and r3 have been |
| # updated and may be used for the remainder bytes to move. |
| # |
| # The code for this loop is generated by the awk program |
| # following. Edit *it*, not what it generates! |
| # |
| #.End]=------------------------------------------------------------------*/ |
| |
| gen_movstrN() { |
| awk $awk_flag "$awk_begin"' |
| if (abi) { |
| ps="#"; us=""; tf="a"; la=".L"; fb=16; |
| } else { |
| ps=""; us="_"; tf="x"; la="@L"; fb=8; |
| } |
| } |
| NR == 1 && NF == 4 { |
| mode = $1; suffix = $2; align = $3; count = $4; |
| ld = align; st = 0; |
| |
| printf "; The following was calculated using awk.\n"; |
| printf "\ttext\n"; |
| printf "\talign\t%d\n", fb; |
| printf "%sloop%s%d:\n", la, mode, count * align; |
| printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; |
| printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; |
| printf "\tsubu\t%sr6,%sr6,1\n", ps, ps; |
| for (r = count + 1; r >= 1; r--) { |
| evenp = r % 2; |
| name = sprintf("__%smovstr%s%dn%d", us, mode, count * align, r * align); |
| if (r > 1) { |
| printf "\tglobal\t%s\n", name; |
| printf "%s:\n", name; |
| } |
| if (r > 2) { |
| printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; |
| printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; |
| } else if (r == 2) { |
| printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; |
| printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align; |
| printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; |
| printf "\tjmp.n\t%sr1\n", ps; |
| } else { |
| printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; |
| } |
| ld += align; st += align; |
| } |
| if (!no_tdesc) { |
| printf "%send%s%d:\n", la, mode, count * align; |
| printf "\tsection\t.tdesc,\"%s\"\n", tf; |
| printf "\tword\t0x42,1,%sloop%s%d", la, mode, count * align; |
| printf ",%send%s%d\n", la, mode, count * align; |
| printf "\tword\t0x0100001f,0,1,0\n"; |
| printf "\ttext\n"; |
| } |
| printf "; End of awk generated code.\n"; |
| exit; |
| }' |
| } |
| |
| (do_file '"movstrSI64n.s"'; |
| echo 'SI::4:16' | gen_movstrN) > moveSI64n.asm |
| |
| #.Implementation_continued[=----------------------------------------------- |
| # |
| # This generates the even-remainder, straight-line modules. |
| # The code is entered from the callable entry points |
| # ___movstrXINxM, where exactly M bytes will be copied in XI |
| # mode. r2 is the destination pointer, r3 is the source |
| # pointer, neither being offset. The first value is preloaded |
| # into r4 or r5 (r4 if M-N/B is even; r5 if M-N/B is odd, where |
| # B is the mode size of XI). Upon returning, r2 and r3 have not |
| # been changed. |
| # |
| # The code for these cases is generated by the awk program |
| # following. Edit *it*, not what it generates! |
| # |
| #.End]=------------------------------------------------------------------*/ |
| |
| gen_movstrX0() { |
| awk $awk_flag "$awk_begin"' |
| if (abi) { |
| ps="#"; us=""; tf="a"; la=".L"; fb=16; |
| } else { |
| ps=""; us="_"; tf="x"; la="@L"; fb=8; |
| } |
| } |
| NR == 1 && NF == 4 { |
| mode = $1; suffix = $2; align = $3; bytes = $4; |
| ld = align; st = 0; count = bytes / align; |
| reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; |
| printf "; The following was calculated using awk.\n"; |
| printf "\ttext\n"; |
| printf "\talign\t%d\n", fb; |
| for (r = count; r >= 1; r--) { |
| evenp = r % 2; |
| name = sprintf("__%smovstr%s%dx%d", us, mode, count * align, r * align); |
| if (r > 1) { |
| printf "\tglobal\t%s\n", name; |
| printf "%s:\n", name; |
| } |
| if (r == 1) |
| printf "\tjmp.n\t%sr1\n", ps; |
| else |
| printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, reg[evenp], ps, ld; |
| printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, reg[1-evenp], ps, st; |
| ld += align; st += align; |
| } |
| if (!no_tdesc) { |
| printf "%send%s%dx:\n", la, mode, count * align; |
| printf "\tsection\t.tdesc,\"%s\"\n", tf; |
| printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, count * align, count * align; |
| printf ",%send%s%dx\n", la, mode, count * align; |
| printf "\tword\t0x0100001f,0,1,0\n"; |
| printf "\ttext\n"; |
| } |
| printf "; End of awk generated code.\n" |
| exit; |
| }' |
| } |
| |
| (do_file '"movstrQI16x.s"'; |
| echo 'QI:.b:1:16' | gen_movstrX0) > moveQI16x.asm |
| (do_file '"movstrHI48x.s"'; |
| echo 'HI:.h:2:48' | gen_movstrX0) > moveHI48x.asm |
| (do_file '"movstrSI96x.s"'; |
| echo 'SI::4:96' | gen_movstrX0) > moveSI96x.asm |
| (do_file '"movstrDI96x.s"'; |
| echo 'DI:.d:8:96' | gen_movstrX0) > moveDI96x.asm |
| |
| #.Implementation_continued[=----------------------------------------------- |
| # |
| # This generates the odd-remainder, straight-line modules. The |
| # interface is the same as that for the even-remainder modules. |
| # |
| #.End]=------------------------------------------------------------------*/ |
| |
| gen_movstrXr() { |
| awk $awk_flag "$awk_begin"' |
| if (abi) { |
| ps="#"; us=""; tf="a"; la=".L"; fb=16; |
| } else { |
| ps=""; us="_"; tf="x"; la="@L"; fb=8; |
| } |
| } |
| NR == 1 && NF == 4 { |
| mode = $1; rem = $2; most = $3; count = $4; |
| suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d"; |
| |
| prev = align = most; |
| ld = align; st = 0; total = count - rem - most; |
| evenp = int(total/align) % 2; |
| reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; |
| printf "; The following was calculated using awk.\n"; |
| printf "\ttext\n"; |
| printf "\talign\t%d\n", fb; |
| for (bytes = total; bytes >= 0; bytes -= align) { |
| if (bytes < align) { |
| if (bytes >= 4) align = 4; |
| else if (bytes >= 2) align = 2; |
| else align = 1; |
| } |
| name = sprintf("__%smovstr%s%dx%d", us, mode, total + most, bytes + most); |
| if (bytes > most) { |
| printf "\tglobal\t%s\n", name; |
| printf "%s:\n", name; |
| } |
| if (bytes == 0) |
| printf "\tjmp.n\t%sr1\n", ps; |
| else |
| printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, reg[evenp], ps, ld; |
| printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, reg[1-evenp], ps, st; |
| ld += align; st += prev; prev = align; |
| evenp = 1 - evenp; |
| } |
| if (!no_tdesc) { |
| printf "%send%s%dx:\n", la, mode, total + most; |
| printf "\tsection\t.tdesc,\"%s\"\n", tf; |
| printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, total + most, total + most; |
| printf ",%send%s%dx\n", la, mode, total + most; |
| printf "\tword\t0x0100001f,0,1,0\n"; |
| printf "\ttext\n"; |
| } |
| printf "; End of awk generated code.\n" |
| exit; |
| }' |
| } |
| |
| (do_file '"movstrDI47x.s"'; |
| echo 'DI:1:8:48' | gen_movstrXr) > moveDI47x.asm |
| (do_file '"movstrDI46x.s"'; |
| echo 'DI:2:8:48' | gen_movstrXr) > moveDI46x.asm |
| (do_file '"movstrDI45x.s"'; |
| echo 'DI:3:8:48' | gen_movstrXr) > moveDI45x.asm |
| (do_file '"movstrDI44x.s"'; |
| echo 'DI:4:8:48' | gen_movstrXr) > moveDI44x.asm |
| (do_file '"movstrDI43x.s"'; |
| echo 'DI:5:8:48' | gen_movstrXr) > moveDI43x.asm |
| (do_file '"movstrDI42x.s"'; |
| echo 'DI:6:8:48' | gen_movstrXr) > moveDI42x.asm |
| (do_file '"movstrDI41x.s"'; |
| echo 'DI:7:8:48' | gen_movstrXr) > moveDI41x.asm |
| |
| (do_file '"movstrSI47x.s"'; |
| echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm |
| (do_file '"movstrSI46x.s"'; |
| echo 'SI:2:4:48' | gen_movstrXr) > moveSI46x.asm |
| (do_file '"movstrSI45x.s"'; |
| echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm |
| |
| (do_file '"movstrHI15x.s"'; |
| echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm |