Как программное обеспечение выполняет арифметику с плавающей запятой, когда в ЦП нет (или глючит) модуля с плавающей запятой? Примерами могут служить архитектуры микроконтроллеров PIC, AVR и 8051.
Как операции с плавающей запятой эмулируются в программном обеспечении?
Ответы (4)
"Эмуляция" — неправильный термин в контексте PIC, AVR и 8051. Эмуляция с плавающей запятой относится к эмуляции аппаратного обеспечения FPU в архитектурах, которые имеют опцию FPU, но для которых не все части включают FPU. Это позволяет запускать двоичный файл, содержащий инструкции с плавающей запятой, на варианте без FPU. Там, где это используется, эмуляция FPU реализуется как обработчик исключений с недопустимыми инструкциями; когда встречается инструкция FPU, но FPU отсутствует, возникает исключение, и обработчик считывает значение инструкции и реализует операцию в программном обеспечении.
Однако ни одна из перечисленных вами архитектур не определяет инструкции FPU или FPU, поэтому эмулировать нечего. Вместо этого в этих случаях операции с плавающей запятой полностью реализуются в программном обеспечении, а компилятор генерирует код для вызова подпрограмм с плавающей запятой по мере необходимости. Например, выражение x = y * z ;
сгенерирует код, эквивалентный вызову функции x = _fmul( y, z ) ;
. На самом деле, если вы посмотрите на вывод карты компоновщика из сборки, содержащей операции с плавающей запятой, вы, вероятно, увидите обычные имена символов, такие как _fmul
, _fdiv
и им подобные - эти функции являются внутренними для компилятора.
Плавающая точка - это просто научная запись в базе 2. И мантисса, и экспонента являются целыми числами, и библиотеки softfloat разбивают операции с плавающей частью на операции, влияющие на мантиссу и экспоненту, которые могут использовать поддержку целых чисел ЦП.
Например, (x 2n) * (y 2m) = x * y 2n+m.
Часто также требуется этап нормализации, чтобы сохранить каноническое представление с плавающей запятой, но перед нормализацией может быть возможно выполнить несколько операций. Кроме того, поскольку IEEE-754 хранит экспоненту со смещением, это необходимо учитывать.
Плавающая точка не "эмулируется". Обычно они хранятся, как описано в IEEE754.
Фиксированная точка — это другой тип реализации. Число 2,54 может быть реализовано как с фиксированной, так и с плавающей запятой.
Программная реализация VS FPU (модуль с плавающей запятой)
Некоторые современные микроконтроллеры, такие как ARM cortex M4F, имеют блок с плавающей запятой и могут выполнять операции с плавающей запятой (такие как умножение, деление, сложение) на аппаратном уровне намного быстрее, чем программное обеспечение.
В 8-битных микроконтроллерах, таких как AVR, PIC и 8051, операции выполняются только программно (деление может занимать до сотен операций). Ему придется отдельно обрабатывать часть мантиссы (дробной части) и часть экспоненты, а также все особые случаи (например, NaN). У компилятора часто есть много подпрограмм, угрожающих одной и той же операции (например, деление), и он будет выбирать в зависимости от оптимизации (размер/скорость) и других параметров (например, если он знает, что числа всегда положительны...)
Существует еще один вопрос SO, который охватывает требования стандартов C/C++ к числам с плавающей запятой. Так что, строго говоря, float может быть представлен в любой форме, которую предпочитает компилятор. Но на практике, если ваша реализация с плавающей запятой значительно отличается от IEEE754, вы можете ожидать много ошибок, вызванных программами, которые привыкли к IEEE754. И компилятор должен быть дружелюбным к программисту и не должен создавать проблем, используя неуказанные места стандартов. Таким образом, в большинстве случаев числа с плавающей запятой будут представлены так же, как и во всех других архитектурах, включая x86. Арифметика с фиксированной точкой слишком отличается.
В случае AVR и PIC компилятор знает, что fpu недоступен, поэтому он преобразует каждую операцию в набор команд, которые поддерживает ЦП. Он должен будет нормализовать оба операнда до общего показателя степени, затем выполнить операцию над мантиссом, как над целыми числами, а затем настроить показатель степени. Это довольно много операций, поэтому эмулируемая плавающая точка работает медленно. И, кроме того, если вы оптимизируете размер, каждая операция с плавающей запятой может стать вызовом функции.
А на арке ARM все может быть довольно странно. Есть ARM с FPU и без. И вы можете захотеть иметь универсальное приложение, которое будет работать на обоих. На этот случай есть хитрая (и медленная) схема. Приложение использует команды FPU. Если ваш процессор не имеет FPU, то такая команда вызовет прерывание, и в нем ОС будет эмулировать инструкцию, сбрасывать бит ошибки и возвращать управление приложению. Но эта схема оказалась очень медленной и обычно не используется.