Az x87 az x86-os architektúrájú processzorokhoz kapcsolódó – külső vagy belső – matematikai társprocesszorok ill. feldolgozóegységek utasításkészletének és az ahhoz kapcsolódó architekturális elemek leírásának jelölésére szolgáló rövidítés. Az „x87” rövidítés az Intel 8087-es koprocesszor jelöléséből ered – az Intel ennek utódjait is rendre 87-re végződő számokkal jelölte. A matematikai társprocesszorok célja elsősorban a lebegőpontos számítások hardveres gyorsítása (a lebegőpontos egység fixpontos és egész adatokkal is dolgozhat), ezáltal az x87-es utasításkészlet a társprocesszor által támogatott adatformátumokon végezhető műveleteket tartalmazza.

A 8087-es és társai kezdetben különálló egységek voltak, amelyek nem voltak képesek önálló működésre és programok futtatására, csak egy megfelelő x86-os architektúrájú processzorhoz kapcsolva működhettek, az x87 tehát eleinte egy utasításkészlet-kiterjesztést jelentett. Később, az i486-os processzorok és az x86-os utasításkészlet 32 bites kiterjesztésének megjelenésével a lebegőpontos egységet beépítették a processzorba, így ettől fogva az x87 az x86-os utasításkészlet egy jól elkülöníthető részét, ill. részhalmazát jelenti.

A 8087-es matematikai processzor kifejlesztésének célja egy olyan, a már meglévő Intel 8231 és Intel 8232 lebegőpontos egységeknél (és a konkurens AMD megegyező termékeinél) nagyobb tudású processzor létrehozása volt, amely szorosabban kapcsolódik az x86-os architektúrához és az Intel által 1977-ben kezdeményezett IEEE 754 szabványhoz. Az 1980-ban elkészült 8087-es processzor volt az IEEE 754 szabvány első, bár nem teljes, fizikai megvalósítása. Az új architektúra megőrizte az elődök (8231, 8232) egyes elemeit, pl. a regiszterek veremstruktúrába való szervezését és egyes adatformátumokat, azonban számos új utasítást kapott és 80 bitre kiterjesztett (ezáltal megnövelt pontosságú) belső adatformátumot tartalmaz.

Leírás Az x87 regiszterei egy nem szigorúan vett veremstruktúrát alkotnak, amelyben a regisztereket ST(0)-tól ST(7)-ig számozzák. A regiszterek elsősorban a push (behelyezés a verembe) és pop (kivétel a veremből) műveletekkel kapnak értéket, de operandusként közvetlenül is elérhetők, a verem tetejétől számított indexeléssel (ez valamennyire hasonlít pl. a veremkeret kitöltésére a folytonosan címezhető memóriában).

A verem tartalma a push, pop műveletekkel változtatható, de azt a számítások is megváltoztatják. A monadikus utasítások, mint pl. a FSQRT, FPTAN és továbbiak, beleértett módon az ST(0) regiszter tartalmán végzik el a műveletet, míg a diadikus műveletek – FADD, FMUL, FCOM és mások – az ST(0) és ST(1) regiszterekkel végzik el a műveletet. A nem szigorú veremmodell megengedi, hogy a diadikus műveletek az alapértelmezett két regiszteren kívül a második operandus (ami alapértelmezésben az ST(1)) szerepében memóriaoperandust vagy explicit módon meghatározott veremregisztert (ST(x)) használjanak, ilyenkor az ST(0) a megszokott akkumulátor-regiszterhez hasonlóan működik, tehát ez szolgáltatja a művelet első operandusát és az eredmény is ebbe kerül. Ez a címzési szerepkör utasításonként meg is fordítható, amikor az eredmény az ST(x) regiszterbe kerül és az ST(0) értéke változatlan marad. Ezen felül az FXCH ST(x) utasítással az ST(0) tartalma felcserélhető egy másik ST(x) veremregiszter tartalmával.

Az x87 verem ezáltal hét szabadon hozzáférhető regiszter és egy kijelölt akkumulátor (vagy megfordítva: hét kijelölt akkumulátor) használatát teszi lehetővé. Ez nagyon jól kihasználható a szuperskalár x86 processzorokban (mint pl. az 1993-as és későbbi Pentium processzorok), amelyekben ezeket az (D9C8..D9CFh kódú) FXCH ST(x) cserélőutasításokat egészen nulla órajel alatt végrehajthatóvá optimalizálták, az FPU utasításokkal párhuzamosan végrehajtható egészértékű adatutak felhasználásával. Annak ellenére, hogy ez a rendszer az emberi gépi kódú programozók számára természetes és kényelmesen használható, a fordítóprogram-íróknak nehézséget okozott az x87 utasításokat hatékonyan ütemező automatikus kódgenerátorok készítése. Egy ilyen veremalapú interfész képes lehet minimalizálni az átmeneti értékek tárolására fordított tár- v. regiszterhasználatot a függvényhívásokban, szemben a regiszteralapú interfészekkel, annak ellenére, hogy az eredeti tervezési meggondolások erősen korlátozták ezt a lehetőséget az elkészült eszközben.

Az x87 architektúra az egyszeres pontosságú bináris lebegőpontos, a dupla pontosságú bináris lebegőpontos és a 80 bites kiterjesztett pontosságú (v. kiterjesztett duplapontos) bináris lebegőpontos adatábrázolási formátumokat és az azokon végzett műveleteket támogatja, az IEEE 754-1985 szabvány szerint. Alapértelmezésben az x87-es processzorok a 80 bit széles kiterjesztett-duplapontos adatformátumot használják belső adatformátumként, ami lehetővé teszi a pontosság fenntartását a sorozatos számításokban – ez egyike volt az IEEE 754 tervezési irányelveinek. A műveletek egy meghatározott sorozata ezért kissé eltérő eredményekre vezethet a szigorúan egyszeres vagy duplapontos adatformátumokkal dolgozó IEEE 754-szabványú matematikai processzorokban.David Monniaux, The pitfalls of verifying floating-point computations, to appear in ACM TOPLAS Ez néha problémákat is okozhat bizonyos nem teljesen numerikus számításoknál, amelyekben feltételezik a dupla pontosságot a helyes működés érdekében: hogy ezeket a problémákat elkerüljék, az x87-es processzorok egy speciális konfigurációs regiszter segítségével beállíthatók úgy, hogy minden elvégzett művelet után automatikusan egyszeres vagy dupla pontosságúra kerekítsék az eredményt. Az SSE2 bevezetése után az x87-es utasítások jelentősége csökkent, de továbbra is fontos maradt, mint a kerekítési hibákra érzékeny és a 80 bites adatformátum 64 bites mantisszáját (szignifikandusát) kihasználó számításokat hatékonyan végző skaláris számítóegység. Teljesítmény Az alábbi táblázatban tipikus x87-es FPU-utasítások órajelei láthatók, csak a regiszter-regiszter címzésű utasítás-változatokhoz.A számok az adott processzor adatlapjairól, programozási kézikönyvéből vagy optimalizálási kézikönyvéből származnak.

Az A~B jelölés minimum-maximum értéket jelöl és átfogja a különböző átmeneti futószalag-állapotokat és a használható adatábrázolási pontosságot (32, 64 vagy 80 bit), és változhat a választott numerikus eset függvényében is (pl. beállított bitek száma, nulla stb.). Az L→H jelölés a legkisebb (L) és legnagyobb (H) alkalmazott órajelet jelenti.

x87 implementáció FADD FMUL FDIV FXCH FCOM FSQRT FPTAN FPATAN Max órajel FMUL/slebegőpontos szorzás / másodperc csúcsérték 5 MHz-es 8087§ FMULműv.hez viszonyított érték 8087 70~100 90~145 193~203 10~15 40~50 180~186 30~540 250~800 5→10 MHz 34~55K → 100~111K 1.0 → 2.0-szer gyorsabb 80287 (eredeti) 70~100 90~145 193~203 10~15 40~50 180~186 30~540 250~800 6→12 MHz 41~66K → 83~133K 1.2 → 2.4-szer gyorsabb 80387 (és későbbi287 modellek) 23~34 29~57 88~91 18 24 122~129 191~497 314~487 16→33 MHz 280~552K → 579~1100Kkb. 10 → 20 × gyorsabb 80486 (vagy 80487) 8~20 16 73 4 4 83~87 200~273 218~303 16→50 MHz 1.0M → 3.1M kb. 18 → 56 × gyorsabb Cyrix 6x86, Cyrix MII 4~7 4~6 24~34 2 4 59~60 117~129 97~161 66→300 MHz 11~16M → 50~75Mkb. 320 → 1400 × AMD K6 (K6 II/III is) 2 2 n.a. 2 n.a. n.a. n.a. n.a. 166→550 MHz 83M → 275Mkb. 1500 → 5000 × Intel P5 / Pentium/ Pentium MMX 1~3 1~3 39 1 (0*) 1~4 70 17~173 19~134 60→300 MHz 20~60M → 100~300Mkb. 1100 → 5400 × Pentium Pro 1~3 2~5 16~56 1 (0*) 1 28~68 n.a. n.a. 150→200 MHz 30~75M → 40~100Mkb. 1400 → 1800 × Pentium II / III 1~3 2~5 17~38 1 (0*) 1 27~50 n.a. n.a. 233→1400 MHz 47~116M → 280~700Mkb. 2100 → 13000 × Athlon (K7) 1~4 1~4 13~24 1 (0*) 1~2 16~35 n.a. n.a. 500→2330 MHz 125~500M → 0.580~2.33Gkb. 9000 → 42000 × Pentium 4 1~5 2~7 20~43 több ciklus n.a. 20~43 n.a. n.a. 1.3→3.8 GHz 186~650M → 0.543~1.90Gkb. 11000 → 34000 × Athlon 64 (K8) 1~4 1~4 13~24 1 (0*) 1~2 16~35 n.a. n.a. 1.0→3.2 GHz 250~1000M → 0.800~3.2Gkb. 18000 → 58000 × * Effektív nulla órajelű végrehajtási idő lehetséges, a szuperskalár végrehajtás következményeként.

