home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1863 < prev    next >
Internet Message Format  |  1990-12-28  |  36KB

  1. From: pcg@cs.aber.ac.uk (Piercarlo Grandi)
  2. Newsgroups: comp.arch,alt.sources
  3. Subject: Alignment IS important
  4.     copying between [un]aligned source and/or destination addresses
  5. Message-ID: <PCG.90Sep25171913@odin.cs.aber.ac.uk>
  6. Date: 25 Sep 90 16:19:13 GMT
  7. Sender: pcg@aber-cs.UUCP
  8. Organization: Coleg Prifysgol Cymru
  9. Lines: 1135
  10. Nntp-Posting-Host: odin
  11.  
  12.  
  13. There has been some debate in this newsgroup about the importance of
  14. aligned memory access. I have finally neatly packaged my own technology
  15. for doing core-to-core memory copies, aligned and unaligned, and here I
  16. am posting the technology and some discussion of the results.
  17.  
  18. This article is posted to comp.arch because it discusses architecture,
  19. and to alt.sources because it contains generally useful source code.
  20.  
  21.     Usual disclaimer: this work has no relationship whatever to that
  22.     of the University College of Wales; it was performed exclusively
  23.     by me, with the use of my own time, funds, machines, know-how,
  24.     and has not been aided abetted or supported in any way by the
  25.     Unviersity College of Wales. I thank them for providing the
  26.     opportunity to access News and therefore to post this article,
  27.     about which they do not actually know anything.
  28.  
  29. This article is about a library function essentially equivalent to
  30. memcpy(3), that I have called CoreCopy().  It does not handle
  31. overlapping moves, even if it would not be difficult to extend it so.
  32.  
  33. It is very portable, but also highly tuned and parametric on the machine
  34. characteristics. I use a set of my own (longish) headers for the parametric
  35. information; they have been summarized here in the file "CoreHdr.h". I hope
  36. that the parameters are self explanatory. The way the parametrization is
  37. used in the CoreCopy source is I hope quite clear, even if virtually all of
  38. the source is preprocessor source, which I have tried to make as readable as
  39. possible. This is one obvious case where very careful hand optimization and
  40. parametrization gives a pay-off and is relevant, as core-to-core copy
  41. bandwidth is often crucial, e.g. to the overall efficiency of the UNIX
  42. kernel.
  43.  
  44. Here is a list of files contained in the attached shar and their
  45. contents:
  46.  
  47. Core.h        The user interface of CoreCopy()
  48. CoreCopy.c    The source for CoreCopy()
  49. CoreHdr.h    Environment parameters
  50. CoreSun3.h    Tuning parameters for Sun 3 machines
  51. CoreSv386.h    Tuning parameters for SysV/386 machines
  52. CoreTest.c    A program to "benchmark" CoreCopy()
  53. CoreRun.sh    A shell script to run CoreTest
  54. CoreSv386.pr    Results of running CoreRun.sh under SysV/386
  55. CoreSun3.pr    Results of running CoreRun.sh on a Sun 3
  56.  
  57. I will provide here some comments on the "benchmark" results:
  58.  
  59. The benchmarks involve three cases, copying a total 16MB, in chunks of 8,
  60. 32, 128, 512 and 2048 bytes; each copy is done first with both source and
  61. destination aligned on a "double" boundary, then with both misaligned by 1
  62. byte, then with source aligned and destination misaligned by 3 bytes, and
  63. then the reverse.
  64.  
  65. User time in seconds.centiseconds is reported, as returned by the OS.
  66.  
  67. The first case does not really copy anything; it is run just to have an idea
  68. of the function calling overhead, which dominates when calling small chunks.
  69. The second is copying using the system provided memcpy(3) function; the
  70. third case is running CoreCopy() itself. (you can if you want run additional
  71. cases, just for comparison, as they do not involve CoreCopy() itself; look
  72. at the "CoreTest.c" file).
  73.  
  74. Some parts of the "benchmark" may be not perfectly portable (one example is
  75. that I ensure that the source and destination buffers are aligned by putting
  76. before their definition a definition for a 'double'), but should be to
  77. nearly every common architecture I can imagine.
  78.  
  79.     Environment of benchmarks:
  80.  
  81.     Sv386 is an i386DX 20Mhz with (write-thru) 64KB cache, running System
  82.     V/386 with the Register C Compiler. As a very rought measure of power,
  83.     it does a bit more than 6000 2.x dhrystone.
  84.  
  85.     Sun3 is a Sun 3/280, 68020 25Mhz with (write-thru?) cache, running
  86.     SunOS 4.0.3 with the PCC descended compiler. This does also a bit
  87.     more than 6000 2.x dhrystones.
  88.  
  89. Here is a subset of the results; on the left is the Sun3, the right is
  90. the Sv386. I have chosen as block sizes 512 because it is large enough
  91. that procedure call overhead is not large, and 32 because it is small
  92. enough that the overhead starts to matter.
  93.  
  94.   .------------------ Size of block copied in bytes
  95.   |
  96.   |    .------------ Destination address modulus 4
  97.   |    |
  98.   |    |    .------- Source address modulus 4
  99.   |    |    |
  100.   |    |    |   .--- Time in seconds.centiseconds to copy 16MB
  101.   |    |    |   |
  102.   |    |    |     |
  103.   V    V    V   V
  104.  
  105. Sun3 memcpy(3)          Sv386 memcpy(3)
  106.  
  107. 512B t% 0 f% 0   2.25u    512B t% 0 f% 0   1.55u    
  108. 512B t% 1 f% 1   3.02u    512B t% 1 f% 1   4.21u
  109. 512B t% 0 f% 3   8.38u    512B t% 0 f% 3   3.32u
  110. 512B t% 3 f% 0   8.44u    512B t% 3 f% 0   2.43u
  111.  32B t% 0 f% 0   7.02u     32B t% 0 f% 0   4.71u
  112.  32B t% 1 f% 1   8.02u     32B t% 1 f% 1   7.39u
  113.  32B t% 0 f% 3  12.20u     32B t% 0 f% 3   6.44u
  114.  32B t% 3 f% 0  12.01u     32B t% 3 f% 0   5.64u
  115.  
  116. Sun3 CoreCopy()          Sv386 CoreCopy()
  117.  
  118. 512B t% 0 f% 0   2.49u    512B t% 0 f% 0   1.68u
  119. 512B t% 1 f% 1   3.11u    512B t% 1 f% 1   1.77u
  120. 512B t% 0 f% 3   4.09u    512B t% 0 f% 3   2.65u
  121. 512B t% 3 f% 0   3.23u    512B t% 3 f% 0   2.57u
  122.  32B t% 0 f% 0   6.10u     32B t% 0 f% 0   6.48u
  123.  32B t% 1 f% 1   6.46u     32B t% 1 f% 1   9.21u
  124.  32B t% 0 f% 3   6.09u     32B t% 0 f% 3   8.28u
  125.  32B t% 3 f% 0   6.29u     32B t% 3 f% 0   7.45u
  126.  
  127.  
  128. The results are often surprising, and must be analyzed with some detailed
  129. knowledge of the logic used by CoreCopy(), memcpy(3), and the performance
  130. profiles of the compiler and CPU architecture and implementation
  131. involved (please also refer to the full set of results in the shar
  132. archive below).
  133.  
  134. In general CoreCopy() is as fast or just a little bit slower than the
  135. in-built memcpy(3) function for aligned copies; it is usually much faster
  136. for unaligned copies. This holds true down to fairly small chunk sizes; for
  137. very small chunk sizes the higher overheads of CoreCopy() become more
  138. important.
  139.  
  140. I have not included any statistics on this, but indeed aligning the
  141. destination instead of the source does provide a significant performance
  142. benefit. Another interesting note is that (4-way) loop unrolling does not
  143. buy much for the machines I have used; probably tight loops in this case are
  144. just as good, because of pipelining or something else. It helps instead to
  145. unroll the code that copies the misaligned head and tail of the core area to
  146. copy, because on most machines 4-way unrolling means that the loop will
  147. never be repeated, because head and tail are 1, 2 or 3 bytes long.
  148.  
  149. Probably substituting memcpy(3) with CoreCopy() on each of the tested
  150. machines would provide overall benefits, because CoreCopy() is only a
  151. little worse then memcpy(3) with aligned copies, but usually
  152. dramatically better with unaligned ones. In particular if you use it in
  153. the "insdel.c" module of GNU Emacs, for which an opportune patch will be
  154. posted, you may experience huge speedups; currently "insdel.c" uses a C
  155. coded char-by-char loop to shift the buffer. Even just using the system
  156. provided bcopy(3) or memcpy(3) will help a lot.
  157.  
  158. It is essential to performance to have inline assembler code on the 386, but
  159. not on the 68020; this is probably because the code to do a string copy on a
  160. 386 looks fairly large -- using the in-built string copy instructions
  161. provides a 3x speedup, probably most because of saving on instruction word
  162. fetches, and the limited pipelining of the 386. It would be interesting to
  163. see how the 486 compares.  It is interesting to note that memcpy(3) on the
  164. 386 also uses the string copy instructions; it however ignores alignment,
  165. and copies word by word until there is less than a wordful of bytes, and
  166. then byte by byte.
  167.  
  168. I think that some inline machine language would also be vital for machines
  169. like the MIPS or SPARC that do traps to support unaligned accesses in
  170. general. I did actually run some cases on a Mips, but the unaligned cases
  171. are simply too slow because of trapping (in the aligned ones CoreCopy() is
  172. as quick as the assembler coded memcpy(3)).
  173.  
  174. You are welcome to provide machine dependent headers for other architectures
  175. and compilers, and to experiment with the various parameters, thresholds,
  176. etc... you will find in the source. I would be interested in knowing the
  177. times for the VAX-11/780, on which the first incarnation of this function
  178. was developed (as soon I had read how the CPU-SBI-Memory interface worked
  179. for byte stores :->).
  180.  
  181. The source and the full result files are in the following shar archive.
  182.  
  183. ---------------------------cut here---------------------------------------
  184. #! /bin/sh
  185. # This is a shell archive.  Remove anything before this line, then unpack
  186. # it by saving it into a file and typing "sh file".  To overwrite existing
  187. # files, type "sh file -c".  You can also feed this as standard input via
  188. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  189. # will see the following message at the end:
  190. #        "End of shell archive."
  191. # Contents:  Core.h CoreCopy.c CoreHdr.h CoreRun.sh CoreSun3.h
  192. #   CoreSun3.pr CoreSv386.h CoreSv386.pr CoreTest.c
  193. # Wrapped by pcg@thor on Tue Sep 25 16:32:40 1990
  194. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  195. echo '
  196.     Copyright 1982,1990 Piercarlo Grandi.  All rights reserved.
  197.  
  198.     This shar archive contains free software; you can redistribute
  199.     it and/or modify it under the terms of the GNU General Public
  200.     License as published by the Free Software Foundation; either
  201.     version 1, or (at your option) any later version.
  202.  
  203.     This shar archive is distributed in the hope that it will be
  204.     useful, but WITHOUT ANY WARRANTY; without even the implied
  205.     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  206.     PURPOSE.  See the GNU General Public License for more details.
  207.  
  208.     You may have received a copy of the GNU General Public License
  209.     along with this program; if not, write to the Free Software
  210.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  211. '
  212. sleep 4
  213. if test -f 'Core.h' -a "${1}" != "-c" ; then 
  214.   echo shar: Will not clobber existing file \"'Core.h'\"
  215. else
  216. echo shar: Extracting \"'Core.h'\" \(487 characters\)
  217. sed "s/^X//" >'Core.h' <<'END_OF_FILE'
  218. X#ifndef Core_H
  219. X#define Core_H
  220. X#if __STDC__
  221. X#   pragma once
  222. X#endif
  223. X
  224. X#if 0
  225. X#ifndef Extend_H
  226. X#   include "Extend.h"
  227. X#endif
  228. X#endif
  229. X
  230. X/*
  231. X    This is a set of library routines to allocate virtual memory and
  232. X    manipulate  it.  It  strives  to  be  reliable  and  consistent,
  233. X    efficient  and  portable.  Unfortunately  this latter quality is
  234. X    more  difficult  to  obtain than the others for such a low level
  235. X    library.
  236. X*/
  237. X
  238. extern pointer        CoreCopy of((pointer,pointer,addressy));
  239. X
  240. X#endif /* Core_H */
  241. END_OF_FILE
  242. if test 487 -ne `wc -c <'Core.h'`; then
  243.     echo shar: \"'Core.h'\" unpacked with wrong size!
  244. fi
  245. # end of 'Core.h'
  246. fi
  247. if test -f 'CoreCopy.c' -a "${1}" != "-c" ; then 
  248.   echo shar: Will not clobber existing file \"'CoreCopy.c'\"
  249. else
  250. echo shar: Extracting \"'CoreCopy.c'\" \(8519 characters\)
  251. sed "s/^X//" >'CoreCopy.c' <<'END_OF_FILE'
  252. X#if 1
  253. X#   include "CoreHdr.h"
  254. X#else
  255. X#ifndef Extend_h
  256. X#   include "Extend.h"
  257. X#endif
  258. X
  259. X#include <import>
  260. X#ifndef Here_h
  261. X#   include "Here.h"
  262. X#endif
  263. X#ifndef With_h
  264. X#   include "With.h"
  265. X#endif
  266. X#ifndef Type_h
  267. X#   include "Type.h"
  268. X#endif
  269. X#ifndef Convert_h
  270. X#   include "Convert.h"
  271. X#endif
  272. X#ifndef Bits_h
  273. X#   include "Bits.h"
  274. X#endif
  275. X#ifndef Assert_h
  276. X#   include "Assert.h"
  277. X#endif
  278. X
  279. X#include <export>
  280. X#endif /* 1 */
  281. X
  282. X#ifndef Core_h
  283. X#   include "Core.h"
  284. X#endif
  285. X
  286. X#if ((CcFEATURE & CcKR78) != CcKR78)
  287. X#   include "ERROR: language supported too old"
  288. X#endif
  289. X
  290. X/*
  291. X    This function is handed pointers to two memory areas, and copies as many
  292. X    units as it is told from the second to the first. The two areas are
  293. X    expected to begin at any byte boundary, and the size is given in bytes
  294. X    too.
  295. X
  296. X    If the memory subsystem of the machine handles more efficiently
  297. X    naturally aligned requests in clusters (multiples of a unit), we try to
  298. X    take advantage of that. Since we cannot take advantage of moving clusters
  299. X    for both source and destination, we optimize the writing of clusters, of
  300. X    course...
  301. X*/
  302. X
  303. X/*
  304. X    We need three copying operations. Only the first is always needed,
  305. X    the remaining two are needed only if copying by clusters pays.
  306. X
  307. X    BYTECOPY(to,from,bytes) copies bytes by byte, the number of bytes is
  308. X    guaranteed to be >= 0.
  309. X
  310. X    ODDCOPY(to,from,bytes) also copies byte by byte, but the number of bytes
  311. X    is guaranteed to be >= 0 && < ClusterBYTES.
  312. X
  313. X    CLUSTERCOPY(to,from,clusters) copies cluster by cluster, and the number
  314. X    of clusters is guaranteed to be > 0.
  315. X
  316. X    For all these macros, the value of bytes is not touched, but to and from
  317. X    are updated to point to the end of the copied area.
  318. X*/
  319. X
  320. X#if (CpuIS == CpuIAPX && CpuMODEL == 0x0386)
  321. X#   include "CoreSv386.h"
  322. X#endif /* CpuIAPX && 0x0386 */
  323. X
  324. X#if (CpuIS == CpuMC68000 && CpuMODEL == 0x0020)
  325. X#   include "CoreSun3.h"
  326. X#endif /* CpuMC68000 && 0x0020 */
  327. X
  328. X#if (CpuIS == CpuMIPS /* && CpuMODEL == 0x3000 */)
  329. X#   include "CoreMips.h"
  330. X#endif /* CpuMIPS */
  331. X
  332. X#ifndef ClusterBITS
  333. X
  334. X#   ifdef CoreFASTALIGN
  335. X#    define ClusterBITS        (CoreFASTALIGN*CpuUNIT)
  336. X#   else
  337. X#    if (CoreFEATURE & (CoreDCACHE|CoreWRITETHRU) == (CoreDCACHE))
  338. X#        define ClusterBITS        (CoreCACHELINE*CpuUNIT)
  339. X#    else
  340. X#        ifdef CoreCORELINE
  341. X#        define ClusterBITS    (CoreCORELINE*CpuUNIT)
  342. X#        else
  343. X#        ifdef CoreINTERLEAVE
  344. X#            define ClusterBITS    (CoreINTERLEAVE*CpuUNIT)
  345. X#        else
  346. X#            define ClusterBITS    CpuUNIT
  347. X#        endif
  348. X#        endif
  349. X#    endif
  350. X#   endif
  351. X
  352. X#   if (ClusterBITS >= LongBITS && (ClusterBITS % LongBITS) == 0)
  353. X#    undef ClusterBITS
  354. X#    define ClusterBITS    LongBITS
  355. X#   endif
  356. X
  357. X#   if ((ClusterBITS % ByteBITS) == 0)
  358. X#    define ClusterBYTES    (ClusterBITS/ByteBITS)
  359. X#   else
  360. X#    include "ERROR: Cluster size is not an even # of bytes"
  361. X#   endif
  362. X
  363. X#endif /* ndef ClusterBITS */
  364. X
  365. X#if (ClusterBYTES > 1)
  366. X
  367. X#   ifndef ClusterLNBYTES
  368. X#    if (ClusterBYTES == 2)
  369. X#        define ClusterLNBYTES    1
  370. X#    endif
  371. X#    if (ClusterBYTES == 4)
  372. X#        define ClusterLNBYTES    2
  373. X#    endif
  374. X#    if (ClusterBYTES == 8)
  375. X#        define ClusterLNBYTES    3
  376. X#    endif
  377. X#   endif
  378. X
  379. X#   ifndef ClusterBEST
  380. X#    if (CoreFEATURE & CoreWRITETHRU)
  381. X#        define ClusterBEST        (ClusterBYTES*4)
  382. X#    else
  383. X#        define ClusterBEST        (ClusterBYTES*8)
  384. X#    endif
  385. X#   endif
  386. X
  387. X#   ifndef ClusterALIGNTO
  388. X#    define ClusterALIGNTO        1
  389. X#   endif
  390. X
  391. X#   ifndef ClusterDOALIGN
  392. X#    define ClusterDOALIGN        (ClusterBEST*4)
  393. X#   endif
  394. X
  395. X#   ifndef ClusterTYPE
  396. X#    if (ClusterBITS == ShortBITS && !defined ClusterTYPE)
  397. X#        define ClusterTYPE        short
  398. X#    endif
  399. X#    if (ClusterBITS == IntBITS && !defined ClusterTYPE)
  400. X#        define ClusterTYPE        int
  401. X#    endif
  402. X#    if (ClusterBITS == LongBITS && !defined ClusterTYPE)
  403. X#        define ClusterTYPE        long
  404. X#    endif
  405. X#    if (!defined ClusterTYPE)
  406. X#        include "ERROR: cannot define a sensible ClusterTYPE"
  407. X#    endif
  408. X#   endif
  409. X
  410. X#   if (!defined ClusterREM && defined ClusterLNBYTES)
  411. X#    define ClusterREM(n)    ((n) & (ClusterBYTES-1))
  412. X#    define ClusterDIV(n)    ((n) >> ClusterLNBYTES)
  413. X#   else
  414. X#    define ClusterREM(n)    ((n) % ClusterBYTES)
  415. X#    define ClusterDIV(n)    ((n) / ClusterBYTES)
  416. X#   endif
  417. X
  418. X#   if (!defined Core4CLUSTERCOPY                    \
  419. X        && (CodeREGISTERS >= 6 || CodePREGISTERS >= 5))
  420. X#       define Core4CLUSTERCOPY(to,from,clusters)            \
  421. X    begindef                            \
  422. X        fast ClusterTYPE    *CoreTo = (ClusterTYPE *) (to);        \
  423. X        fast ClusterTYPE    *CoreFrom = (ClusterTYPE *) (from);    \
  424. X        fast addressy    CoreClusters = (clusters);        \
  425. X        while (CoreClusters) switch (CoreClusters)            \
  426. X        {                                \
  427. X        default:    *CoreTo++ = *CoreFrom++; --CoreClusters;    \
  428. X        case 3:    *CoreTo++ = *CoreFrom++; --CoreClusters;    \
  429. X        case 2:    *CoreTo++ = *CoreFrom++; --CoreClusters;    \
  430. X        case 1:    *CoreTo++ = *CoreFrom++; --CoreClusters;    \
  431. X        case 0:    break; /* keep this "useless" break in ... */    \
  432. X        }                                \
  433. X        /* do *CoreTo++ = *CoreFrom++; while (--CoreClusters); */    \
  434. X        (to) = (pointer) CoreTo, (from) = (pointer) CoreFrom;    \
  435. X    enddef
  436. X#   endif
  437. X
  438. X#   ifndef Core4CLUSTERCOPY
  439. X#    define Core4CLUSTERCOPY(to,from,clusters)            \
  440. X    begindef                            \
  441. X        fast addressy    CoreClusters = (clusters);        \
  442. X        while (CoreClusters) switch (CoreClusters)            \
  443. X        {                                \
  444. X        default:                            \
  445. X        *(ClusterTYPE *) (to) = *(ClusterTYPE *) (from);    \
  446. X        (to) += ClusterBYTES, (from) += ClusterBYTES;        \
  447. X        --CoreClusters;                        \
  448. X        case 3:                            \
  449. X        *(ClusterTYPE *) (to) = *(ClusterTYPE *) (from);    \
  450. X        (to) += ClusterBYTES, (from) += ClusterBYTES;        \
  451. X        --CoreClusters;                        \
  452. X        case 2:                            \
  453. X        *(ClusterTYPE *) (to) = *(ClusterTYPE *) (from);    \
  454. X        (to) += ClusterBYTES, (from) += ClusterBYTES;        \
  455. X        --CoreClusters;                        \
  456. X        case 1:                            \
  457. X        *(ClusterTYPE *) (to) = *(ClusterTYPE *) (from);    \
  458. X        (to) += ClusterBYTES, (from) += ClusterBYTES;        \
  459. X        --CoreClusters;                        \
  460. X        case 0: break; /* keep this "useless" break in ... */    \
  461. X        }                                \
  462. X    enddef
  463. X#   endif
  464. X
  465. X#   ifndef CoreCLUSTERCOPY
  466. X#    define CoreCLUSTERCOPY(to,from,clusters)            \
  467. X    begindef                            \
  468. X        fast addressy    CoreClusters = (clusters);        \
  469. X        do    {   *(ClusterTYPE *) (to) = *(ClusterTYPE *) (from);    \
  470. X            (to) += ClusterBYTES, (from) += ClusterBYTES;    \
  471. X        } while (--CoreClusters);                    \
  472. X    enddef
  473. X#   endif
  474. X
  475. X#endif /* ClusterBYTES > 1 */
  476. X
  477. X#ifndef Core4BYTECOPY
  478. X#   define Core4BYTECOPY(to,from,bytes)                    \
  479. X    begindef                                \
  480. X    fast addressy CoreBytes = (bytes);                \
  481. X    while (CoreBytes) switch (CoreBytes)                \
  482. X    {                                \
  483. X    default:    *(to)++ = *(from)++; --CoreBytes;            \
  484. X    case 3:        *(to)++ = *(from)++; --CoreBytes;            \
  485. X    case 2:        *(to)++ = *(from)++; --CoreBytes;            \
  486. X    case 1:        *(to)++ = *(from)++; --CoreBytes;            \
  487. X    case 0:        break; /* keep this "useless" break in ... */    \
  488. X    }                                \
  489. X    enddef
  490. X#endif /* ndef Core4BYTECOPY */
  491. X
  492. X/*
  493. X    You may want to define this, but at least on my machine (iAPX 386)
  494. X    unrolling loops does not pay.
  495. X*/
  496. X
  497. X#ifndef CoreBYTECOPY
  498. X#   if ((CpuFEATURE&CpuPIPELINE) && !(CpuIS == CpuIAPX && CpuMODEL == 0x0386))
  499. X#    define CoreBYTECOPY        Core4BYTECOPY
  500. X#   endif
  501. X#endif
  502. X
  503. X#ifndef CoreBYTECOPY
  504. X#   define CoreBYTECOPY(to,from,bytes)                    \
  505. X    begindef                                \
  506. X    fast addressy CoreBytes = (bytes);                \
  507. X    while (CoreBytes) *(to)++ = *(from)++, --CoreBytes;        \
  508. X    enddef
  509. X#endif /* ndef CoreBYTECOPY */
  510. X
  511. X#ifndef CoreODDCOPY
  512. X#   if (ClusterBYTES <= 4)
  513. X#    define CoreODDCOPY    Core4BYTECOPY
  514. X#   else
  515. X#    define CoreODDCOPY    CoreBYTECOPY
  516. X#   endif
  517. X#endif /* ndef CoreODDCOPY */
  518. X
  519. global pointer        CoreCopy(to,from,bytes)
  520. X    fast pointer        to;
  521. X    fast pointer        from;
  522. X    addressy            bytes;
  523. X{
  524. X#   ifndef CoreCLUSTERCOPY
  525. X    CoreBYTECOPY(to,from,bytes);
  526. X#   else
  527. X    {
  528. X    copySmallBlock:
  529. X
  530. X    if (bytes < ClusterBEST)
  531. X    {
  532. X        CoreBYTECOPY(to,from,bytes);
  533. X        return to;
  534. X    }
  535. X
  536. X#    if (ClusterDOALIGN != 0)
  537. X    {
  538. X        /*
  539. X                Note that here we usually want align cluster transfers
  540. X                on 'to', as we care more about aligning writes than
  541. X                reads, that are often easier to pipeline.
  542. X        */
  543. X
  544. X    copyHead:
  545. X
  546. X        if (bytes >= ClusterDOALIGN)
  547. X        {
  548. X        addressy            odd;
  549. X
  550. X#        if (ClusterALIGNTO)
  551. X#            define ClusterALIGN        to
  552. X#        else
  553. X#            define ClusterALIGN        from
  554. X#        endif
  555. X
  556. X        if ((odd = ClusterREM((addressy) ClusterALIGN)) != 0)
  557. X        {
  558. X            CoreODDCOPY(to,from,odd = ClusterBYTES - odd);
  559. X            bytes -= odd;
  560. X        }
  561. X
  562. X#        undef ClusterALIGN
  563. X        }
  564. X    }
  565. X#    endif /* ClusterDOALIGN != 0 */
  566. X
  567. X    copyClusters:
  568. X
  569. X    assert (ClusterREM((addressy) to) == 0,"CoreCopy");
  570. X    CoreCLUSTERCOPY(to,from,ClusterDIV(bytes));
  571. X    assert (ClusterREM((addressy) to) == 0,"CoreCopy");
  572. X
  573. X    copyTail:
  574. X
  575. X    CoreODDCOPY(to,from,ClusterREM(bytes));
  576. X    }
  577. X#endif /* ndef CoreCLUSTERCOPY */
  578. X
  579. X    return to;
  580. X}
  581. END_OF_FILE
  582. if test 8519 -ne `wc -c <'CoreCopy.c'`; then
  583.     echo shar: \"'CoreCopy.c'\" unpacked with wrong size!
  584. fi
  585. # end of 'CoreCopy.c'
  586. fi
  587. if test -f 'CoreHdr.h' -a "${1}" != "-c" ; then 
  588.   echo shar: Will not clobber existing file \"'CoreHdr.h'\"
  589. else
  590. echo shar: Extracting \"'CoreHdr.h'\" \(2367 characters\)
  591. sed "s/^X//" >'CoreHdr.h' <<'END_OF_FILE'
  592. X#define CpuIAPX        0x0005
  593. X#define CpuMC68000    0x0006
  594. X#define CpuMIPS        0x0007
  595. X
  596. X#ifdef i386
  597. X#define CpuIS        CpuIAPX        /* Type of instruction set    */
  598. X#define CpuMODEL    0x0386        /* In HEX !            */
  599. X#endif
  600. X#ifdef sun3
  601. X#define CpuIS        CpuMC68000    /* Type of instruction set    */
  602. X#define CpuMODEL    0x0020        /* In HEX !            */
  603. X#endif
  604. X#ifdef mips
  605. X#define CpuIS        CpuMIPS        /* Type of instruction set    */
  606. X#define CpuMODEL    0x3000        /* In HEX !            */
  607. X#endif
  608. X
  609. X#define CpuUNIT        8        /* Bits in addressable unit    */
  610. X
  611. X#define CpuFEATURE    0x0008        /* Peculiarities of CPU        */
  612. X#define CpuPIPELINE    0x0002        /* Multi stage command obey    */
  613. X#define CpuDALIGN    0x000a        /* Must align data        */
  614. X
  615. X#define CoreFEATURE    0x0006        /* Peculiarities of memory sys    */
  616. X#define CoreDCACHE    0x0002        /* Has a DATA cache        */
  617. X#define CoreWRITETHRU    0x0004        /* Updates directly to memory    */
  618. X
  619. X#define CoreCACHELINE    16        /* D cache line size in units    */
  620. X#define CoreCORELINE    4        /* Units to/from mem at a time    */
  621. X#define CoreINTERLEAVE    1        /* Interleaving in units    */
  622. X#define CoreFASTALIGN    4        /* Align at this for fast move    */
  623. X
  624. X#define CcPORTABLE    0x0005        /* Johnson's classic        */
  625. X#define CcREGISTER    0x0006        /* Successor to PORTABLE    */
  626. X
  627. X#ifdef i386
  628. X#define CcIS        CcREGISTER    /* Type (author) of compiler    */
  629. X#define CodeREGISTERS    5        /* Spare universal registers    */
  630. X#define CodeDREGISTERS    0        /* Spare data only registers    */
  631. X#define CodePREGISTERS    0        /* Spare pointer only registers    */
  632. X#endif
  633. X#ifdef sun3
  634. X#define CcIS        CcPORTABLE    /* Type (author) of compiler    */
  635. X#define CodeREGISTERS    0        /* Spare universal registers    */
  636. X#define CodeDREGISTERS    3        /* Spare data only registers    */
  637. X#define CodePREGISTERS    3        /* Spare pointer only registers    */
  638. X#endif
  639. X#ifdef mips
  640. X#define CcIS        CcPORTABLE    /* Type (author) of compiler    */
  641. X#define CodeREGISTERS    8        /* Spare universal registers    */
  642. X#define CodeDREGISTERS    0        /* Spare data only registers    */
  643. X#define CodePREGISTERS    0        /* Spare pointer only registers    */
  644. X#endif
  645. X
  646. X#define CcFEATURE    0x027f        /* Compiler dependent C        */
  647. X#define CcKR78        0x007f        /*=All that is in K&R 1st ed.    */
  648. X#define CcASM        0x0200        /*!asm(" ... ");        */
  649. X
  650. X#define ByteBITS    8
  651. X#define ShortBITS    16
  652. X#define IntBITS        32
  653. X#define LongBITS    32
  654. X
  655. X
  656. X#define    of(ARGS)    (/* ARGS */)
  657. X#define    begindef    do {
  658. X#define enddef        } while (0)
  659. X
  660. X#define global        /* extern */
  661. X#define fast        register
  662. X#define assert(c,m)    /* no op */
  663. X
  664. typedef unsigned    addressy;
  665. typedef char        *pointer;
  666. END_OF_FILE
  667. if test 2367 -ne `wc -c <'CoreHdr.h'`; then
  668.     echo shar: \"'CoreHdr.h'\" unpacked with wrong size!
  669. fi
  670. # end of 'CoreHdr.h'
  671. fi
  672. if test -f 'CoreRun.sh' -a "${1}" != "-c" ; then 
  673.   echo shar: Will not clobber existing file \"'CoreRun.sh'\"
  674. else
  675. echo shar: Extracting \"'CoreRun.sh'\" \(126 characters\)
  676. sed "s/^X//" >'CoreRun.sh' <<'END_OF_FILE'
  677. for C in 0 1 2
  678. do
  679. X    for B in 2048 512 128 32 8
  680. X    do
  681. X    $1    $C    $B    0    0
  682. X    $1    $C    $B    1    1
  683. X    $1    $C    $B    0    3
  684. X    $1    $C    $B    3    0
  685. X    done
  686. done
  687. END_OF_FILE
  688. if test 126 -ne `wc -c <'CoreRun.sh'`; then
  689.     echo shar: \"'CoreRun.sh'\" unpacked with wrong size!
  690. fi
  691. chmod +x 'CoreRun.sh'
  692. # end of 'CoreRun.sh'
  693. fi
  694. if test -f 'CoreSun3.h' -a "${1}" != "-c" ; then 
  695.   echo shar: Will not clobber existing file \"'CoreSun3.h'\"
  696. else
  697. echo shar: Extracting \"'CoreSun3.h'\" \(1135 characters\)
  698. sed "s/^X//" >'CoreSun3.h' <<'END_OF_FILE'
  699. X#define ClusterBITS        32    /* Bits in a cluster        */
  700. X#define ClusterBYTES        4    /* Bytes in a cluster        */
  701. X#define ClusterLNBYTES        2    /* Log2 of ClusterBYTES        */
  702. X#define ClusterTYPE        int    /* The type of a cluster    */
  703. X
  704. X#define ClusterALIGNTO        1    /* Align destination        */
  705. X
  706. X#if (CcIS == CcPORTABLE)
  707. X
  708. X#   define ClusterBEST        16    /* Copy clusters when longer    */
  709. X#   define ClusterDOALIGN    64    /* Align clusters when longer    */
  710. X#   define CoreODDCOPY        CoreBYTECOPY
  711. X
  712. X    /* Asm inlines do not improve speed */
  713. X#   if (0 && (CcFEATURE&CcASM))
  714. X    /*
  715. X        Having had a look at the generated code, we know that to is
  716. X        a5, from is a4, and the count is "always" ready in d0.
  717. X    */
  718. X
  719. X#    define CoreBYTECOPY(to,from,bytes)                \
  720. X    begindef                            \
  721. X        fast unsigned CoreBytes;                    \
  722. X        if (CoreBytes = (bytes)) {                    \
  723. X        asm ("1:    movb    a4@+,a5@+");            \
  724. X        asm ("        dbra    d0,1b"); }            \
  725. X    enddef
  726. X
  727. X#    define CoreCLUSTERCOPY(to,from,clusters)            \
  728. X    begindef                            \
  729. X        fast unsigned CoreClusters;                    \
  730. X        if (CoreClusters = (clusters)) {                \
  731. X        asm ("1:    movl    a4@+,a5@+");            \
  732. X        asm ("        dbra    d0,1b"); }            \
  733. X    enddef
  734. X
  735. X#   endif /* 0 */
  736. X
  737. X#endif /* CsIS == CcPORTABLE */
  738. END_OF_FILE
  739. if test 1135 -ne `wc -c <'CoreSun3.h'`; then
  740.     echo shar: \"'CoreSun3.h'\" unpacked with wrong size!
  741. fi
  742. # end of 'CoreSun3.h'
  743. fi
  744. if test -f 'CoreSun3.pr' -a "${1}" != "-c" ; then 
  745.   echo shar: Will not clobber existing file \"'CoreSun3.pr'\"
  746. else
  747. echo shar: Extracting \"'CoreSun3.pr'\" \(2040 characters\)
  748. sed "s/^X//" >'CoreSun3.pr' <<'END_OF_FILE'
  749. X 16MB C=0 2048B t% 0 f% 0   0.01u
  750. X 16MB C=0 2048B t% 1 f% 1   0.02u
  751. X 16MB C=0 2048B t% 0 f% 3   0.02u
  752. X 16MB C=0 2048B t% 3 f% 0   0.02u
  753. X 16MB C=0  512B t% 0 f% 0   0.07u
  754. X 16MB C=0  512B t% 1 f% 1   0.04u
  755. X 16MB C=0  512B t% 0 f% 3   0.08u
  756. X 16MB C=0  512B t% 3 f% 0   0.04u
  757. X 16MB C=0  128B t% 0 f% 0   0.27u
  758. X 16MB C=0  128B t% 1 f% 1   0.25u
  759. X 16MB C=0  128B t% 0 f% 3   0.25u
  760. X 16MB C=0  128B t% 3 f% 0   0.23u
  761. X 16MB C=0   32B t% 0 f% 0   1.44u
  762. X 16MB C=0   32B t% 1 f% 1   1.52u
  763. X 16MB C=0   32B t% 0 f% 3   1.43u
  764. X 16MB C=0   32B t% 3 f% 0   1.45u
  765. X 16MB C=0    8B t% 0 f% 0   7.04u
  766. X 16MB C=0    8B t% 1 f% 1   7.23u
  767. X 16MB C=0    8B t% 0 f% 3   7.25u
  768. X 16MB C=0    8B t% 3 f% 0   7.25u
  769. X 16MB C=1 2048B t% 0 f% 0   2.10u
  770. X 16MB C=1 2048B t% 1 f% 1   2.45u
  771. X 16MB C=1 2048B t% 0 f% 3   8.38u
  772. X 16MB C=1 2048B t% 3 f% 0   8.37u
  773. X 16MB C=1  512B t% 0 f% 0   2.25u
  774. X 16MB C=1  512B t% 1 f% 1   3.02u
  775. X 16MB C=1  512B t% 0 f% 3   8.38u
  776. X 16MB C=1  512B t% 3 f% 0   8.44u
  777. X 16MB C=1  128B t% 0 f% 0   3.22u
  778. X 16MB C=1  128B t% 1 f% 1   4.32u
  779. X 16MB C=1  128B t% 0 f% 3  10.43u
  780. X 16MB C=1  128B t% 3 f% 0  10.00u
  781. X 16MB C=1   32B t% 0 f% 0   7.02u
  782. X 16MB C=1   32B t% 1 f% 1   8.02u
  783. X 16MB C=1   32B t% 0 f% 3  12.20u
  784. X 16MB C=1   32B t% 3 f% 0  12.01u
  785. X 16MB C=1    8B t% 0 f% 0  22.05u
  786. X 16MB C=1    8B t% 1 f% 1  25.23u
  787. X 16MB C=1    8B t% 0 f% 3  24.37u
  788. X 16MB C=1    8B t% 3 f% 0  24.35u
  789. X 16MB C=2 2048B t% 0 f% 0   3.01u
  790. X 16MB C=2 2048B t% 1 f% 1   2.44u
  791. X 16MB C=2 2048B t% 0 f% 3   3.06u
  792. X 16MB C=2 2048B t% 3 f% 0   3.21u
  793. X 16MB C=2  512B t% 0 f% 0   2.49u
  794. X 16MB C=2  512B t% 1 f% 1   3.11u
  795. X 16MB C=2  512B t% 0 f% 3   4.09u
  796. X 16MB C=2  512B t% 3 f% 0   3.23u
  797. X 16MB C=2  128B t% 0 f% 0   3.48u
  798. X 16MB C=2  128B t% 1 f% 1   4.10u
  799. X 16MB C=2  128B t% 0 f% 3   4.53u
  800. X 16MB C=2  128B t% 3 f% 0   4.19u
  801. X 16MB C=2   32B t% 0 f% 0   6.10u
  802. X 16MB C=2   32B t% 1 f% 1   6.46u
  803. X 16MB C=2   32B t% 0 f% 3   6.09u
  804. X 16MB C=2   32B t% 3 f% 0   6.29u
  805. X 16MB C=2    8B t% 0 f% 0  29.09u
  806. X 16MB C=2    8B t% 1 f% 1  29.53u
  807. X 16MB C=2    8B t% 0 f% 3  28.50u
  808. X 16MB C=2    8B t% 3 f% 0  28.56u
  809. END_OF_FILE
  810. if test 2040 -ne `wc -c <'CoreSun3.pr'`; then
  811.     echo shar: \"'CoreSun3.pr'\" unpacked with wrong size!
  812. fi
  813. # end of 'CoreSun3.pr'
  814. fi
  815. if test -f 'CoreSv386.h' -a "${1}" != "-c" ; then 
  816.   echo shar: Will not clobber existing file \"'CoreSv386.h'\"
  817. else
  818. echo shar: Extracting \"'CoreSv386.h'\" \(1879 characters\)
  819. sed "s/^X//" >'CoreSv386.h' <<'END_OF_FILE'
  820. X#define ClusterBITS        32    /* Bits in a cluster        */
  821. X#define ClusterBYTES        4    /* Bytes in a cluster        */
  822. X#define ClusterLNBYTES        2    /* Log2 of ClusterBYTES        */
  823. X#define ClusterTYPE        int    /* The type of a cluster    */
  824. X
  825. X#define ClusterALIGNTO        1    /* This should be 1; 25% diff.    */
  826. X
  827. X#if (CcIS == CcREGISTER)
  828. X
  829. X#   define ClusterBEST        16    /* Copy clusters when longer    */
  830. X#   define ClusterDOALIGN    64    /* Align clusters when longer    */
  831. X
  832. X    /* This is 0, but should be 1. Cannot get asm procs to work! */
  833. X#   if (0 && (CcFEATURE&CcASM))
  834. X
  835. X    asm void CoreByteCopy(to,from,bytes)
  836. X    {
  837. X    %   ureg to,from; reg bytes;
  838. X
  839. X        movl    to,%edi
  840. X        movl    from,%esi
  841. X        movl    bytes,%ecx
  842. X        rep
  843. X        movsb   /* (%esi),(%edi) */
  844. X    }
  845. X
  846. X    asm void CoreClusterCopy(to,from,clusters)
  847. X    {
  848. X    %   ureg to,from; reg clusters;
  849. X
  850. X        movl    to,%edi
  851. X        movl    from,%esi
  852. X        movl    clusters,%ecx
  853. X        rep
  854. X        movsl   /* (%esi),(%edi) */
  855. X    }
  856. X
  857. X#    define CoreBYTECOPY        CoreByteCopy
  858. X#    define CoreODDCOPY        CoreByteCopy
  859. X#    define CoreCLUSTERCOPY        CoreClusterCopy
  860. X
  861. X#   endif /* 0 */
  862. X
  863. X#   /* This is 1, but should be 0, because we should use inline asm procs */
  864. X#   if (1 && (CcFEATURE&CcASM))
  865. X    /*
  866. X        Having had a look at the generated code, we know that to is
  867. X        %esi, from is in %edi, and bytes is in %ebx.
  868. X    */
  869. X
  870. X#    define CoreBYTECOPY(to,from,bytes)                \
  871. X    begindef                            \
  872. X        fast addressy CoreBytes = (bytes);                \
  873. X        asm ("    movl    %ebx,%ecx");                \
  874. X        asm ("    rep");                        \
  875. X        asm ("    movsb    / (%esi),(%edi)");            \
  876. X    enddef
  877. X
  878. X#    define CoreCLUSTERCOPY(to,from,clusters)            \
  879. X    begindef                            \
  880. X        fast addressy CoreClusters = (clusters);            \
  881. X        asm ("    movl    %ebx,%ecx");                \
  882. X        asm ("    rep");                        \
  883. X        asm ("    movsl    / (%esi),(%edi)");            \
  884. X    enddef
  885. X
  886. X#    define CoreODDCOPY        CoreBYTECOPY
  887. X
  888. X#   endif /* 1 */
  889. X
  890. X#   ifndef CoreCLUSTERCOPY
  891. X#    define CoreCLUSTERCOPY Core4CLUSTERCOPY
  892. X#   endif
  893. X
  894. X#endif /* CsIS == CcREGISTER */
  895. END_OF_FILE
  896. if test 1879 -ne `wc -c <'CoreSv386.h'`; then
  897.     echo shar: \"'CoreSv386.h'\" unpacked with wrong size!
  898. fi
  899. # end of 'CoreSv386.h'
  900. fi
  901. if test -f 'CoreSv386.pr' -a "${1}" != "-c" ; then 
  902.   echo shar: Will not clobber existing file \"'CoreSv386.pr'\"
  903. else
  904. echo shar: Extracting \"'CoreSv386.pr'\" \(2040 characters\)
  905. sed "s/^X//" >'CoreSv386.pr' <<'END_OF_FILE'
  906. X 16MB C=0 2048B t% 0 f% 0   0.05u
  907. X 16MB C=0 2048B t% 1 f% 1   0.05u
  908. X 16MB C=0 2048B t% 0 f% 3   0.05u
  909. X 16MB C=0 2048B t% 3 f% 0   0.05u
  910. X 16MB C=0  512B t% 0 f% 0   0.20u
  911. X 16MB C=0  512B t% 1 f% 1   0.20u
  912. X 16MB C=0  512B t% 0 f% 3   0.20u
  913. X 16MB C=0  512B t% 3 f% 0   0.20u
  914. X 16MB C=0  128B t% 0 f% 0   0.81u
  915. X 16MB C=0  128B t% 1 f% 1   0.81u
  916. X 16MB C=0  128B t% 0 f% 3   0.81u
  917. X 16MB C=0  128B t% 3 f% 0   0.82u
  918. X 16MB C=0   32B t% 0 f% 0   3.23u
  919. X 16MB C=0   32B t% 1 f% 1   3.23u
  920. X 16MB C=0   32B t% 0 f% 3   3.22u
  921. X 16MB C=0   32B t% 3 f% 0   3.22u
  922. X 16MB C=0    8B t% 0 f% 0  12.88u
  923. X 16MB C=0    8B t% 1 f% 1  12.89u
  924. X 16MB C=0    8B t% 0 f% 3  12.88u
  925. X 16MB C=0    8B t% 3 f% 0  12.88u
  926. X 16MB C=1 2048B t% 0 f% 0   1.39u
  927. X 16MB C=1 2048B t% 1 f% 1   4.08u
  928. X 16MB C=1 2048B t% 0 f% 3   3.16u
  929. X 16MB C=1 2048B t% 3 f% 0   2.28u
  930. X 16MB C=1  512B t% 0 f% 0   1.55u
  931. X 16MB C=1  512B t% 1 f% 1   4.21u
  932. X 16MB C=1  512B t% 0 f% 3   3.32u
  933. X 16MB C=1  512B t% 3 f% 0   2.43u
  934. X 16MB C=1  128B t% 0 f% 0   2.18u
  935. X 16MB C=1  128B t% 1 f% 1   4.84u
  936. X 16MB C=1  128B t% 0 f% 3   3.94u
  937. X 16MB C=1  128B t% 3 f% 0   3.07u
  938. X 16MB C=1   32B t% 0 f% 0   4.71u
  939. X 16MB C=1   32B t% 1 f% 1   7.39u
  940. X 16MB C=1   32B t% 0 f% 3   6.44u
  941. X 16MB C=1   32B t% 3 f% 0   5.64u
  942. X 16MB C=1    8B t% 0 f% 0  14.79u
  943. X 16MB C=1    8B t% 1 f% 1  17.57u
  944. X 16MB C=1    8B t% 0 f% 3  16.10u
  945. X 16MB C=1    8B t% 3 f% 0  16.10u
  946. X 16MB C=2 2048B t% 0 f% 0   1.42u
  947. X 16MB C=2 2048B t% 1 f% 1   1.44u
  948. X 16MB C=2 2048B t% 0 f% 3   2.33u
  949. X 16MB C=2 2048B t% 3 f% 0   2.31u
  950. X 16MB C=2  512B t% 0 f% 0   1.68u
  951. X 16MB C=2  512B t% 1 f% 1   1.77u
  952. X 16MB C=2  512B t% 0 f% 3   2.65u
  953. X 16MB C=2  512B t% 3 f% 0   2.57u
  954. X 16MB C=2  128B t% 0 f% 0   2.72u
  955. X 16MB C=2  128B t% 1 f% 1   3.03u
  956. X 16MB C=2  128B t% 0 f% 3   3.89u
  957. X 16MB C=2  128B t% 3 f% 0   3.61u
  958. X 16MB C=2   32B t% 0 f% 0   6.48u
  959. X 16MB C=2   32B t% 1 f% 1   9.21u
  960. X 16MB C=2   32B t% 0 f% 3   8.28u
  961. X 16MB C=2   32B t% 3 f% 0   7.45u
  962. X 16MB C=2    8B t% 0 f% 0  22.22u
  963. X 16MB C=2    8B t% 1 f% 1  22.24u
  964. X 16MB C=2    8B t% 0 f% 3  22.23u
  965. X 16MB C=2    8B t% 3 f% 0  22.23u
  966. END_OF_FILE
  967. if test 2040 -ne `wc -c <'CoreSv386.pr'`; then
  968.     echo shar: \"'CoreSv386.pr'\" unpacked with wrong size!
  969. fi
  970. # end of 'CoreSv386.pr'
  971. fi
  972. if test -f 'CoreTest.c' -a "${1}" != "-c" ; then 
  973.   echo shar: Will not clobber existing file \"'CoreTest.c'\"
  974. else
  975. echo shar: Extracting \"'CoreTest.c'\" \(3039 characters\)
  976. sed "s/^X//" >'CoreTest.c' <<'END_OF_FILE'
  977. X#include <sys/types.h>
  978. X#include <sys/times.h>
  979. X#include <sys/param.h>
  980. X
  981. X#ifndef HZ
  982. X#    define HZ 60
  983. X#endif
  984. X
  985. X#include <stdio.h>
  986. X
  987. X#ifndef B
  988. X#   define B        4096        /* Maximum & default # of bytes    */
  989. X#endif
  990. X#ifndef M
  991. X#   define M        (16<<20)    /* Default megabytes copied    */
  992. X#endif
  993. X
  994. typedef char        *(*method)();
  995. X
  996. static time_t        measure(p,t,f,b)
  997. X    register method        p;
  998. X    register char        *t,*f;
  999. X    register unsigned        b;
  1000. X{
  1001. X    register unsigned        i;
  1002. X    struct tms            tms;
  1003. X    time_t            utime;
  1004. X
  1005. X    (void) times(&tms);
  1006. X    utime = tms.tms_utime;
  1007. X
  1008. X    for (i = 0; i < M; i += b)
  1009. X    (void) (*p)(t,f,b);
  1010. X
  1011. X    (void) times(&tms);
  1012. X    return tms.tms_utime - utime;
  1013. X}
  1014. X
  1015. extern char        *null();
  1016. extern char        *memcpy();
  1017. extern char        *CoreCopy();
  1018. extern char        *copy1();
  1019. extern char        *copy2();
  1020. extern char        *copy3();
  1021. X
  1022. static method        methods[] = {null,memcpy,CoreCopy,copy1,copy2,copy3};
  1023. static unsigned        nmethods = sizeof methods/sizeof (method);
  1024. X
  1025. X#define SLOP        sizeof (long unsigned)
  1026. X
  1027. long unsigned        alignit1;
  1028. char            bfrom[B+SLOP];
  1029. X
  1030. long unsigned        alignit2;
  1031. char            bto[B+SLOP];
  1032. X
  1033. extern int        main(argc,argv)
  1034. X    int                argc;
  1035. X    char            **argv;
  1036. X{
  1037. X    register unsigned        i,b;
  1038. X    register char        *f,*t;
  1039. X    unsigned            of,ot;
  1040. X    unsigned            m;
  1041. X    time_t            utime;
  1042. X    
  1043. X
  1044. X    m    = (argc <= 1) ? 0 : atoi(argv[1]);
  1045. X    b    = (argc <= 2) ? B : atoi(argv[2]);
  1046. X    ot    = (argc <= 3) ? 1 : atoi(argv[3]);
  1047. X    of    = (argc <= 4) ? 1 : atoi(argv[4]);
  1048. X
  1049. X    if (m >= nmethods)        m = 1;
  1050. X    if (b > B)            b = B;
  1051. X    if (ot > SLOP)        ot %= SLOP;
  1052. X    if (of > SLOP)        of %= SLOP;
  1053. X
  1054. X    f = bfrom + of; t = bto + ot;
  1055. X
  1056. X    printf("%3uMB C=%u %4uB t%% %u f%% %u ",
  1057. X        M>>20,m,b,(unsigned) t%SLOP,(unsigned) f%SLOP);
  1058. X    fflush(stdout);
  1059. X
  1060. X    utime = measure(methods[m],f,t,b);
  1061. X
  1062. X    printf("%3u.%02uu\n",utime/HZ,utime%HZ);
  1063. X    fflush(stdout);
  1064. X
  1065. X    return 0;
  1066. X}
  1067. X
  1068. extern char        *null(to,from,bytes)
  1069. X    register char        *to,*from;
  1070. X    register unsigned        bytes;
  1071. X{
  1072. X    return to+bytes;
  1073. X}
  1074. X
  1075. extern char        *copy1(to,from,bytes)
  1076. X    register char        *to,*from;
  1077. X    register unsigned        bytes;
  1078. X{
  1079. X    if (bytes)
  1080. X    {
  1081. X    do *to++ = *from++;
  1082. X    while (--bytes);
  1083. X    }
  1084. X
  1085. X    return to;
  1086. X}
  1087. X
  1088. extern char        *copy2(to,from,bytes)
  1089. X    register char        *to,*from;
  1090. X    register unsigned        bytes;
  1091. X{
  1092. X    while (bytes >= sizeof (long))
  1093. X    {
  1094. X    *(long *) to = *(long *) from;
  1095. X    to += sizeof (long), from += sizeof (long);
  1096. X    bytes -= sizeof (long);
  1097. X    }
  1098. X
  1099. X    if (bytes)
  1100. X    {
  1101. X    do *to++ = *from++;
  1102. X    while (--bytes);
  1103. X    }
  1104. X
  1105. X    return to;
  1106. X}
  1107. X
  1108. extern char        *copy3(to,from,bytes)
  1109. X    register char        *to,*from;
  1110. X    register unsigned        bytes;
  1111. X{
  1112. X    while (bytes >= 2*sizeof (long))
  1113. X    {
  1114. X    *(long *) to = *(long *) from;
  1115. X    *((long *) to + 1) = *((long *) from +1);
  1116. X    to +=2*sizeof (long), from += 2*sizeof (long);
  1117. X    bytes -= 2*sizeof (long);
  1118. X    }
  1119. X
  1120. X    while (bytes >= sizeof (long))
  1121. X    {
  1122. X    *(long *) to = *(long *) from;
  1123. X    to += sizeof (long), from += sizeof (long);
  1124. X    bytes -= sizeof (long);
  1125. X    }
  1126. X
  1127. X    if (bytes)
  1128. X    {
  1129. X    do *to++ = *from++;
  1130. X    while (--bytes);
  1131. X    }
  1132. X
  1133. X    return to;
  1134. X}
  1135. END_OF_FILE
  1136. if test 3039 -ne `wc -c <'CoreTest.c'`; then
  1137.     echo shar: \"'CoreTest.c'\" unpacked with wrong size!
  1138. fi
  1139. # end of 'CoreTest.c'
  1140. fi
  1141. echo shar: End of shell archive.
  1142. exit 0
  1143. --
  1144. Piercarlo "Peter" Grandi           | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
  1145. Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
  1146. Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
  1147.