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

@ -9,16 +9,16 @@ long. That means that it can never execute in less than 24 cycles even
if the 4-byte prefetch queue is full when it starts, since 6 instruction
bytes would still remain to be fetched, at 4 cycles per fetch. If the
prefetch queue is empty at the start, the sequence *could* take 40
cycles. In short, thanks to instruction fetching, the code won’t run at
cycles. In short, thanks to instruction fetching, the code won't run at
its documented speed, and could take up to four times longer than it is
supposed to.
Why does Intel document Execution Unit execution time rather than
overall instruction execution time, which includes both instruction
fetch time and Execution Unit (EU) execution time? Well, instruction
fetching isn’t performed as part of instruction execution by the
fetching isn't performed as part of instruction execution by the
Execution Unit, but instead is carried on in parallel by the Bus
Interface Unit (BIU) whenever the external data bus isn’t in use or
Interface Unit (BIU) whenever the external data bus isn't in use or
whenever the EU runs out of instruction bytes to execute. Sometimes the
BIU is able to use spare bus cycles to prefetch instruction bytes before
the EU needs them, so in those cases instruction fetching takes no time
@ -34,14 +34,14 @@ overall execution time of the following instructions.
![](images/i.jpg) *In other words, while the execution time for a given instruction is constant, the fetch time for that instruction depends heavily on the context in which the instruction is executing—the amount of prefetching the preceding instructions allowed—and can vary from a full 4 cycles per instruction byte to no time at all.*
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
As we’ll see later, other cycle-eaters, such as DRAM refresh and display
As we'll see later, other cycle-eaters, such as DRAM refresh and display
memory wait states, can cause prefetching variations even during
different executions of the same code sequence. Given that, it’s
different executions of the same code sequence. Given that, it's
meaningless to talk about the prefetch time of a given instruction
except in the context of a specific code sequence.
So now you know why the official instruction execution times are often
wrong, and why Intel can’t provide better specifications. You also know
wrong, and why Intel can't provide better specifications. You also know
now why it is that you must time your code if you want to know how fast
it really is.
@ -57,16 +57,16 @@ the timer can cause problems.
Some slight prefetch queue-induced inaccuracy usually exists even when
the Zen timer is used to time longer code sequences, since the calls to
the Zen timer usually alter the code’s prefetch queue from its normal
the Zen timer usually alter the code's prefetch queue from its normal
state. (Branches—jumps, calls, returns and the like—empty the prefetch
queue.) Ideally, the Zen timer is used to measure the performance of an
entire subroutine, so the prefetch queue effects of the branches at the
start and end of the subroutine are similar to the effects of the calls
to the Zen timer when you’re measuring the subroutine’s performance.
to the Zen timer when you're measuring the subroutine's performance.
Another way in which the prefetch queue cycle-eater complicates the use
of the Zen timer involves the practice of timing the performance of a
few instructions over and over. I’ll often repeat one or two
few instructions over and over. I'll often repeat one or two
instructions 100 or 1,000 times in a row in listings in this book in
order to get timing intervals that are long enough to provide reliable
measurements. However, as we just learned, the actual performance of any
@ -84,12 +84,12 @@ always empty, execution time should work out to about 4 cycles per byte,
or 8 cycles per **SHR,** as shown in Figure 4.3. (Figure 4.3 illustrates
the relationship between instruction fetching and execution in a
simplified way, and is not intended to show the exact timings of 8088
operations.) That’s quite a contrast to the official 2-cycle execution
operations.) That's quite a contrast to the official 2-cycle execution
time of **SHR**. In fact, the Zen timer reports that Listing 4.5
executes in 1.81µs per byte, or slightly *more* than 4 cycles per byte.
(The extra time is the result of the dynamic RAM refresh cycle-eater,
which we’ll discuss shortly.) Going by Listing 4.5, we would conclude
that the “true” execution time of **SHR** is 8.64 cycles.
which we'll discuss shortly.) Going by Listing 4.5, we would conclude
that the "true" execution time of **SHR** is 8.64 cycles.
**LISTING 4.5 LST4-5.ASM**
@ -124,20 +124,20 @@ that the “true” execution time of **SHR** is 8.64 cycles.
**Figure 4.3**  *Execution and instruction prefetching sequence for
Listing 4.5.*
Now let’s examine Listing 4.6. Here each **SHR** follows a **MUL**
Now let's examine Listing 4.6. Here each **SHR** follows a **MUL**
instruction. Since **MUL** instructions take so long to execute that the
prefetch queue is always full when they finish, each **SHR** should be
ready and waiting in the prefetch queue when the preceding **MUL** ends.
As a result, we’d expect that each **SHR** would execute in 2 cycles;
As a result, we'd expect that each **SHR** would execute in 2 cycles;
together with the 118-cycle execution time of multiplying 0 times 0, the
total execution time should come to 120 cycles per **SHR/MUL** pair, as
shown in Figure 4.4. And, by God, when we run Listing 4.6 we get an
execution time of 25.14 µs per **SHR/MUL** pair, or *exactly* 120
cycles! According to these results, the “true” execution time of **SHR**
cycles! According to these results, the "true" execution time of **SHR**
would seem to be 2 cycles, quite a change from the conclusion we drew
from Listing 4.5.
The key point is this: We’ve seen one code sequence in which **SHR**
The key point is this: We've seen one code sequence in which **SHR**
took 8-plus cycles to execute, and another in which it took only 2
cycles. Are we talking about two different forms of **SHR** here? Of
course not—the difference is purely a reflection of the differing states