Прерывания и особые ситуации: Условия генерации и особенности обработки исключений FPU

Печать
Программирование - Архитектура и система команд микропроцессоров x86

 

Недействительная операция (#I)

Существует два класса операций, которые могут вызывать исключение недействительная операция: стековые и арифметические. В случае возникновения этого исключения устанавливается флаг SW.IE, а флаг SW.SF идентифицирует тип ошибки.

  1. Стековые операции (#IS)

    Исключение возникает, если производится попытка занесения данных в занятый стековый регистр или попытка чтения из незанятого регистра. При этом в сопроцессорах, которые отвечают стандарту IEEE-754 (Intel387, Intel486, …), устанавливается также флаг SW.SF, а флаг SW.C1 идентифицирует тип стековой ошибки.

    • SW.C1 = 1 — запись в занятый регистр;
    • SW.C1 = 0 — чтение пустого регистра.

    Когда исключение "недействительная операция" замаскировано, FPU возвращает неопределенность в формате операнда-назначения. Это значение помещается в операнд-назначение, разрушая его содержимое. Когда исключение не замаскировано, то вызывается обработчик исключений, поле SW.TOP и исходные операнды не изменяются.

  2. Арифметические операции (#IA)

    Исключение генерируется в самых различных случаях, когда команды используют неправильные операнды. Если исключение не замаскировано, то вызывается обработчик исключений, и операнды остаются неизмененными. Если же исключение замаскировано, то устанавливаются соответствующие коды условий в регистре SW или в качестве результата операции возвращается специальное значение — неопределенность.

     

    Таблица 3.7. Условия возникновения исключения #IA и реакция сопроцессора, если исключение замаскировано

    

    Условия

    Реакция (при CW.IM=1)1

    Для сопроцессоров отвечающих стандарту IEEE-754 (Intel386, Intel486, ...)3

    Для сопроцессоров Intel287, 8087

    Один или оба операнда SNAN.

    Один или оба операнда NAN.

    Возвращает неопределенность QNAN (с большим абсолютным значением).

    Сравнение или тестирование, если один или оба операнда NAN.

    Сравнение или тестирование, если один или оба операнда  NAN, или один операнд - проективная бесконечность.

    Устанавливает код "несравнимы" (SW.C3, SW.C0 = 11).

    Сложение бесконечностей с различными знаками или вычитание бесконечностей с одинаковыми знаками.

    Сложение бесконечностей с различными знаками или вычитание бесконечностей с одинаковыми знаками (аффинная арифметика). Сложение или вычитание, когда оба операнда - проективная бесконечность.

    Возвращает неопределенность QNAN.

    Умножение бесконечности на нуль или нуля на бесконечность.

    Умножение бесконечности на нуль или нуля на бесконечность.

    Возвращает неопределенность QNAN.

    Деление бесконечности на бесконечность или нуля на нуль.

    Деление бесконечности на бесконечность, нуля на нуль, нуля на псевдонуль, делитель не нормализован или денормализован.

    Возвращает неопределенность QNAN.

    Команды FPREM, FPREM1: делитель нулевой, или делимое бесконечность.

    Команды FPREM, FPREM1: делитель нулевой, не нормализован, денормализован, или делимое бесконечность.

    Возвращает неопределенность QNAN, устанавливает код "команда завершения" (C2=0).

    Команда FSQRT: отрицательный операнд (кроме -0); команда FYL2X: отрицательный операнд (кроме -0); команда FYL2XP1: операнд меньше -1.

    Команда FSQRT: операнд не нормализован, денормализован, отрицательное число (кроме -0), проективная бесконечность.

    Возвращает неопределенность QNAN.

    Команды FIST(P): регистр источник пуст, NAN, бесконечность или непредставим в указанном формате.

    Команды FIST(P): регистр источник пуст, не нормализован, денормализован, NAN, бесконечность или непредставим в указанном формате.

    Записывает целочисленную неопределенность.

    Команды FBST(P): регистр источник пуст, NAN, бесконечность или превышает 18 десятичных цифр.

    Команды FBST(P): регистр источник пуст, денормализован, не нормализован, NAN, бесконечность или превышает 18 десятичных цифр.

    Записывает упакованную десятичную неопределенность.

     

    Команды FST(P): регистр источник содержит не нормализованные значения, а регистр приемник определен форматом short-real или long-real.

    Записывает код неопределенности в формате short-real или long-real.

    Тригонометрические команды FCOS, FSIN, FPTAN, FSINCOS: операнд бесконечность.

     

    Возвращает неопределенность QNAN, устанавливает код SW.C2 = 0.

    Команда FXCH: один или оба регистра пусты.

    Команда FXCH: один или оба регистра пусты.

    Заполняет пустой/пустые регистры кодом неопределенность QNAN и совершает обмен.

    Операции с неподдерживаемыми форматами2

     

    Возвращает неопределенность QNAN.

     

     

    1.  Процессоры Intel287, 8087 не поддерживают формат неопределенности QNAN, вместо этого они возвращают неопределенность в формате временного вещественного.

     

    2.  Форматы псевдонуль, псевдоNAN, псевдонеопределенность, и не нормализованный поддерживаются только сопроцессорами Intel287 и 8087. Intel387, Intel486, … генерируют исключение #IA при встрече данных форматов.

     

    3.  Intel387, Intel486, ... автоматически нормализуют встреченные денормализованные операнды, где это возможно.

     

     

    Флаг SW.SF, при генерации исключения #IA не устанавливается — он сигнализирует только о стековых ошибках #IS. Однако возможна ситуация, когда флаг SW.SF не был сброшен после предыдущей стековой ошибки #IS. В этом случае после арифметической ошибки #IA окажутся установленными флаги SW.SF и SW.IE, что может быть неправильно интерпретировано как стековая ошибка #IS.

 

Денормализованный операнд (#D)

Исключение "денормализованный операнд" индицируется флагом SW.DE (бит 1). Оно генерируется в следующих случаях:

Во всех сопроцессорах, если исключение #D не замаскировано (CW.DM = 0), то при встрече денормализованного операнда происходит вызов обработчика исключений (операнды при этом не изменяются).

Если исключение замаскировано (CW.DM = 1), то процессоры Intel387, Intel486, … производят преобразование встреченных денормализованных операндов к нормализованному виду. Сопроцессоры Intel287, 8087 в этом случае оперируют с денормализованными операндами по следующим правилам:

  • для команды FLD, когда операнд-источник денормализован — операнд загружается как обычный (никаких специальных действий);
  • для арифметических команд, когда один или оба операнда денормализованы — операнд(ы) преобразуются в эквивалентное ненормализованное значение и команда выполняется;
  • в команде FXTRACT исключение #D не поддерживается.

 

Деление на нуль (#Z)

Исключение "деление на нуль" индицируется флагом SW.ZE (бит 2). Оно возникает при делении ненулевого операнда на нуль. Это возможно в командах F(I)DIV(R)(P), а также в неявно использующих деление командах FYL2X и FXTRACT.

Если исключение не замаскировано (CW.ZM = 0), то вызывается обработчик исключения, исходные операнды и поле SW.TOP остаются неизменными. Если же исключение замаскировано (CW.ZM = 1), то происходит следующее:

  • операции F(I)DIV(R)(P) возвращают бесконечность со знаком равным исключающему ИЛИ (XOR) знаков операндов;
  • FYL2X возвращает бесконечность со знаком противоположным знаку ненулевого операнда;
  • для FXTRACT, ST(1) устанавливается равным - , ST(0) устанавливается в 0 со знаком исходного операнда (Intel387, Intel486, …).

 

Переполнение (#O)

Исключение "переполнение" индицируется флагом SW.OE (бит 3). Оно генерируется, если результат операции превышает максимально допустимое значение для положительных чисел или минимально допустимое для отрицательных. Это может происходить в командах FST(P), F(I)ADD(P), F(I)SUB(R)(P), F(I)MUL(P), FDIV(R)(P), FSCALE, FYL2X, FYL2XP1. Исключение #O генерируется только в тех случаях, когда некорректным результатом операции является число в формате вещественного. Для случаев, когда результатом операции является целое или двоично-десятичное значение генерируется исключение #IA.

 

Если исключение "переполнение" замаскировано (CW.OM = 1), то возвращается одно из значений по таблице 3.8.

 

Таблица 3.8. Значения, возвращаемые, когда исключение "переполнение" замаскировано

Значения, возвращаемые, когда исключение

 

Если исключение "переполнение" не замаскировано (CW.OM = 0), реакция сопроцессора зависит от того, предполагает команда поместить результат в стек или в память.

Если назначением является стек, истинный результат делится на 224576 и округляется (до заданной полем PC слова управления точности в командах, где задание точности возможно, и до расширенной точности в других командах). Бит SW.C1 устанавливается, если произошло округление вверх.

Если назначением является память, то в ней ничего не сохраняется, исходные операнды и поле SW.TOP остаются неизменными. Обработчик исключения может изменить исходные операнды и перезапустить команду, а также принудительно записать нужный результат в память и продолжить выполнение.

В процессорах Intel387, Intel486, … , если исключение "переполнение" замаскировано и установлен режим округления к нулю, результатом операции, вызвавшей переполнение, является наибольшее положительное или наименьшее отрицательное число. Сопроцессоры Intel287 и 8087 не генерируют исключение "переполнение", если маскируемый отклик не является бесконечностью.

Если исключение "переполнение" не замаскировано, то в процессорах Intel387, Intel486, … , когда результат запоминается в стеке, мантисса результата округляется в соответствии с полем PC слова управления или в соответствии с кодом операции; при этом флаг исключения точности устанавливается по результатам операции. В сопроцессорах Intel287 и 8087 округление не производится и флаг исключения точности не изменяется.

 

Антипереполнение (#U)

Исключение "антипереполнение" индицируется флагом SW.UE (бит 4). Оно может быть вызвано командами FST(P), FADD(P), FSUB(R)(P), FMUL(P), F(I)DIV(R)(P), FSCALE, FPREM(1), FPTAN, FSIN, FSINCOS, FPATAN, F2XM1, FYL2XP1, которые выдают следующие результаты (только для вещественных, некорректные целые и двоично-десятичные результаты будут вызывать исключение #IA):

  • очень маленький результат, который из-за своей малости может стать причиной некоторых других исключений впоследствии (например, исключение "переполнение" после деления);
  • неточный результат, то есть ситуации, когда точный результат может быть получен при вычислении с неограниченным диапазоном экспоненты и точности (потеря точности при денормализации малых чисел).

Исключение "антипереполнение" генерируется:

  • когда результат одновременно маленький и неточный, если маска установлена (CW.UM = 1).
  • когда результат маленький, если маска не установлена (CW.UM = 0), точность/неточность результата значения не имеет.

Если исключение "антипереполнение" замаскировано (CW.UM = 1), то возвращается денормализованный или нулевой результат, также может генерироваться исключение #P.

Если исключение "антипереполнение" не замаскировано (CW.UM = 0), то реакция сопроцессора зависит от того, предполагает команда поместить результат в стек или в память.

Если назначением является стек, истинный результат умножается на 224576 и округляется до заданной полем PC слова управления точности в командах, где задание точности возможно и до расширенной точности в других командах. Бит SW.C1 устанавливается, если произошло округление вверх.

Если назначением является память, то в ней ничего не сохраняется, исходные операнды и поле SW.TOP остаются неизменными. Обработчик исключения может изменить исходные операнды и перезапустить команду, а также принудительно записать нужный результат в память и продолжить выполнение.

В сопроцессорах Intel287 и 8087 когда округление производится к нулю, и маска установлена (CW.UM = 1), флаг антипереполнения выставляется по маленькому результату независимо от его точности/неточности. Когда маска неустановлена, и назначение — стек, то мантисса не округляется (то есть результат отличается от результата в Intel387, Intel486, … значением наименее значимого бита мантиссы).

 

Неточный результат (#P)

Исключение "неточный результат" индицируется флагом SW.PE (бит 5). Оно возникает, если результат операции не может быть точно представлен в формате назначения (например, 1/3 не может быть точно представлена в двоичном виде). Команды вычисления трансцендентных функций (FSIN, FCOS, FSINCOS, FPTAN, FPATAN, F2XM1, FYL2X, FYL2XP1) всегда генерируют это исключение.

При обнаружении неточного результата, который не вызывает генерации исключений "переполнение" и "антипереполнение", независимо от того, замаскировано (CW.PM = 1) или не замаскировано (CW.PM = 0) исключение "неточный результат", сопроцессор устанавливает флаг SW.PE и возвращает округленный результат. Метод округления задается текущим значением поля CW.RC. Бит SW.C1 показывает в какую сторону произведено округление: SW.C1 = 1 — вверх, SW.C1 = 0 — вниз. При округлении вниз наименее значимые биты результата обрезаются, с тем чтобы получившееся значение соответствовало заданному для него формату.

Когда исключение "неточный результат" происходит вместе с исключением "переполнение" или "антипереполнение", то возможны следующие три варианта:

  • если неточный результат получен при замаскированных #O или #U, то сопроцессор устанавливает флаги SW.PE и, соответственно, SW.OE или SW.UE, а затем возвращает результат так, как это описано для этих исключений, далее управление передается в обработчик исключений, если CW.PM = 0;
  • если неточный результат получен при незамаскированных #O или #U, а результат операции должен помещаться в стек, то сопроцессор устанавливает флаги SW.PE и, соответственно, SW.OE или SW.UE, а затем возвращает результат так, как это описано для этих исключений, управление затем передается в обработчик исключений независимо от значения CW.PM;
  • если неточный результат получен при незамаскированных #O или #U, а результат операции должен помещаться в память, то неточность результата игнорируется.