Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
34
12-03.md
34
12-03.md
|
|
@ -2,11 +2,11 @@
|
|||
[Previous](12-02.html) [Table of Contents](index.html) [Next](12-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
There is, of course, no guarantee that I’m entirely correct about the
|
||||
There is, of course, no guarantee that I'm entirely correct about the
|
||||
optimizations discussed in this chapter. Without knowing the internals
|
||||
of the 486, all I can do is time code and make inferences from the
|
||||
results; I invite you to deduce your own rules and cross-check them
|
||||
against mine. Also, most likely there are other optimizations that I’m
|
||||
against mine. Also, most likely there are other optimizations that I'm
|
||||
unaware of. If you have further information on these or any other
|
||||
undocumented optimizations, please write and let me know. And, of
|
||||
course, if anyone from Intel is reading this and wants to give us the
|
||||
|
|
@ -27,11 +27,11 @@ of the first set of instructions and is then immediately used to address
|
|||
memory by one of the second set. This raises the specter of unpleasant
|
||||
programming contortions such as intermixing **PUSH**es and **POP**s with
|
||||
other instructions to avoid interrupting the addressing pipeline.
|
||||
Fortunately, matters are actually not so grim as Intel’s documentation
|
||||
Fortunately, matters are actually not so grim as Intel's documentation
|
||||
would indicate; my tests indicate that the addressing pipeline penalty
|
||||
pops up only spottily when the stack pointer is involved.
|
||||
|
||||
For example, you’d certainly expect a sequence such as
|
||||
For example, you'd certainly expect a sequence such as
|
||||
|
||||
:
|
||||
pop ax
|
||||
|
|
@ -69,11 +69,11 @@ the sequence
|
|||
|
||||
loses two cycles for the same reason.
|
||||
|
||||
I certainly haven’t tried all possible combinations, but the results so
|
||||
I certainly haven't tried all possible combinations, but the results so
|
||||
far indicate that the stack pointer incurs the addressing pipeline
|
||||
penalty only if (E)SP is the *explicit* destination of one instruction
|
||||
and is then used by one of the two following instructions to address
|
||||
memory. So, for instance, SP isn’t the explicit operand of **POP AX—**AX
|
||||
memory. So, for instance, SP isn't the explicit operand of **POP AX—**AX
|
||||
is—and no cycles are lost if **POP AX** is followed by **POP** or
|
||||
**RET**. Happily, then, we need not worry about the sequence in which we
|
||||
use **PUSH** and **POP**. However, adding to, moving to, or subtracting
|
||||
|
|
@ -84,7 +84,7 @@ pointer to address memory.
|
|||
#### Problems with Byte Registers {#Heading9}
|
||||
|
||||
There are two ways to lose cycles by using byte registers, and neither
|
||||
of them is documented by Intel, so far as I know. Let’s start with the
|
||||
of them is documented by Intel, so far as I know. Let's start with the
|
||||
lesser and simpler of the two.
|
||||
|
||||
Rule \#3: Do not load a byte portion of a register during one
|
||||
|
|
@ -101,7 +101,7 @@ So, for example, it would be a bad idea to do this
|
|||
|
||||
because AL is loaded by one instruction, then AX is used as the source
|
||||
register for the next instruction. A cycle can be saved simply by
|
||||
rearranging the instructions so that the byte register load isn’t
|
||||
rearranging the instructions so that the byte register load isn't
|
||||
immediately followed by the word register usage, like so:
|
||||
|
||||
mov ah,o
|
||||
|
|
@ -115,16 +115,16 @@ Basically, when a byte destination register is part of a word source
|
|||
register for the next instruction, the 486 is unable to directly use the
|
||||
result from the first instruction as the source for the second
|
||||
instruction, because only part of the register required by the second
|
||||
instruction is contained in the first instruction’s result. The full,
|
||||
instruction is contained in the first instruction's result. The full,
|
||||
updated register value must be read from the register file, and that
|
||||
value can’t be read out until the result from the first instruction has
|
||||
value can't be read out until the result from the first instruction has
|
||||
been written *into* the register file, a process that takes an extra
|
||||
cycle. I’m not going to explain this in great detail because it’s not
|
||||
cycle. I'm not going to explain this in great detail because it's not
|
||||
important that you understand why this rule exists (only that it *does*
|
||||
in fact exist), but it is an interesting window on the way the 486
|
||||
works.
|
||||
|
||||
In case you’re curious, there’s no such penalty for the typical **XLAT**
|
||||
In case you're curious, there's no such penalty for the typical **XLAT**
|
||||
sequence like
|
||||
|
||||
mov bx,offset MemTable
|
||||
|
|
@ -139,17 +139,17 @@ is so slow—4 cycles—that it gives the 486 time to perform addressing
|
|||
calculations during the course of the instruction.
|
||||
|
||||
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *While it’s nice that **XLAT** doesn’t suffer from the various 486 addressing penalties, the reason for that is basically that **XLAT** is slow, so there’s still no compelling reason to use **XLAT** on the 486.*
|
||||
 *While it's nice that **XLAT** doesn't suffer from the various 486 addressing penalties, the reason for that is basically that **XLAT** is slow, so there's still no compelling reason to use **XLAT** on the 486.*
|
||||
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
In general, penalties for interrupting the 486’s pipeline apply
|
||||
In general, penalties for interrupting the 486's pipeline apply
|
||||
primarily to the fast core instructions of the 486, most notably
|
||||
register-only instructions and **MOV**, although arithmetic and logical
|
||||
operations that access memory are also often affected. I don’t know all
|
||||
the performance dependencies, and I don’t plan to; figuring all of them
|
||||
operations that access memory are also often affected. I don't know all
|
||||
the performance dependencies, and I don't plan to; figuring all of them
|
||||
out would be a big, boring job of little value. Basically, on the 486
|
||||
you should concentrate on using those fast core instructions when
|
||||
performance matters, and all the rules I’ll discuss do indeed apply to
|
||||
performance matters, and all the rules I'll discuss do indeed apply to
|
||||
those instructions.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue