Intel 8087: как микрокод сопроцессора складывает и вычитает дробные числа

Intel 8087: как микрокод сопроцессора складывает и вычитает дробные числа

В 1980 году Intel выпустила сопроцессор 8087, который заметно ускорил операции с плавающей запятой в IBM PC и других системах. Статья на righto.com посвящена только базовой арифметике, сложению и вычитанию, хотя чип умеет и тангенсы, квадратные корни и логарифмы. По словам автора, 8087 ускорял сложение по сравнению с процессором 8086 почти в 100 раз, а сложные операции ещё сильнее. Автор разбирает микрокод и схемотехнику, чтобы показать, как именно реализованы сложение и вычитание, включая многочисленные особые случаи для бесконечностей и других специальных значений.

Чтобы заглянуть внутрь, автор снял с чипа крышку зубилом и сделал под микроскопом снимок кристалла в высоком разрешении. Постоянная память микрокода (ROM) занимает крупный прямоугольник в центре кристалла и хранит 1648 микроинструкций. Нижняя половина чипа, тракт данных (datapath), схемы, которые считают на 80-битных значениях. Для сложения и вычитания важны: целочисленный сумматор в центре (один аргумент он берёт из регистра B, другой из временных или стековых регистров, результат кладёт в регистр суммы), сдвигатель (shifter), который занимает много места, потому что умеет быстро сдвигать значение на любое число бит, схема подсчёта ведущих нулей и конвертер экспонент, который определяет переполнения и исчезновения порядка.

Представление чисел: число с плавающей запятой, это знак × мантисса × 2 в степени экспоненты, где мантисса имеет вид 1.bbb… Например, двоичное 1.1 равно 1,5, а 1.0011 равно 1,1875; 1.1 × 2^8 даёт 384. Сложение требует выровнять двоичные точки (сдвинуть аргумент с меньшей экспонентой вправо), сложить мантиссы как целые числа и нормализовать результат. В примере 13,5+3,5 второй аргумент сдвигается на два разряда вправо, при сложении появляется лишний бит слева, поэтому результат сдвигается на один разряд вправо, а экспонента увеличивается на 1. Вычитание сложнее: результат может быть положительным, отрицательным или нулевым и на порядки меньше аргументов. В примере 8-7,5 нормализация требует сдвига влево на четыре бита, экспонента уменьшается на 4. Если результат отрицателен, мантиссу делают положительной и меняют знак. Если получился ноль, нормализовать нельзя, и возвращается +0 или -0.

Аппаратные детали 8087: внутри числа хранятся в 80-битном формате «temporary real» (знак, 15-битная экспонента, 64-битная мантисса). Экспонента хранится со смещением 16383: экспонента 1 записывается как 0x4000, а -16 как 0x3fef. Восемь внутренних регистров организованы как стек, у каждого значения есть тег: ноль, допустимое число, особое (бесконечность, NaN или денормализованное) или пустой, что позволяет выявлять опустошение и переполнение стека. Временные регистры tmpA и tmpB 80-битные, а tmpC без знака и экспоненты, зато с 68-битной мантиссой: один дополнительный бит против переполнения и три младших бита для округления (guard, round, sticky). Сумматор 69-битный, и одно целочисленное сложение занимает две микроинструкции: первая задаёт аргумент и опции, вторая забирает результат из регистра суммы. Для вычитания включается опция, инвертирующая второй аргумент. Сдвиг тоже занимает две микроинструкции. Каждая микроинструкция 16-битная и выполняет одну низкоуровневую операцию.

Микрокод: почти все операции 8087 реализованы микрокодом. Сложение, вычитание, умножение и деление начинают с общего кода (адрес #0001), который переносит аргументы в tmpA и tmpB, обычно из стековых регистров, а затем вызывает микроподпрограмму конкретной операции. Таблица адресов переходов в микрокод-движке содержит особую цель 0 с тремя разными адресами для умножения, деления и сложения/вычитания; это сделано специальной схемой в ROM, и автор называет такие хаки допустимыми при проектировании чипа. Подпрограмма сложения и вычитания начинается с адреса #0232. Сначала она обрабатывает нулевые случаи 0+0 и 0-0, затем вычитает экспоненты и, если у первого аргумента экспонента меньше, меняет аргументы местами, а «защёлка знака» при необходимости переключается. Далее вызывается CREATE_DENORM, сдвигающий tmpB для выравнивания экспонент. Для сложения мантиссы суммируются, а при переполнении (бит 64 суммы) результат сдвигается вправо на один разряд и счётчик поправки экспоненты увеличивается. Для вычитания мантиссы вычитаются, при отрицательной разности значение обращается, а знак переключается; отдельная ветка обрабатывает нулевой результат. Текст в доступной части обрывается посреди листинга микрокода, поэтому остальные шаги (нормализация, округление, обработка переполнения и бесконечностей) здесь не раскрыты.

Ключевые факты

  • Intel 8087 (1980) ускорил вычисления с плавающей запятой в IBM PC; по словам автора, сложение быстрее, чем на 8086, почти в 100 раз, сложные операции ещё сильнее.
  • Автор вскрыл чип зубилом и сфотографировал кристалл: ROM микрокода хранит 1648 микроинструкций, нижняя половина кристалла, 80-битный тракт данных.
  • Внутренний формат «temporary real»: знак, 15-битная экспонента со смещением 16383 и 64-битная мантисса; регистров восемь, организованы стеком, у каждого есть тег (ноль, допустимое, особое, пустой).
  • Сложение и вычитание идут через 69-битный целочисленный сумматор и сдвигатель; каждая из этих операций занимает две 16-битные микроинструкции.
  • Микроподпрограмма сложения/вычитания начинается с адреса #0232: обработка нулей, сравнение экспонент, обмен аргументов, выравнивание сдвигом, сложение или вычитание мантисс.

Почему это важно

Разбор показывает на реальном кристалле и реальном микрокоде, как сопроцессор 1980 года превратил сложную арифметику с плавающей запятой в последовательность простых 16-битных микроопераций. Это редкая возможность увидеть, из чего состоят выравнивание порядков, нормализация и обработка особых значений, на которых до сих пор держатся вычисления с дробными числами. Автор также отмечает аппаратные приёмы вроде отдельной схемы для особой цели перехода в ROM.

Кому это важно

Интересно тем, кто любит историю вычислительной техники и обратную разработку микросхем, а также программистам и студентам, которые хотят понять, как устроены числа с плавающей запятой, биты округления (guard, round, sticky), теги особых значений и стек регистров изнутри.

Как это применить

Практический смысл, учебный. Статья даёт разобранные на примерах (13,5+3,5 и 8-7,5) шаги алгоритма: выровнять экспоненты сдвигом, сложить или вычесть целые мантиссы, нормализовать результат и скорректировать экспоненту. Эти же шаги помогают читать документацию по формату и отлаживать собственные реализации арифметики. Цен, лицензий и инструментов в материале нет.

Можно ли доверять

Материал написан от первого лица на личном техническом блоге righto.com и опирается на собственные снимки кристалла и листинг микрокода. Оценка ускорения «почти в 100 раз» для сложения приведена без указания методики измерения, тактовой частоты 8086 или бенчмарка; пояснение к ней вынесено в сноску, которая в доступный текст не вошла. Доступная часть статьи обрывается на середине листинга микрокода, так что вывод о полном алгоритме по ней сделать нельзя.

Риски и подводные камни

Материал плотный и рассчитан на читателя, знакомого с двоичными числами и архитектурой процессоров; без этого микрокод читается тяжело. Поскольку листинг в доступном тексте обрывается, детали нормализации, округления и обработки бесконечностей здесь не видны. Не стоит переносить описанные адреса и тонкости микрокода на другие чипы: они относятся именно к 8087.