X87
x87 е наименование на набор от инструкции за работа с числа с плаваща запетая в процесорната архитектура x86. Подобно на архитектурата x86 тези инструкции носят името си от поредицата математически копроцесори на Intel, в които са били въведени.

История 
Първоначално (до появата на процесора Intel 486) архитектурата x86 не разполага с инструкции за обработка на числа с плаваща запетая. Още от самото начало обаче Intel предлага математическия копроцесор 8087, който работи съвместно с 8086 и ускорява изчисленията с плаваща запетая.

През 1985 г. IEEE публикува под името IEEE 754 стандарт за двоична аритметика с плаваща запетая. На практика този стандарт се основава на архитектурата на копроцесора 8087 на Intel и дефинира типовете данни, операциите и начините за обработка на изключенията при работа с двоични числа с плаваща запетая. През 1987 г. е публикувана по-обща версия на стандарта, която е независима от основата на бройната система и носи името IEEE 854.

Повечето производители на компилатори създават емулиращи програмни библиотеки, които позволяват на програмиста да използва един и същ програмен интерфейс независимо дали компютърът, на който се изпълняват програмите, има математически копроцесор, или няма такъв. Това улеснява употребата на инструкциите и те започват да се използват широко в софтуерните продукти. По-късно се появяват копроцесорите 80187, 80287, 80387 и 80487. С въвеждането на процесора 486 математическият копроцесор става част от процесорното ядро, а инструкциите от набора x87 стават неразделна част от архитектурата x86.

След появата на инструкциите SIMD (3DNow! и най-вече SSE) инструкциите от набора x87 вече не са най-бързият начин за извършване на изчисления с плаваща запетая в процесорите от семейството x86. Все пак този набор инструкции остават най-универсални и гъвкави, поради което продължават да се използват широко, особено в случаите, когато точността е по-важна от бързината.

Технология 
Иструкциите за работа с числа с плаваща запетая добавят следните разширения към архитектурата x86:
 осем 80-битови регистъра за числа с плаваща запетая;
 три 16-битови контролни регистъра и три регистъра за запазване на състоянието;
 седем типа данни;
 над шестдесет инструкции.

Регистри 
Инструкциите от набора x87 използват осем регистъра за данни с имена от ST0 до ST7. Всеки от тях е 80-битов и съдържа едно 80-битово число с плаваща запетая с разширена точност. Освен тези регистри x87 включва и три 16-битови контролни регистъра (наричани control, status и tag); както и три други регистъра, които се използват за записване на адреса на инструкцията, данните и вида на операцията, които са предизвикали последното програмно изключение (exception).

Осемте регистъра за данни са организирани в стек, като за указател на върха на стека се използлва 3-битово поле от 16-битовия регистър status.

Типове данни 
Инструкциите от набора x87 работят върху седем типа данни, които могат да се разделят на следните групи:

 Числа с плаваща запетая:
 Единична точност. Числото заема 32 бита, като мантисата е 24-битова, а експонентата е 8-битова. Обхватът на тези числа е от 1,18 * 10–38 до 3,40 * 1038 (при стандартен запис, т.е. когато няма водещи нули в мантисата и точността е максимална).
 Двойна точност. Числото заема 64 бита, като мантисата е 53-битова, а експонентата е 11-битова. Обхватът на тези числа е от 2,23 * 10–308 до 1,79 * 10308 (при стандартен запис).
 Разширена точност. Числото заема 80 бита, като мантисата е 64-битова, а експонентата е 16-битова. Обхватът на тези числа е от 3,37 * 10–4932 до 1,18 * 104932 (при стандартен запис).
 Цели числа:
 Word. Заема 16 бита и има обхват от –32768 до 32767.
 Short. Заема 32 бита и има обхват от –231 to 231 – 1.
 Long. Заема 64 бита и има обхват от –263 to 263 – 1.
 Пакетирани двоично-десетични (BCD) цели числа:
 80-битово двоично-десетично (BCD) число. Числото се състои от 18 десетични цифри и има обхват от –1018 + 1 до 1018 – 1.

