Пара вопросов по FPU

Тема в разделе "WASM.ASSEMBLER", создана пользователем xRom2, 2 июн 2011.

  1. xRom2

    xRom2 New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2011
    Сообщения:
    63
    1) Если вершина стека st0 - свободна, могу ли я считать что остальные регистры тоже свободны? Или по хорошему надо делать проверку каждого из них? Задача: не затереть имеющиеся значения при вызове другой функции моей же программы. Сохранять всю среду сопроцессора - очень долго.

    2) Как узнать за один прием - сколько сводобных регистров у фпу в данный момент? Если я использую fstsw, то биты 11-13 определяют число текущей вершины стека, однако оно становится нулем и в случае когда все регистры свободны и когда - все заняты. Или я что-то не так понимаю?
     
  2. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    Стек сопроцессора это кольцевой буфер. Очевидно при переполнении затираются его поля.
     
  3. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    xRom2
    Выяснение числа свободных регистров и их сохранение скорее всего будет дольше полного сохранения состояния сопроцессора. Некоторые компиляторы регистры сопроцессора очищают перед вызовом других функций, а числа с плавающей точкой передают через обычный стек(иногда функции возвращают результат в st0, но остальные регистры сопроцессора при этом свободны). Вообще ситуация такова, что в вызывающей функции проще очистить регистры, чем в вызываемой функции разбираться сколько и чего нужно сохранять.
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ничего не поделаешь - по негласному правилу при вызове функций стек FPU должен быть "девственно чист", иначе хлопот не оберешься.

    Ну узнаешь, что 2-3, а для нормальной работы функции нужно 4-5, и что будешь делать - писать 5 разных вариантов реализации под разное кол-во свободных регистров ?! Именно поэтому и договариваются, что в общем случае при вызове произвольных\"посторонних" функций стек FPU должен быть чист. И соотв-но отступать от этого правила можно только в случае когда точно знаешь, что вызываемая функция или вообще не юзвет FPU или юзает не более какого-то числа FPU-регистров
     
  5. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    leo
    Сопроцессор ничего про хлопоты не знает. Он только может сепшин доставить на процессор через fwait.
     
  6. asmlamo

    asmlamo Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    1.738
    Нет


    А зачем ? Что значит занят. Если в стеке FPU какие либо значения то это либо "мусор" который можно затереть,либо нужные данные.

    Если данные нужны то просто сохраняем состояние FPU а затем после наших манипуляций восстанавливаем.

    При таком подходе нам пофиг сколько регистров "занято" сколько "свободно" .


    SaveFPU db 110 dup (0) ; Буфер для сохранения состояния FPU.

    finit ; Инициализация мат.сопроцессора.
    fsave [SaveFPU] ; Сохраняем состояние FPU.

    frstor [SaveFPU] ; Восстанавливаем состояние FPU.
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    klzlk
    И в чем смысл сего "глубокомысленного" заявления?
    Во-первых, "сепшн доставляется" не только через fwait, а на любой FPU-команде, следующей за той, которая вызвала ошибку. Поэтому fwait обычно вставляют только в конце fpu-кода, да и то не всегда, а только в сл. когда он заканчивается операцией, которая может вызвать исключение.
    Во-вторых, тут речь идет не о самом сопроцессоре, а о том как его правильно использовать, чтобы с одной стороны не нарваться на сепшены, а с другой стороны не тормозить исполнние бесконечными fsave\frstor.
     
  8. xRom2

    xRom2 New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2011
    Сообщения:
    63
    Эт правильно, но в данном случае вторая функция - обработчик аппаратного прерывания и может быть вызвана в произвольный момент времени. Я конечно могу обойтись в ней исключительно целочисленной арифметикой, но в плане объема кода - это будет тихий ужас. Да и скорость тоже наверно пострадает. Там-то дело по идее плевое: на вход подаются куча данных с локатора в вещественном виде (qword), мне надо перевести их в целые и выдать основной программе. Ну и сделать небольшие проверки на границы, что тоже удобнее делать через fpu. Кстати как я понимаю команду Bound тоже нельзя использовать под виндой в юзермоде?

    Ну я то знаю сколько регистров надо в каждом случае, я бы тогда делал fstp в отдельный буфер, выполнял все что мне нужно и загружал бы обратно. Ну типа push тока для фпу :) Я уже подумал было заменить все увеличивающи или уменьшающие стек сопра команды на макросы и воткнуть в каждый макрос отдельную переменную, которая либо уменьшается командами типа fstp/faddp или увеличивается командами fld/fscale. Идея была хороша, но проблема условных переходов ее похоронила: ассемблер-то тупо подсчитает число команд увеличивающих и умеьшающих стек, но то что часть из них не будет выполнена из-за условных переходов он подсчитать не может. Вобщем сохраняю пока всю среду сопра для надежности.
     
  9. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    leo
    1. При переполнении стека исключение на процессор не будет доставлено, если в управляющем регистре соответствующие исключения замаскированы. Посему переполнение безопасно. Другое это потеря данных на стеке.

    2. Для этого используется сторонний буфер, стек потока(ядро например сохраняет контекст NPX на дне ядерного стека) или есчо какая память, для хранения переменных. Можно и надстройку написать, сохраняющую среду при переполнении стека.
     
  10. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    xRom2
    Для преобразования из чисел с плавающей точкой в целые сопроцессор не сильно нужен: нужно проверить знак, затем проверить, что значение не уползло за верхнюю или нижнюю границу чисел представимых ввиде целого, иначе просто вытащить мантисту и сдвинуть её - всего 6 ветвей. Для 4х байтовых чисел потребуется порядка 30 команд и 2-3 целочисленных регистра.
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    xRom2
    Вот именно, что "по идее плевое", поэтому и не понятно, почему этим должен заниматься именно обработчик прерывания, а не основная программа (тем более, что в ней fpu-вычисления все равно использ-ся).

    Сравнение неотрицательных вещ.чисел на больше\меньше\равно с константами проще и быстрее делаются в целочисленном виде, нежели на fpu. С отрицательными чуть сложнее.
    А для преобразования (валидного\проверенного) double в целое стоит обратить внимание на "замечательную" SSE2-команду cvtsd2si r32,m64, которая не портит никакие xmm регистры
     
  12. xRom2

    xRom2 New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2011
    Сообщения:
    63
    Основная программа - разработка головного офиса конторы, которой по сути плевать на все, ибо оборонка. Формально работает, а исправления могут длиться годами, вот и выкручиваемся как можем. Исходников-то нету, все засекречено, а локаторы-то уже давно новые, интферфейсы другие, данные выдают по другому. а сама программа работает в досе, и максимум что я смог - это трассировать и узнать где и как она забирает данные, и установить обработчик прерывания перед ее запуском, чтобы их туда подсовывать.

    Спасибо, я совсем упустил из виду возможности расширений. Ща проштудирую, спасибо. А пока сделал просто и надежно: выделил буфер и написал аналог пуша: при вызове он сохраняет в буфер, устаналивает флаг записи и число сохраненных регистров. При попе - все наоборот. Вобщем работает, хотя и не так быстро, но быстрее чем всю среду сохранять.
     
  13. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    xRom2
    Нету простого и надёжного способа сохранять регистры сопроцессора частично. Последовательность fstp/fld испортит состояние сопроцессора если верхний регистр пуст.
     
  14. xRom2

    xRom2 New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2011
    Сообщения:
    63
    Я проверяю каждый регистр перед сохранением при помощи fxam, а потом просто два бита проверить и все. Единственная возможная проблема будет если пустой регистр окажется между двумя содержащими значения, но пока вроде такого не произошло.