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) Архив на оригинала от 2009-01-24 в Wayback Machine., виж глава 7 за x87 програмиране ((en))