Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
34
12-04.md
34
12-04.md
|
|
@ -2,17 +2,17 @@
|
|||
[Previous](12-03.html) [Table of Contents](index.html) [Next](13-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
You don’t need to understand every corner of the 486 universe unless
|
||||
you’re a diehard ASMhead who does this stuff for fun. Just learn enough
|
||||
You don't need to understand every corner of the 486 universe unless
|
||||
you're a diehard ASMhead who does this stuff for fun. Just learn enough
|
||||
to be able to speed up the key portions of your programs, and spend the
|
||||
rest of your time on a fast design and overall implementation.
|
||||
|
||||
#### More Fun with Byte Registers {#Heading10}
|
||||
|
||||
Rule \#4: Don’t load *any* byte register exactly 2 cycles before using
|
||||
Rule \#4: Don't load *any* byte register exactly 2 cycles before using
|
||||
*any* register to address memory.
|
||||
|
||||
This, the last of this chapter’s rules, is the strangest of the lot. If
|
||||
This, the last of this chapter's rules, is the strangest of the lot. If
|
||||
any byte register is loaded, and then two cycles later any register is
|
||||
used to point to memory, one cycle is lost. So, for example, this code
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ runs in the expected three cycles.
|
|||
|
||||
In truth, I do not know why this happens. Clearly, it has something to
|
||||
do with interrupting the start of the addressing pipeline, and I have my
|
||||
theories about how this works, but at this point they’re pure
|
||||
theories about how this works, but at this point they're pure
|
||||
speculation. Whatever the reason for this rule, ignorance of it—and of
|
||||
its interaction with the other rules—could lead to considerable
|
||||
performance loss in seemingly air-tight code. For instance, a casual
|
||||
|
|
@ -68,7 +68,7 @@ pipeline is now on its first cycle: the one that loading a byte register
|
|||
can affect.
|
||||
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *I know—it seems awfully complicated. It isn’t, really. Generally, try not to use byte destinations exactly two cycles before using a register to address memory, and try not to load a register either one or two cycles before using it to address memory, and you’ll be fine.*
|
||||
 *I know—it seems awfully complicated. It isn't, really. Generally, try not to use byte destinations exactly two cycles before using a register to address memory, and try not to load a register either one or two cycles before using it to address memory, and you'll be fine.*
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#### Timing Your Own 486 Code {#Heading11}
|
||||
|
|
@ -82,7 +82,7 @@ address memory. Listing 12.1 ran in 120 µs on a 33 MHz 486, or 4 cycles
|
|||
per repetition (120 µs/1000 repetitions = 120 ns per repetition; 120 ns
|
||||
per repetition/30 ns per cycle = 4 cycles per repetition); Listing 12.2
|
||||
ran in 90 µs, or 3 cycles, establishing that loading a byte register
|
||||
costs a cycle only when it’s performed exactly 2 cycles before
|
||||
costs a cycle only when it's performed exactly 2 cycles before
|
||||
addressing memory.
|
||||
|
||||
**LISTING 12.1 LST12-1.ASM**
|
||||
|
|
@ -90,7 +90,7 @@ addressing memory.
|
|||
; Measures the effect of loading a byte register 2 cycles before
|
||||
; using a register to address memory.
|
||||
mov bp,2 ;run the test code twice to make sure
|
||||
; it’s cached
|
||||
; it's cached
|
||||
sub bx,bx
|
||||
CacheFillLoop:
|
||||
call ZTimerOn ;start timing
|
||||
|
|
@ -110,7 +110,7 @@ addressing memory.
|
|||
; Measures the effect of loading a byte register 1 cycle before
|
||||
; using a register to address memory.
|
||||
mov bp,2 ;run the test code twice to make sure
|
||||
; it’s cached
|
||||
; it's cached
|
||||
sub bx,bx
|
||||
CacheFillLoop:
|
||||
call ZTimerOn ;start timing
|
||||
|
|
@ -129,31 +129,31 @@ Note that Listings 12.1 and 12.2 each repeat the timing of the code
|
|||
under test a second time, to make sure that the instructions are in the
|
||||
cache on the second pass, the one for which results are displayed. Also
|
||||
note that the code is less than 8K in size, so that it can all fit in
|
||||
the 486’s 8K internal cache. If I double the **REPT** value in Listing
|
||||
the 486's 8K internal cache. If I double the **REPT** value in Listing
|
||||
12.2 to 2,000, making the test code larger than 8K, the execution time
|
||||
more than doubles to 224 µs, or 3.7 cycles per repetition; the extra
|
||||
seven-tenths of a cycle comes from fetching non-cached instruction
|
||||
bytes.
|
||||
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------
|
||||
 *Whenever you see non-integral timing results of this sort, it’s a good bet that the test code or data isn’t cached.*
|
||||
 *Whenever you see non-integral timing results of this sort, it's a good bet that the test code or data isn't cached.*
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
### The Story Continues {#Heading12}
|
||||
|
||||
There’s certainly plenty more 486 lore to explore, including the 486’s
|
||||
There's certainly plenty more 486 lore to explore, including the 486's
|
||||
unique prefetch queue, more optimization rules, branching optimizations,
|
||||
performance implications of the cache, the cost of cache misses for
|
||||
reads, and the implications of cache write-through for writes.
|
||||
Nonetheless, we’ve covered quite a bit of ground in this chapter, and I
|
||||
trust you’ve gotten a feel for the considerable extent to which 486
|
||||
optimization differs from what you’re used to. Odd as 486 optimization
|
||||
is, though, it’s well worth mastering, for the 486 is, at its best, so
|
||||
Nonetheless, we've covered quite a bit of ground in this chapter, and I
|
||||
trust you've gotten a feel for the considerable extent to which 486
|
||||
optimization differs from what you're used to. Odd as 486 optimization
|
||||
is, though, it's well worth mastering, for the 486 is, at its best, so
|
||||
staggeringly fast that carefully crafted 486 code can do more than twice
|
||||
as much per cycle as the best 386 code—which makes it perhaps 50 times
|
||||
as fast as optimized code for the original PC.
|
||||
|
||||
Sometimes it *is* hard to believe we’re still in Kansas!
|
||||
Sometimes it *is* hard to believe we're still in Kansas!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-03.html) [Table of Contents](index.html) [Next](13-01.html)
|
||||
|
|
|
|||
Loading…
Reference in a new issue