§ Az eredeti x87-es processzor az 5 MHz órajelű 8087 volt. (Hasonló órajelű, 8087 nélküli) 8086-os processzoron szoftveresen megvalósított lebegőpontos rutinokkal összehasonlítva a szorzók sokkal nagyobbak lehetnek, kb. tízszeresek (pl. egy szabályos lebegőpontos összeadás assembly nyelven meghaladhatja az 1000 órajelciklust).

(n.a.: nincs adat)

Gyártók Az Intel 8087 vagy későbbi modellekkel kompatibilis lebegőpontos egységeket terveztek és/vagy gyártottak még a következő cégek (a felsorolás nem teljes):

AMD (287, 387, 486DX, 5x86, K5, K6, K7, K8), Chips and Technologies (Super MATH koprocesszorok), Cyrix (FasMath, Cx87SLC, Cx87DLC stb., 6x86, Cyrix MII), Fujitsu (a korai Pentium Mobile stb.), Harris Semiconductor (80387 és 486DX processzorokat is gyártott), IBM (különféle 387 és 486 kialakítások), IDT (a WinChip, C3, C7, Nano stb.), IIT (a 2C87, 3C87 modellek), LC Technology (a Green MATH koprocesszorok), National Semiconductor (a Geode GX1, Geode GXm stb.), NexGen (az Nx587), Rise Technology (az mP6), ST Microelectronics (486DX, 5x86 stb. gyártó), Texas Instruments (486DX processzorok stb. gyártó), Transmeta (a TM5600 és TM5800), ULSI (a Math·Co koprocesszorok), VIA (a C3, C7 és Nano stb.), és az Xtend (a 83S87SX-25 és más koprocesszorok gyártója).

Architekturális nemzedékek 8087

A 8087-es volt az első „matematikai koprocesszor” ill. társprocesszor, amelyet az Intel 16 bites processzorai mellett való működésre terveztek (egyik elődje, az Intel 8231 8 bites processzorokkal működött együtt); tehát a 8087-es az Intel 8088 vagy 8086 processzorokkal működött együtt.

80187 A 80187 (80C187) az Intel 80186 CPU-hoz kapcsolható matematikai társprocesszor. A 80188-as processzorral nem képes együttműködni, mivel annak adatbusza 8 bites; a 80188-as csak a 8087-es koprocesszort használhatja. A 80187 nem a 80186-os és 80188-as processzorokkal egyidőben jelent meg, hanem a 80287-es és 80387-es megjelenése után készült. Bár a főprocesszor felé kialakított interfész-felülete megegyezett a 8087-esével, magja egy 80387-es volt és ezáltal teljesen megfelel az IEEE 754 szabványnak, és végrehajtja a 80387-es extra utasításait is.

80287

A 80287 (i287) az Intel 80286 sorozat processzoraihoz illeszkedő matematikai társprocesszor. Az Intel-gyártmányú modellek órajelének felső határa 6-tól 12 MHz-ig terjedt. Később elkészült az i80287XL, amely 387-es mikroarchitektúrával rendelkezett, és az i80287XLT, amely egy különleges, laptopokba szánt modell; és még néhány egyéb változat.

A 80287XL jelű modell valójában egy 80387SX, a 287-es lábkiosztásának megfelelő kiszerelésben. Ez egy belső 3/2 arányú szorzót tartalmaz, hogy azokban az alaplapokban, amelyek a koprocesszort a főprocesszor órajelének 2/3-ára csökkentett sebességen hajtják, a koprocesszor a CPU-val azonos sebességen működjön. További 387-eshhez hasonló teljesítményű 287-es modellek pl. a CHMOS III technológiával gyártott Intel 80C287, és az AMD 80EC287, amely az AMD CMOS folyamatával készült és teljesen statikus kapukat tartalmaz.

A 80287 és 80287XL a 80386-os processzorral működik együtt; ez volt a 80386-oshoz illeszthető teljes koprocesszor-választék egészen a 80387-es megjelenéséig 1987-ben. Szintén ezek kapcsolódhattak a Cyrix Cx486SLC processzorhoz. A 80387-es nagyobb teljesítménye és utasításkészlete miatt népszerűbb lett ezeknél.

80387

A 80387 (másként 387 vagy i387) volt az első Intel koprocesszor, amely teljesen megfelelt az IEEE 754 szabványnak. 1987-ben bocsátották ki, két évvel a 386-os processzor megjelenése után. Az i387-es csip sebessége jóval felülmúlta a 8087/80287 koprocesszorok sebességét, és javított trigonometriai funkciókkal bővült (a 287-esnél az értelmezési tartomány korlátozott, −45-től +45 fokig terjed).