Трябва да се има предвид, че описаните формати на данните важат само при съхраняването на число в паметта. При прехвърлянето му в някои от регистрите на процесор от типа x87 числото автоматично се преобразува в 80-битово с плваваща запетая с разширена точност и се обработва в този формат.

Методи за адресиране 
Операндите на x87 инструкциите може да се намират или в x87 регистрите, или в паметта (не се използват непосредствени операнди – такива, които са кодирани в самата инструкция).

Повечето x87 инструкции могат да приемат операнд от паметта, а някои от тях могат и да записват резултата в паметта. При достъп до операнд в паметта, могат да се използват стандартните x86 методи за адресиране.

Повечето x87 инструкции могат да приемат операнд от x87 регистър и да записват резултата в него. При достъп до x87 регистрите се използва означението ST(i), където i е число от 0 до 7. ST(0) обозначава регистъра, който е на върха на регистровия стек, ST(1) е регистърът под него и т.н.

Повечето x87 инструкции са с два операнда, като първият е едновременно и място, където се записва резултатът от операцията (подобно на x86 инструкциите).

Инструкции 
Имената на всички x87 инструкции започват с буквата F (например FADD, FMUL и др.). Те могат да се разделят на следните групи:

Трансфер и конвертиране на данни 
 FLD, FST, FSTP – прехвърляне на число с плаваща запетая от и към върха на регистровия стек.
 FILD, FIST, FISTP – прехвърляне на цяло число от и към върха на регистровия стек.
 FBLD, FBSTP – прехвърляне на BCD число от и към върха на регистровия стек.
 FCMOVB, FCMOVBE, FCMOVE, FCMOVNB, FCMOVNBE, FCMOVNE, FCMOVNU, FCMOVU – условно прехвърляне в рамките на регистровия стек в зависимост от флагове в x86 регистъра FLAGS.
 FXCH – размяна на съдържанието на върха на регистровия стек и друг регистър от стека.
 FXTRACT – извлича мантисата и експонентата на числото от върха на регистровия стек.

Зареждане на константи 
 FLDZ – зареждане на числото 0 на върха на регистровия стек.
 FLD1 – зареждане на числото 1 на върха на регистровия стек.
 FLDPI – зареждане на числото π (Пи) на върха на регистровия стек.
 FLDL2E – зареждане на log2 e на върха на регистровия стек.
 FLDL2T – зареждане на log2 10 на върха на регистровия стек.
 FLDLG2 – зареждане на log10 2 на върха на регистровия стек.
 FLDLN2 – зареждане на ln 2 (loge 2) на върха на регистровия стек.

Аритметични 
 FADD, FADDP, FIADD – събиране на две числа с плаваща запетая. FADD записва резултата на върха на регистровия стек. FADDP записва резултата в ST(1) и прави този регистър новия връх на регистровия стек. FIADD е еквивалент на FADD с тази разлика, че единият операнд е цяло число от паметта.
 FSUB, FSUBP, FISUB, FSUBR, FSUBRP, FISUBR – изваждане на числа с плаваща запетая. FSUB записва резултата на върха на регистровия стек. FSUBP записва резултата в ST(1) и прави този регистър новия връх на регистровия стек. FISUB е еквивалент на FSUB с тази разлика, че единият операнд е цяло число от паметта. Инструкциите със суфикс R са еквивалентни на първите три инструкции, но с разменени места на операндите (тъй като изваждането не е комутативна операция).
 FMUL, FMULP, FIMUL – умножение на две числа с плаваща запетая. FMUL записва резултата на върха на регистровия стек. FMULP записва резултата в ST(1) и прави този регистър новия връх на регистровия стек. FIMUL е еквивалент на FMUL с тази разлика, че единия операнд е цяло число от паметта.
 FDIV, FDIVP, FIDIV, FDIVR, FDIVRP, FIDIVR – деление на числа с плаваща запетая. FDIV записва резултата на върха на регистровия стек. FDIVP записва резултата в ST(1) и прави този регистър новия връх на регистровия стек. FIDIV е еквивалент на FDIV с тази разлика, че единият операнд е цяло число от паметта. Инструкциите със суфикс R са еквивалентни на първите три инструкции, но с разменени места на операндите (тъй като делението не е комутативна операция).
 FABS – абсолютна стойност.
 FCHS – смяна на знака.
 FRNDINT – закръгляване на число с плаваща запетая до цяло число.
 FPREM, FPREM1 – частичен остатък при делене на числа с плаваща запетая.
 FSQRT – квадратен корен.

