Normal quotes

This commit is contained in:
James Gregory 2013-12-30 18:34:31 +11:00
commit 18011c595a
352 changed files with 6040 additions and 6040 deletions

View file

@ -4,14 +4,14 @@
The first, obvious thing we can do to Listing 21.1 is change **ADC
AX,0** to **ADC EAX,0**, eliminating a prefix byte and saving a full
cycle. Now we’re down from five to four cycles. What next?
cycle. Now we're down from five to four cycles. What next?
Listing 21.2 shows one interesting alternative that doesn’t really buy
us anything. Here, we’ve eliminated all size prefixes by doing
Listing 21.2 shows one interesting alternative that doesn't really buy
us anything. Here, we've eliminated all size prefixes by doing
byte-sized **MOVs** and **ADDs**, but because the size prefix on **ADD
AX,[ESI]**, for whatever reason, didn’t cost anything in Listing 21.1,
AX,[ESI]**, for whatever reason, didn't cost anything in Listing 21.1,
our efforts are to no avail—Listing 21.2 still takes 4 cycles per
checksummed word. What’s worth noting about Listing 21.2 is the extent
checksummed word. What's worth noting about Listing 21.2 is the extent
to which the code is broken into simple instructions and reordered so as
to avoid size prefixes, register contention, AGIs, and data bank
conflicts (the latter because both **[ESI]** and **[ESI+1]** are in the
@ -28,7 +28,7 @@ same cache data bank, as discussed in the last chapter).
sub eax,eax ;initialize the checksum
mov dx,[esi] ;first word to checksum
dec ecx ;we’ll do 1 checksum outside the loop
dec ecx ;we'll do 1 checksum outside the loop
jz short ckloopend ;only 1 checksum to do
add esi,2 ;point to the next word to checksum
@ -50,7 +50,7 @@ Listing 21.3 is a more sophisticated attempt to speed up the checksum
calculation. Here we see a hallmark of Pentium optimization: two
operations (the checksumming of the current and next pair of words)
interleaved together to allow both pipes to run at near maximum
capacity. Another hallmark that’s apparent in Listing 21.3 is that
capacity. Another hallmark that's apparent in Listing 21.3 is that
Pentium-optimized code tends to use more registers and require more
instructions than 486-optimized code. Again, note the careful mixing of
byte-sized reads to avoid AGIs, register contention, and cache bank
@ -69,7 +69,7 @@ placement of **ADD ESI,4** to avoid an AGI.
sub eax,eax ;initialize the checksum
sub edx,edx ;prepare for later ORing
shr ecx,1 ;we’ll do two words per loop
shr ecx,1 ;we'll do two words per loop
jnc short ckloopsetup ;even number of words
mov ax,[esi] ;do the odd word
jz short ckloopdone ;no more words to checksum
@ -109,14 +109,14 @@ placement of **ADD ESI,4** to avoid an AGI.
The checksum loop in Listing 21.3 takes longer than the loop in Listing
21.2, at 6 cycles versus 4 cycles for Listing 21.2—but Listing 21.3 does
two checksum operations in those 6 cycles, so we’ve cut the time per
two checksum operations in those 6 cycles, so we've cut the time per
checksum addition from 4 to 3 cycles. You might think that this small an
improvement doesn’t justify the additional complexity of Listing 21.3,
improvement doesn't justify the additional complexity of Listing 21.3,
but it is a one-third speedup, well worth it if this is a critical
loop—and, in general, if it isn’t critical, there’s no point in
hand-tuning it. That’s why I haven’t bothered to try to optimize the
non-inner-loop code in Listing 21.3; it’s only executed once per
checksum, so it’s unlikely that a cycle or two saved there would make
loop—and, in general, if it isn't critical, there's no point in
hand-tuning it. That's why I haven't bothered to try to optimize the
non-inner-loop code in Listing 21.3; it's only executed once per
checksum, so it's unlikely that a cycle or two saved there would make
any real-world difference.
Listing 21.3 could be made a bit faster yet with some loop unrolling,
@ -127,12 +127,12 @@ time to eliminate both the word prefix of Listing 21.1 and the multiple
byte-sized accesses of Listing 21.3. An obvious drawback to this is the
considerable complexity needed to ensure that the dword accesses are
dword-aligned (remember that unaligned dword accesses cost three cycles
each), and to handle buffer lengths that aren’t dword multiples. I’ve
each), and to handle buffer lengths that aren't dword multiples. I've
handled these problems by requiring that the buffer be dword-aligned and
a dword multiple in length, which is of course not always the case in
the real world. However, the point of these listings is to illustrate
Pentium optimization—dword issues, being non-inner-loop stuff, are
solvable details that aren’t germane to the main focus. In any case, the
solvable details that aren't germane to the main focus. In any case, the
complexity and assumptions are well justified by the performance of this
code: three cycles per loop, or 1.5 cycles per checksummed word, more
than three times the speed of the original code. Again, note that the