Что такое fpu в компьютере
Математический сопроцессор
Математический сопроцессор — сопроцессор для расширения командного множества центрального процессора и обеспечивающий его функциональностью модуля операций с плавающей запятой, для процессоров, не имеющих интегрированного модуля.
Модуль операций с плавающей запятой (или с плавающей точкой; англ. floating point unit (FPU) ) — часть процессора для выполнения широкого спектра математических операций над вещественными числами.
Простым «целочисленным» процессорам для работы с вещественными числами и математическими операциями требуются соответствующие процедуры поддержки и время для их выполнения. Модуль операций с плавающей запятой поддерживает работу с ними на уровне примитивов — загрузка, выгрузка вещественного числа (в/из специализированных регистров) или математическая операция над ними выполняется одной командой, за счёт этого достигается значительное ускорение таких операций.
Содержание
Сопроцессоры
x87 — это специальный набор инструкций для работы с математическими вычислениями, являющийся подмножеством архитектуры процессоров x86. Такое название он получил, потому что первоначальные отдельные математические сопроцессорные чипы имели названия, заканчивающиеся на 87. Как и другие расширения базового набора инструкций процессора, эти инструкции не являются строго необходимыми для построения рабочей программы, но будучи аппаратно реализованными, общие математические задачи они позволяют выполнять гораздо быстрее. Например, в наборе инструкций x87 присутствуют команды для расчёта значений синуса или косинуса.
Сопроцессоры Intel семейства x86
Для процессоров семейства x86 с 8086/8088 по 386, модуль операций с плавающей запятой был выделен в отдельную микросхему, называемую математическим сопроцессором. Для установки сопроцессора на плате компьютера предусматривался отдельный разъём.
Сопроцессор не является полноценным процессором, так как не умеет делать многих необходимых для этого операций (например, не умеет работать с программой и вычислять адреса памяти), являясь всего лишь придатком центрального процессора.
Одна из схем взаимодействия центрального процессора и сопроцессора, применяемая, в частности, в x86 сопроцессорах, реализуется следующим образом:
Начиная с процессора Intel486DX модуль операций с плавающей запятой был интегрирован в центральный процессор и назван FPU. В линейке Intel486SX модуль FPU отключался (поначалу в эту линейку попадали процессоры с бракованным FPU). Для процессоров Intel486SX также выпускался «сопроцессор» Intel487SX, но, фактически, он являлся процессором Intel486DX и при его установке процессор Intel486SX отключался.
Несмотря на интеграцию, FPU в процессорах i486 представляет собой неизменный сопроцессор, выполненный на том же кристалле, более того, схема FPU i486 полностью идентична сопроцессору предыдущего поколения 387DX вплоть до тактовой частоты (в два раза меньшей, чем частота центрального процессора). Настоящая интеграция FPU c центральным процессором началась только в процессорах Pentium модели MMX.
Сопроцессоры x86 от сторонних производителей
Широкое распространение в соответствующий период получили сопроцессоры для платформы x86, выпускавшиеся компанией Weitek — ею были выпущены 1167, 2167 в виде набора микросхем и микросхемы 3167, 4167, для процессоров 8086, 80286, 80386, 80486, соответственно. По сравнению с сопроцессорами от Intel они обеспечивали в 2-3 раза большую производительность, но обладали несовместимым программным интерфейсом, реализованным через технологию memory-mapping. Она сводилась к тому, что основной процессор должен был записывать информацию в те или иные области памяти, контролируемые Weitek-овским сопроцессором (собственно, оперативной памяти там, конечно не было). Конкретный адрес, куда производилась запись, интерпретировался в качестве той или иной команды. Несмотря на несовместимость, сопроцессоры от Weitek были широко поддержаны как разработчиками ПО, так и производителями материнских плат, предусматривавших на них гнёзда для установки такой микросхемы.
Ряд других компаний также выпускал различные несовместимые математические сопроцессоры, реализуя интерфейс к ним через порты ввода-вывода или прерывания BIOS, но они не получили такого широкого распространения.
Компании-производители клонов выпускали совместимые с 80287 80387 сопроцессоры, работавшие быстрее аналогичных интеловских. Среди этих компаний можно упомянуть Cyrix, AMD, Chips & Technologies (C&T). Иногда система команд этих сопроцессоров расширялась несколькими несовместимыми, например, аналог 80287 от C&T содержал команды для работы с вектором из четырёх значений с плавающей точкой. Серьёзной поддержки от производителей ПО эти расширенные команды не получили.
Процессоры EMC87 от фирмы Cyrix могли работать как в режиме программной совместимости с Intel 80387, так и в собственном несовместимом режиме программирования. Для них обеспечивалась аппаратная совместимость с разъёмом 80387-го сопроцессора.
В СССР выпускалась микросхема (КМ)1810ВМ87, которая являлась аналогом 8087
Другие платформы
Аналогично, материнские платы ПК, построенных на процессорах Motorola, до разработки этой фирмой процессора MC68040 (в который сопроцессор был встроен) содержали математический сопроцессор. Как правило, в качестве FPU использовался сопроцессор 68881 16 МГц или 68882 25 МГц. Практически любой современный процессор имеет встроенный сопроцессор.
Компания Weitek также выпускала математические сопроцессоры для платформ 68000 и MIPS.
Устройство FPU
Все процессоры Intel и AMD, начиная с 486DX, имеют встроенный математический сопроцессор, и в отдельном сопроцессоре не нуждаются (за исключением Intel486SX). Тем не менее, термин x87 всё ещё используется для выделения той части инструкций процессора, которая занимается вычислениями с использованием плавающей запятой; компиляторы могут использовать эти инструкции для производства кода, который работает быстрее, нежели тот, что использует вызовы к библиотекам для выполнения операций с плавающей запятой.
Инструкции x87 совместимы со стандартом IEEE-754. Однако, x87 выполняют операции не в строгом соответствии с форматами IEEE-754, из-за использования более широких регистров. Поэтому последовательность арифметических операций может выполняться несколько по-разному на наборе x87 и на процессоре, строго следующем формату IEEE-754.
x87 организует свои регистры не как массив, как большинство других архитектур, а как регистровый стек, работающий по принципу обратной польской записи. Это означает, что в один момент времени, только два верхних регистра доступны для проведения операций, а доступ к другим регистрам требует манипуляций со стеком. Хотя такая организация получается и удобной для программистов, она делает трудоёмким построение эффективного кода x87 для компиляторов.
Начиная с Pentium III, вычисления с помощью инструкций SSE осуществляются с одинарной точностью, а в более поздних версиях — с двойной точностью форматов IEEE-754. После появления SSE2, использование x87 в значительной степени умаляется в 64-разрядных архитектурах x86-64 и связанных с ней 64-битных реализациях операционных систем, таких как Microsoft Windows, Mac OS X, Solaris, FreeBSD и Linux, хотя он по-прежнему хорошо поддерживается для полной совместимости со старыми приложениями.
Модуль операций с плавающей запятой [2] [3] представляет собой стековый калькулятор, работающий по принципу обратной польской записи. Перед операцией аргументы помещаются в LIFO-стек, при выполнении операции необходимое количество аргументов снимается со стека. Результат операции помещается в стек, где может быть использован в дальнейших вычислениях или может быть снят со стека для записи в память. Также поддерживается и прямая адресация аргументов в стеке относительно вершины.
Форматы данных
Внутри FPU числа хранятся в 80-битном формате с плавающей запятой, для записи же или чтения из памяти могут использоваться:
FPU также поддерживает специальные численные значения:
Регистры
В FPU можно выделить три группы регистров:
Система команд сопроцессора
Система включает около 80 команд. Их классификация:
См. также
Примечания
8 бит · 16 бит · 32 бит · 64 бит · 128 бит
Pipeline | Конвейер · In-Order & Out-of-Order execution · Переименование регистров · Speculative execution |
Уровни | Бит · Инструкций · Суперскалярность · Данных · Задач |
Потоки | Многопоточность · Simultaneous multithreading · Hyperthreading · Superthreading · Аппаратная виртуализация |
Классификация Флинна | SISD · SIMD · MISD · MIMD |
Полезное
Смотреть что такое «Математический сопроцессор» в других словарях:
математический сопроцессор — — [Е.С.Алексеев, А.А.Мячев. Англо русский толковый словарь по системотехнике ЭВМ. Москва 1993] Тематики информационные технологии в целом EN match coprocessor … Справочник технического переводчика
Сопроцессор — Сопроцессор специализированный процессор, расширяющий возможности центрального процессора компьютерной системы, но оформленный как отдельный функциональный модуль. Физически сопроцессор может быть отдельной микросхемой или может быть… … Википедия
Блок операций с плавающей точкой — Математический сопроцессор 80×287 в колодке на базовой плате персонального компьютера. Сопроцессор Motorola 68881 Математический сопроцессор сопроцессор для расширения командного множества центрального процессора и обеспечивающий его… … Википедия
Периферийный процессор — Сопроцессор специализированный процессор, расширяющий возможности центрального процессора компьютерной системы, но оформленный как отдельный функциональный модуль. Физически сопроцессор может быть отдельной микросхемой или может быть встроен в… … Википедия
Intel 80486 — > Центральный процессор Микропроцессор Intel 80486 Производство: с 10 апреля … Википедия
80486 — > Центральный процессор … Википедия
80386 — В этой статье не хватает ссылок на источники информации. Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена. Вы можете отредактировать эту статью … Википедия
Am486 — AMD Am486DX 40 Am486 семейство микропроцессоров архитектуры x86 компании AMD, предст … Википедия
Микропроцессорный комплект серии К1810 — Микропроцессорный комплект cерии К1810 набор микросхем, аналогичных набору микросхем для процессора Intel 8086, дальнейшее развитие микропроцессорного комплекта К580. Использовался в отечественных IBM PC совместимых компьютерах, таких как… … Википедия
Процессор — У этого термина существуют и другие значения, см. Процессор (значения). Запрос «ЦП» перенаправляется сюда; см. также другие значения. Intel Celeron 1100 Socket 370 в корпусе FC PGA2, вид снизу … Википедия
Программирование сопроцессора на C#? Да!
fld [arg1]
fld [arg2]
fsubp
fld [arg3]
faddp
fstp [result]
ret
Теперь поясню. В квадратных скобках мы должны указывать адреса переменных arg1, arg2, arg3, result.
Инструкция fld загружает в вершину стека (FPU работает со стеком, причем он имеет некоторые особенности) значение переменной double, адрес которой идет сразу после инструкции; fsubp – производит вычитание значения, лежащего на 1 позиции в стеке ниже, значение, лежащее на вершине стека и освобождает вершину стека, тем самым результат записывается на место значения, из которого вычитается, результат находится теперь на вершине стека; faddp – работает по аналогии с fsubp, только не вычитает, а складывает значения; fstp – выгружает из вершины стека значение double, выгружает в ячейку по адресу, указанному далее; ну и инструкция ret – интуитивно понятная – завершает выполнение функции и передает управление в функцию, вызвавшую ее. Чтобы было более понятно, покажу работу нашего кода в картинках:
Результат записывается в ячейку памяти, откуда его можно забрать. Работа инструкций надеюсь ясна. Теперь посмотрим как нам такой код создать из программы на С++.
double ExecuteMagic( double arg1, double arg2, double arg3)
<
short * code;
short * code_cursor;
short * code_end;
double * data;
double * data_cursor;
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD region_size = si.dwAllocationGranularity;
code = ( short *)VirtualAlloc(NULL, region_size * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
code_cursor = code;
code_end = ( short *)(( char *)code + region_size);
data = ( double *)code_end;
data_cursor = data;
*data_cursor = arg1;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)(data_cursor); //1.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
data_cursor++;
*data_cursor = arg2;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //-2.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0xE9DEu; //fsubp
*data_cursor = arg3;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //2.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0xC1DEu; //faddp
double *result = data_cursor;
*code_cursor++ = ( short )0x1DDDu; //fstp
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0x90C3u; //ret
void (*function)() = ( void (*)())code;
Теперь давайте разберем все самое вкусное здесь. Итак, мы с помощью функции VirtualAlloc выделяем нашему коду некоторое количество памяти (а именно согласно значению структуры
SYSTEM_INFO. dwAllocationGranularity, как бы системная величина разбиения памяти); обратите внимание какие аргументы принимает функция на вход, а именно на PAGE_EXECUTE_READWRITE – именно этот параметр позволяет обратиться к вновь созданному участку памяти не только для чтения/записи, но и для выполнения кода, т.е. мы можем передать в этот участок памяти управление и процессор будет считывать дальнейшие инструкции именно отсюда.
Половина этого созданного массива выделяем для кода, вторую половину для данных – некое подобие сегмента кода и сегмента данных. Все что осталось – заполнить эти сегменты данных необходимыми значениями. Для заполнения массива кодом необходимо просто записать в этот массив опкоды (инструкции процессора) в шестнадцатеричном виде. Разберем все по порядку.
Инструкция FLD имеет опкод DD/0. Да, кстати, сразу скажу, что значения опкодов и их мнемоническое написание вы можете посмотреть в документации по архитектуре процессоров. Продолжим, FSTP имеет тоже опкод DD, но уже с приставкой /3 – это расширение опкода – mod r/m байт. Вот таблица значений mod r/m байта [http://www.sandpile.org/ia32/opc_rm32.htm] (Пытливые умы при присутствии интереса смогут разобраться во всем этом, поверьте). Так как инструкция FLD и FSTP могут оперировать с операндами разного типа, т.е. ячейками, регистрами процессора, то для этого и существует расширение опкода. Нам для работы нужен вид операнда адрес числа double, поэтому в той таблице мы смотрим значение для [sdword]. Для FLD это значение равно 05h, для FSTP 1Dh. Прибавляем эти значения к опкодам и получаем: FLD = DD05h, FSTP = DD1Dh. Инструкция FSUBP имеет опкод DE/5, и мы опять должны обратиться к таблице расширения опкода и посмотреть значение расширения для XMM1 (это ссылка элемент стека FPU) и видим, что оно равно E9h, т.е. FSUBP = DEE9h. FADDP также как и FSUBP имеет опкод DE, но уже /0, что для XMM1 имеет значение C1h, т.е. FADDP = DEC1h. Инструкция RET имеет опкод C390h.
Следует отметить, что инструкции процессор считывает с конца, поэтому их надо записывать наоборот, с учетом того, что они по 2 байта и парные, т.е. FLD = DD05h надо записывать не 50DDh, а 05DDh, это важно!
Ну вот в принципе и все по опкодам. Код на языке С++ выше показывает как заполнять массив инструкциями. Сначала записываем инструкцию, затем, если это необходимо, адрес ячеек. Обратите внимание, что адрес имеет длину 4 байта (32 бита) для 32-битных систем, поэтому после записи адреса в массив кода, необходимо сместить указатель на 4 байта вперед, вместо 2 байт в случае инструкций.
Кульминацией сего чуда является выполнение записанного в память кода. Как выполнить код из нашего массива? За помощью мы обращаемся к указателю на функцию, здесь язык С++ выручает. Создаем указатель на функцию типа void с параметрами void, далее присваиваем ему указатель на начало массива кода. Все! Запускаем наш указатель на функцию, получаем результат работы программы прям в памяти, процессор все сделал ровно так, как мы ему сказали в нашем массиве кода.
Теперь я напомню, что это 1 способ передачи параметров и возвращения результата. Второй способ заключается в том, чтобы создать указатель на функцию типа double(void), т.е. чтобы нам не в память записывался результат и мы его сами вытаскивали, а чтобы нам уже результат возвратила наша функция, созданная динамически. Для этого просто изменяем код на такой:
fld [arg1]
fld [arg2]
fsubp
fld [arg3]
faddp
//fstp [result]
ret
Т.е. просто оставляем в вершине стека результат. И наш указатель на функцию вернет нам результат из вершины стека. Все просто.
Читатель уже с середины статьи задается вопросом: «Причем тут C#. Один С++ и Ассемблер, непонятные цифры…». Справедливо, но надо быть терпеливее :).
using namespace System;
namespace smallcodelib
<
public ref class CodeMagics
<
public :
static double ExecuteMagic( double arg1, double arg2, double arg3)
<
short * code;
short * code_cursor;
short * code_end;
double * data;
double * data_cursor;
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD region_size = si.dwAllocationGranularity;
code = ( short *)VirtualAlloc(NULL, region_size * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
code_cursor = code;
code_end = ( short *)(( char *)code + region_size);
data = ( double *)code_end;
data_cursor = data;
*data_cursor = arg1;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)(data_cursor); //1.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
data_cursor++;
*data_cursor = arg2;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //-2.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0xE9DEu; //fsubp
*data_cursor = arg3;
*code_cursor++ = ( short )0x05DDu; //fld
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //2.0
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0xC1DEu; //faddp
double *result = data_cursor;
*code_cursor++ = ( short )0x1DDDu; //fstp
*( int *)code_cursor = ( int )(INT_PTR)data_cursor++; //
code_cursor = ( short *)(( char *)code_cursor + sizeof ( int )); // смещение
*code_cursor++ = ( short )0x90C3u; //ret
void (*function)() = ( void (*)())code;
Это код для класса на С++.
using System;
using System.Collections. Generic ;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using smallcodelib;
double result = CodeMagics.ExecuteMagic(arg1, arg2, arg3);
Проверьте! Все работает!
Ясное дело, что тут больше кода на С++, однако если у интересующихся есть определенный талант и интерес помучаться в данной области, то можно написать некоторую обертку на С++, которая будет генерировать такой код динамически, а использовать эту обертку уже из C#, наполняя ее необходимыми переменными и параметрами, ну и т.д. Можно получить довольно интересную штуку.
Добавлю еще пару приятностей.
Статья написана применительно программирования сопроцессора. На самом деле можно писать все, что душе угодно, для этого надо изучить архитектуру памяти и процессора ЭВМ, инструкции. Технологически продвинутые программисты, знающие что такое SSE (а она уже чуть ли не 5), могут писать код, используя все новшества процессорных технологий и самое приятное – это использовать это в C#. Все ограничивается фантазией =). Удачи в начинаниях!
Что делает опция “Stress FPU” в Aida64?
Тот, кто хоть раз запускал тест стабильности системы в программе Aida64 (бывший Everest), или хотя бы открывал его окно, то должен был обратить внимание на наличие галочки, которая называется “Stress FPU”. Судя по тому, что она находится среди других опций, активирующих нагрузку на отдельные компоненты ПК, не совсем понятно, за какой конкретный компонент она отвечает. Разобраться в этом нам и предстоит в данной статье.
Что такое FPU?
Как известно, процессор в единицу времени обрабатывает достаточно большой объем данных, среди которых есть операции с плавающей точкой. Говоря более простыми словами, это операции с дробными числами, причем дробная часть, может быть достаточно длинной, например 0,000014345679.
Именно количество операций с плавающей точкой в секунду (floating-point operations per second) является одим из основных показателей производитеьности системы. Измеряется оно в FLOPS.
Показатель производительности видеокарты в операциях с плавающей точкой
Что же такое Stress FPU?
Эта опция в тесте стабильности программы Aida64, которая задействует для увеличения нагрузки на процессор (графичечкий процессор) расчет операций с плавающей точкой.
Тест стабильности системы в Aida64
При ее активации ваша система будет нагружена расчетами дробных чисел, что ускорит нагревание процессора и поможет выявить возможные ошибки в работе компьютера, в том числе из-за перегрева.
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
FPU (Floating Point Unit)
Математический сопроцессор — сопроцессор для расширения командного множества центрального процессора и обеспечивающий его функциональностью модуля операций с плавающей запятой, для процессоров, не имеющих интегрированного модуля.
Модуль операций с плавающей запятой (или с плавающей точкой; англ. floating point unit (FPU) ) — часть процессора для выполнения широкого спектра математических операций над вещественными числами.
Простым «целочисленным» процессорам для работы с вещественными числами и математическими операциями требуются соответствующие процедуры поддержки и время для их выполнения. Модуль операций с плавающей запятой поддерживает работу с ними на уровне примитивов — загрузка, выгрузка вещественного числа (в/из специализированных регистров) или математическая операция над ними выполняется одной командой, за счёт этого достигается значительное ускорение таких операций.
Содержание
Сопроцессоры
x87 — это специальный набор инструкций для работы с математическими вычислениями, являющийся подмножеством архитектуры процессоров x86. Такое название он получил, потому что первоначальные отдельные математические сопроцессорные чипы имели названия, заканчивающиеся на 87. Как и другие расширения базового набора инструкций процессора, эти инструкции не являются строго необходимыми для построения рабочей программы, но будучи аппаратно реализованными, общие математические задачи они позволяют выполнять гораздо быстрее. Например, в наборе инструкций x87 присутствуют команды для расчёта значений синуса или косинуса.
Сопроцессоры Intel семейства x86
Для процессоров семейства x86 с 8086/8088 по 386 модуль операций с плавающей запятой был выделен в отдельную микросхему, называемую математическим сопроцессором. Для установки сопроцессора на плате компьютера предусматривался отдельный разъём.
Сопроцессор не является полноценным процессором, так как не умеет делать многих необходимых для этого операций (например, не умеет работать с программой и вычислять адреса памяти), являясь всего лишь придатком центрального процессора.
Одна из схем взаимодействия центрального процессора и сопроцессора, применяемая, в частности, в x86-сопроцессорах, реализуется следующим образом:
Начиная с процессора Intel486DX модуль операций с плавающей запятой был интегрирован в центральный процессор и назван FPU. В линейке Intel486SX модуль FPU отключался (поначалу в эту линейку попадали процессоры с бракованным FPU). Для процессоров Intel486SX также выпускался «сопроцессор» Intel487SX, но фактически он являлся процессором Intel486DX, и при его установке процессор Intel486SX отключался.
Несмотря на интеграцию, FPU в процессорах i486 представляет собой неизменный сопроцессор, выполненный на том же кристалле, более того, схема FPU i486 полностью идентична сопроцессору предыдущего поколения 387DX вплоть до тактовой частоты (в два раза меньшей, чем частота центрального процессора). Настоящая интеграция FPU c центральным процессором началась только в процессорах Pentium модели MMX.
Сопроцессоры x86 от сторонних производителей
Широкое распространение в соответствующий период получили сопроцессоры для платформы x86, выпускавшиеся компанией Weitek — ею были выпущены 1167, 2167 в виде набора микросхем и микросхемы 3167, 4167, для процессоров 8086, 80286, 80386, 80486, соответственно. По сравнению с сопроцессорами от Intel они обеспечивали в 2—3 раза большую производительность, но обладали несовместимым программным интерфейсом, реализованным через технологию memory-mapping. Она сводилась к тому, что основной процессор должен был записывать информацию в те или иные области памяти, контролируемые Weitek-овским сопроцессором (собственно оперативной памяти там, конечно, не было). Конкретный адрес, куда производилась запись, интерпретировался в качестве той или иной команды. Несмотря на несовместимость, сопроцессоры от Weitek были широко поддержаны как разработчиками ПО, так и производителями материнских плат, предусматривавших на них гнёзда для установки такой микросхемы.
Ряд других компаний также выпускал различные несовместимые математические сопроцессоры, реализуя интерфейс к ним через порты ввода-вывода или прерывания BIOS, но они не получили такого широкого распространения.
Компании-производители клонов выпускали совместимые с 80287 80387 сопроцессоры, работавшие быстрее аналогичных интеловских. Среди этих компаний можно упомянуть Cyrix, AMD, Chips & Technologies (C&T). Иногда система команд этих сопроцессоров расширялась несколькими несовместимыми, например, аналог 80287 от C&T содержал команды для работы с вектором из четырёх значений с плавающей точкой. Серьёзной поддержки от производителей ПО эти расширенные команды не получили.
Процессоры EMC87 от фирмы Cyrix могли работать как в режиме программной совместимости с Intel 80387, так и в собственном несовместимом режиме программирования. Для них обеспечивалась аппаратная совместимость с разъёмом 80387-го сопроцессора.
В СССР выпускалась микросхема (КМ)1810ВМ87, которая являлась аналогом 8087.
Другие платформы
Аналогично, материнские платы ПК, построенных на процессорах Motorola, до разработки этой фирмой процессора MC68040 (в который сопроцессор был встроен) содержали математический сопроцессор. Как правило, в качестве FPU использовался сопроцессор 68881 16 МГц или 68882 25 МГц. Практически любой современный процессор имеет встроенный сопроцессор.
Компания Weitek также выпускала математические сопроцессоры для платформ 68000 и MIPS.
Библиотека с плавающей точкой
Когда центральный процессор выполняет программу, которая требует операции с плавающей точкой, которые непосредственно не поддерживаются аппаратными средствами, процессор использует ряд более простых операций с плавающей точкой. В системах без каких-либо аппаратных средств с плавающей точкой, процессор эмулирует его, используя ряд простых арифметических операций с фиксированной точкой, которые работают на целочисленных АЛУ.
Программное обеспечение, которое перечисляет необходимую последовательность операций для эмуляции операций с плавающей запятой часто находится в библиотеке с плавающей запятой.
Устройство FPU
Все процессоры Intel и AMD, начиная с 486DX, имеют встроенный математический сопроцессор, и в отдельном сопроцессоре не нуждаются (за исключением Intel486SX). Тем не менее, термин x87 всё ещё используется для выделения той части инструкций процессора, которая занимается вычислениями с использованием плавающей запятой; компиляторы могут использовать эти инструкции для производства кода, который работает быстрее, нежели тот, что использует вызовы к библиотекам для выполнения операций с плавающей запятой.
Инструкции x87 совместимы со стандартом IEEE-754. Однако x87 выполняют операции не в строгом соответствии с форматами IEEE-754, из-за использования более широких регистров. Поэтому последовательность арифметических операций может выполняться несколько по-разному на наборе x87 и на процессоре, строго следующем формату IEEE-754.
x87 организует свои регистры не как массив, как большинство других архитектур, а как регистровый стек, работающий по принципу обратной польской записи. Это означает, что в один момент времени только два верхних регистра доступны для проведения операций, а доступ к другим регистрам требует манипуляций со стеком. Хотя такая организация получается и удобной для программистов, она делает трудоёмким построение эффективного кода x87 для компиляторов.
Начиная с Pentium III, вычисления с помощью инструкций SSE осуществляются с одинарной точностью, а в более поздних версиях — с двойной точностью форматов IEEE-754. После появления SSE2 использование x87 в значительной степени умаляется в 64-разрядных архитектурах x86-64 и связанных с ней 64-битных реализациях операционных систем, таких, как Microsoft Windows, Mac OS X, Solaris, FreeBSD и Linux, хотя он по-прежнему хорошо поддерживается для полной совместимости со старыми приложениями.
Модуль операций с плавающей запятой представляет собой стековый калькулятор, работающий по принципу обратной польской записи. Перед операцией аргументы помещаются в LIFO-стек, при выполнении операции необходимое количество аргументов снимается со стека. Результат операции помещается в стек, где может быть использован в дальнейших вычислениях или может быть снят со стека для записи в память. Также поддерживается и прямая адресация аргументов в стеке относительно вершины.
Форматы данных
Внутри FPU числа хранятся в 80-битном формате с плавающей запятой, для записи же или чтения из памяти могут использоваться:
FPU также поддерживает специальные численные значения:
Регистры
В FPU можно выделить три группы регистров:
Система команд сопроцессора
Система включает около 80 команд. Их классификация: