3 ms·
No, thats not it as explained in my reply to that TerrifiedMouse comment in 2023 :) On x86 Integer instructions _never_ waited for floating point opcode to ret
by rasz 2y ago
No, thats not it as explained in my reply to that TerrifiedMouse comment in 2023 :)
On x86 Integer instructions _never_ waited for floating point opcode to retire. You can check it yourself by reading FPU status register busy flag - if FPU was blocking you could never catch it in BUSY state and FWAIT would be useless :-)
Abrash exploited the fact Pentium was the first time x87 FPU instructions could run pipelined overlapping one another. All other x86 vendors FPUs waited for previous FPU instruction to retire.
https://www.agner.org/optimize/microarchitecture.pdf https://www.agner.org/optimize/microarchitecture.pdf page 47
While floating point instructions in general cannot be paired, many can be pipelined, i.e. one
instruction can begin before the previous instruction has finished. Example:
fadd st1,st0 ; Clock cycle 1-3
fadd st2,st0 ; Clock cycle 2-4
fadd st3,st0 ; Clock cycle 3-5
fadd st4,st0 ; Clock cycle 4-6
Obviously, two instructions cannot overlap if the second instruction needs the result of the
first one. Since almost all floating point instructions involve the top of stack register, ST0,
there are seemingly not very many possibilities for making an instruction independent of the
result of previous instructions. The solution to this problem is register renaming. The FXCH
instruction does not in reality swap the contents of two registers; it only swaps their names.
Paradoxically often mentioned Texture Divide every 16 pixels overlaps just fine on all CPUs and doesnt explain performance discrepancies. Intel FDIV latency is 19 cycles compared to Cyrix 24, mere 20% yet you need almost double the MHz on Cyrix to match FPS numbers. Answer lies in rest of Quake heavily pipelined FPU code.