Трансцендентни 
 FSIN, FCOS, FSINCOS, FTAN, FATAN – изчисляване съответно на синус, косинус, синус и косинус, тангенс и арктангенс от число с плаваща запетая.
 F2XM1 – изчислява 2x – 1.
 FSCALE – изчислява 2x.
 FYL2X – изчислява y * log2 x.
 FYL2XP1 – изчислява y * log2 (x + 1).

Сравнение и проверка 
 FCOM, FCOMP, FCOMPP, FCOMI, FCOMIP – сравнение на операнди с плаваща запетая.
 FUCOM, FUCOMP, FUCOMPP, FUCOMI, FUCOMIP – сравнение на операнди с плаваща запетая, при което операдите може да са безкрайности.
 FICOM, FICOMP – сравнение на целочислен операнд с върха на стека.
 FTST – сравнение на операнд с плаваща запетая с 0.
 FXAM – проверка за специални стойности на операнда с плаваща запетая.

Други 
 FDECSTP – намалява указателя на регистровия стек с 1.
 FINCSTP – увеличава указателя на регистровия стек с 1.
 FFREE – обявява даден x87 регистър за празен.
 FNOP – празна инструкция.
 FINIT, FNINIT – инициализиране на x87 блока на процесора.
 FWAIT – проверка за x87 изключения.
 FCLEX, FNCLEX – нулиране на флаговете на status регистъра.
 FLDCW, FSTCW, FNSTCW – зареждане и записване на control регистъра.
 FSTSW, FNSTSW – записване на status регистъра.
 FLDENV, FNSTENV, FSTENV – зареждане от и записване в паметта на състоянието на x87 блока на процесора без x87 регистровия стек.
 FSAVE, FNSAVE, FRSTOR – записване в паметта и зареждане от паметта на цялостното състояние на x87 блока на процесора, включително и x87 регистровия стек.

Проблеми 
По отношение на функционалност, точност и универсалност, x87 инструкциите са напълно достатъчни за почти всички видове приложения. Основният им недостатък се крие в наследената от x86 SISD организация, при която всяка инструкция оперира само върху един набор от операнди. Това значително намалява максимално възможната производителност и ограничава употребата на x87 инструкциите в области като обработка на звук и видео, компютърни игри и други.

Приложения 
В исторически аспект, x87 са основният набор от инструкции за обработка на числа с плаваща запетая. Значението им е най-голямо по време на появата на първите 3D компютърни игри (Doom, Quake) и възпроизвеждането на видео на персоналните компютри.

След появата на SSE, x87 инструкциите се използват в много по-тесен кръг от приложения, при които са по-важни точността и възможността за гъвкава обработка на грешките и специалните случаи (най-вече научно-технически приложения).

Специфичните предимства на x87 инструкциите са:

 Представяне на числата в съответстиве със стандартите IEEE 754 и IEEE 854, което осигурява повтаряемост на резултатите на всички платформи, които поддържат тези стандарти.
 От архитектурна гледна точка, x87 блоковете на повечето съвременни процесори са независими от тези на SSE инструкциите, което позволява по-висока теоретична производителност, ако се използват едновременно x87 и SSE инструкции.
 По-разнообразни инструкции и много гъвкав механизъм за обработка на безкрайности и изключения.

Вижте също 
 SSE – популярно разширение на x86 инструкциите, което позволява SIMD обработка на числа с плаваща запетая.
 3DNow! – друго SIMD разширение на x86 инструкциите.
 MMX – целочислени SIMD разширения на x86 инструкциите.

Външни препратки 
 Ръководство за софтуерния разработчик за архитектурата IA-32, том 1 (PDF) , виж глава 7 за x87 програмиране 

Процесорна архитектура x86