Примечание: прошло много времени с тех пор, как я работал над этим. Надеюсь, мой ответ на стадионе.
Вам нужно перехватить исключение div-0, которое возникает, когда это происходит, - я считаю, что MSR.FE0
и MSR.FE1
, а также FPSCR.VE
и FPSCR.ZE
нужно будет манипулировать, чтобы обеспечить обрабатывать это так, как вы хотите.
Так что, как только вы настроите и заработаете, вам нужно:
взять на себя управление обработкой исключений для этих сценариев (0/0 и 1/0). В большинстве небольших ядер реального времени, которые я использую, со всем доступным исходным кодом, я бы знал, что делать. Не уверен, какой у вас ОСРВ или какой у вас контроль. Скорее всего, если это «тяжеловесная» ОС, она не позволит вам возиться с логикой обработчика исключений.
Я думаю, что 0/0
вызовет исключение "недопустимая операция" (FPSCR.VE
), тогда как 1/0
вызовет исключение IEEE с плавающей запятой с нулевым делением (FPSCR.ZE
).
если вы получаете исключение Invalid Operation, вам нужно определить, была ли причина 0/0
или что-то еще. С 0/0
, FPSCR.VXZDZ
будет установлено (я думаю). Есть и другие способы вызвать это исключение, поэтому здесь FPSCR
ваш друг.
если вы получаете исключение IEEE FP div-0, вам необходимо определить, была ли причина 1/0
или что-то еще (например, 2/0
). Я думаю, что для этого вам нужно изучить регистры прерванного контекста, чтобы увидеть, был ли числитель 1
во время операции деления, которая вызвала исключение. FPU не волнует, если вы пытались 1/0
или 2/0
, но, очевидно, ваше приложение делает.
Далее вам нужно изменить возвращаемый контекст, чтобы получить желаемый результат. Это может быть что-то вроде изменения регистров FP, используемых в операции, так что при возврате из исключения и повторном испытании деления FP он возвращает ноль. Например, сделать числитель 0
и делитель 1
.
Затем, когда вы вернетесь из исключения, вы получите желаемый результат. Извините, я не справился с конкретными регистрами и значениями, надеюсь, этого достаточно, чтобы выполнить работу.
Вы также спрашивали о выборочном включении этого поведения только для вашего процесса приложения. Раньше мне приходилось делать подобные вещи, но больше в плоско-адресном пространстве, ядрах типа «один процесс, несколько потоков» (где каждая задача на самом деле является потоком, все выполняются в одном и том же плоском адресном пространстве). Я сделал это несколькими разными способами, вот несколько идей, которые могут работать для вас:
В обработчике исключений проверьте идентификатор процесса / идентификатор задачи и, если это процесс вашего приложения, обработайте его особым образом, в противном случае обработайте его стандартным "системным" способом.
В качестве альтернативы, при переключении контекста в вашем приложении установите «специальную» обработку для этого исключения. При переключении контекста из процесса приложения замените его на стандартную обработку. Обратите внимание, что само приложение не сможет сделать это, вам нужно будет подключиться к ядру, чтобы сделать это (возможно, вы можете использовать ловушку переключения контекста / callout, в противном случае вы, вероятно, будете изменять исходный код ядра). ).
Я унаследовал подобный код и чувствую вашу боль. Вы хотите потрясти кулаком людей, которые установили такое поведение с костью, но сейчас покачивание кулаком не помогает вам отправлять продукт. Вам нужно решение. Удачи.