Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!brl-adm!seismo!mimsy!chris From: chris@mimsy.UUCP Newsgroups: comp.arch,comp.lang.c,comp.unix.wizards Subject: Re: String Handling and run-time libraries Message-ID: <6042@mimsy.UUCP> Date: Tue, 31-Mar-87 04:36:46 EST Article-I.D.: mimsy.6042 Posted: Tue Mar 31 04:36:46 1987 Date-Received: Thu, 2-Apr-87 01:16:36 EST References: <15292@amdcad.UUCP> <978@ames.UUCP> <15694@sun.uucp> <5@wb1.cs.cmu.edu> Followup-To: comp.unix.wizards Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 78 Xref: utgpu comp.arch:724 comp.lang.c:1398 comp.unix.wizards:1608 >In article <1531@husc6.UUCP> reiter@harvard.UUCP (Ehud Reiter) writes: >[strcpy is inordinately slow on a uVax II running 4.3BSD] In article <5@wb1.cs.cmu.edu> avie@wb1.cs.cmu.edu (Avadis Tevanian) writes: >... the 4.3 libc ... has been carefully optimized to use the fancy >VAX instructions for the string routines. Unfortunately, some of >these instructions are not implemented by the MicroVAX-II hardware. >As it turns out, what is happening is that your tests (including >Dhrystone) are causing kernel traps to emulate those instructions! Exactly. Strcpy, strcat, and strlen were all modified to use the Vax `locc' instruction to find the ends of strings. This instruction is not implemented in hardware in the uVax II. The obvious solution is to arrange the libraries so that on a uVax, programs use a straightforward test-byte-and-branch loop (see sample code below). There are two ways to do this. One could attempt to determine at run-time whether `locc' is available; or one can simply assume that anything compiled on a uVax will run on a uVax, and anything compiled on a `big Vax' will run on a big Vax. The former would be hard, requring a system call, but would likely be worthwhile if this could be done at most once per program run. The latter is easy: just build libc.a differently on a uVax (and then watch rdist run, and weep). Both tricks, however, require some way for user programs to discover which CPU is executing them. A `getcputype' call, anyone? (But what about dynamic process relocation, where a program might move from one CPU type to another? [ECAPISTRANO, process migrated]) Here is a sample replacement for strlen (untested!), assuming there were a getcputype system call. /* get CPU type numbers */ #include /* lenroutine is the address of the proper routine, once known */ .lcomm lenroutine,4 ENTRY(strlen) .word 0 # save no registers movl lenroutine,r0 # know which routine to use? beql 1f # no, go figure (and pipeline flush) jmp (r0) # go do it /* * Someone should find out whether a branch to the jmp (r0) below * would be slower (two pipeline flushes vs. one?). Need to test * all architectures! */ /* figure out which routine to use */ 1: calls $0,_getcputype cmpl $UVAX2,r0 # is it a MicroVAX-II? beql 2f movl bigvax,r0 # use big vax code brb 3f 2: movl chipvax,r0 # use chip vax code 3: movl r0,lenroutine # remember which to use jmp (r0) # and go do it /* locc version */ bigvax: ... # insert 4.3BSD code here ret /* byte-at-a-time version */ chipvax: movl 4(ap),r0 # get string movl r0,r1 # and avoid two mem refs 1: tstb (r0)+ # find the \0 bneq 1b # loop until just past the \0 decl r0 # point back at \0 subl2 r1,r0 # return r0 - r1 ret -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: seismo!mimsy!chris ARPA/CSNet: chris@mimsy.umd.edu