PowerPC:如何使 div/0 结果返回零

发布于 2024-11-17 01:28:05 字数 330 浏览 4 评论 0原文

我们正在尝试将遗留应用程序从旧的单片 RTOS 移植到 PowerPC 8360 上基于 UNIX 的 RTOS。在旧系统中,我们的大型代码库变得依赖于 1/0 返回零和 0/0 返回零。现在,在新操作系统中,1/0 返回 inf,0/0 返回 NaN,这会破坏我们的应用程序。我们尝试过使用 FPSCR 寄存器,但没有结果。

其次,如果有办法改变的话,改变是否会影响到我们的应用程序进程而不是整个系统?我们不想更改系统内其他应用程序的 div/0 行为。

预见到不可避免的“你为什么要这样做”的问题,我们必须保留以前的行为,因此将应用程序更改为实际上不除以零是不可能的。这是我们的痛处,所以请不要询问。提前致谢!

We are attempting to port a legacy application from an old monolithic RTOS to a unix based RTOS on a PowerPC 8360. In the old system, our large code base became dependent upon 1/0 returning zero, and 0/0 returning zero. Now in the new operating system 1/0 returns inf and 0/0 returns NaN, which breaks our application. We've tried playing around with the FPSCR register with no results.

Secondly, if there is a way to change it, can the change take affect for our application process and not the entire system? We do not want to change the div/0 behavior of other applications within the system.

Anticipating the inevitable "why are you doing it that way" question, we have to preserve the previous behavior so changing the app to actually not divide by zero is out of the question. This is a sore spot with us so please refrain from asking. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

善良天后 2024-11-24 01:28:05

注意:我已经有一段时间没有从事此类工作了。希望我的答案是大概的。

您需要捕获发生这种情况时发生的 div-0 异常 - 我相信 MSR.FE0MSR.FE1< /code> 以及 FPSCR.VEFPSCR.ZE 需要进行操作,以确保按照您想要的方式进行处理。

因此,一旦您完成该设置并开始工作,您将需要:

  • 控制这些场景(0/0 和 1/0)的异常处理。在我使用的大多数小型实时内核中,只要有所有可用的源代码,我就会知道该怎么做。不确定您的 RTOS 是什么或您拥有多少控制权。很可能,如果它是一个“重量级”操作系统,它不会让您摆弄异常处理程序逻辑。
    我认为 0/0 将触发“无效操作”异常 (FPSCR.VE),而 1/0 将触发 IEEE 浮动-零点除法异常 (FPSCR.ZE)。

    • 如果您收到无效操作异常,您需要确定原因是 0/0 还是其他原因。使用 0/0FPSCR.VXZDZ 将被设置(我认为)。还有其他方法可以触发此异常,因此 FPSCR 是您的朋友。

    • 如果您收到 IEEE FP div-0 异常,您需要确定原因是 1/0 还是其他原因(例如 2/0) 。我认为为此,您必须检查中断上下文的寄存器,以查看在导致异常的除法运算时分子是否为 1。 FPU 并不关心您尝试的是 1/0 还是 2/0,但显然您的应用程序会关心。

  • 接下来,您需要更改返回的上下文,以便获得所需的结果。这可能类似于更改操作中使用的 FP 寄存器,以便当您从异常返回时 &重新尝试 FP 除法,结果为零。例如,使分子 0 和除数 1

然后当你从异常返回时,你应该得到你想要的结果。抱歉,我对特定的寄存器和值很生疏,我希望这足以完成工作。

您还询问了是否有选择地为您的应用程序进程启用此行为。我以前必须做这样的事情,但更多的是在平面地址空间,“单进程,多线程”类型内核(其中每个任务实际上是一个线程,所有任务都在同一个平面地址空间中运行)。我已经用几种不同的方式完成了它,以下是一些可能对您有用的想法:

  • 在异常处理程序中,检查进程 ID / 任务 ID,如果它是您的应用程序进程,则以特殊方式处理它,否则处理它是标准的“系统”方式。

  • 或者,在上下文切换到应用程序时,安装对此异常的“特殊”处理。在应用程序进程的上下文切换时,将其替换为标准处理。请注意,应用程序本身无法执行此操作,您必须进入内核才能执行此操作(可能有一个可以使用的上下文切换挂钩/标注,否则您可能会修改内核源代码)。

我之前继承过这样的遗留代码&我感受到你的痛苦。你想对那些做出这种愚蠢行为的人挥动拳头,但现在挥动拳头并不能帮助你交付产品。你需要一个解决方案。祝你好运。

Note: it's been a while since I worked on this kind of stuff. Hopefully my answer is in the ballpark.

You'll need to trap the div-0 exception that occurs when this happens -- I believe MSR.FE0 and MSR.FE1 as well as FPSCR.VE and FPSCR.ZE will need to be manipulated in order to ensure the handling of this the way you want.

So once you get that set up and working, you'll need to:

  • take control of the exception handling for these scenarios (0/0 and 1/0). In most of the small real-time kernels I use, with all source code available, I would know what to do. Not sure what your RTOS is or how much control you have. Chances are, if it's a "heavierweight" OS, it's not going to let you fiddle with exception handler logic.
    I think 0/0 will trigger an "Invalid Operation" exception (FPSCR.VE), whereas 1/0 will trigger an IEEE floating-point zero divide exception (FPSCR.ZE).

    • if you get the Invalid Operation exception you need to determine if the cause was 0/0 or something else. With 0/0, FPSCR.VXZDZ will be set (I think). There are other ways to trigger this exception so here FPSCR is your friend.

    • if you get the IEEE FP div-0 exception you need to determine if the cause was 1/0 or something else (e.g. 2/0). I think for this you'll have to examine the registers of the interrupted context to see if the numerator was 1 at the time of the division operation that caused the exception. The FPU doesn't care if you attempted 1/0 or 2/0, but apparently your application does.

  • next, you need to alter the returning context so that you get the desired result. This might be something like changing the FP registers used in the operation so that when you return from exception & the FP division is re-tried, it yields zero. For example, make the numerator 0 and the divisor 1.

Then when you return from the exception, you should get your desired result. Sorry I'm rusty on the specific registers and values, I hope this is enough to get the job done.

You also asked about selectively enabling this behavior just for your application process. I've had to do things like this before, but more in flat-address space, "single process, multiple thread" type kernels (where each task is really a thread, all running in the same flat address space). I've done it a couple different ways, here are some ideas that might work for you:

  • In the exception handler, examine the process ID / task ID and if it's your application process, handle it the special way, otherwise handle it the standard "system" way.

  • Alternatively, on a context switch into your application, install your "special" handling for this exception. On a context switch out of your application process, replace it with the standard handling. Note that the application itself won't be able to do this, you'll have to tap into the kernel to do it (there might be a context switch hook/callout that you can use, otherwise you'll probably be modifying kernel source).

I've inherited legacy code like this before & I feel your pain. You want to shake your fist at the people who installed such bone-headed behavior, but right now shaking your fist doesn't help you ship product. You need a solution. Good luck.

辞慾 2024-11-24 01:28:05

如果您要迁移到 POSIX 兼容系统(例如 QNX 或 Linux),您可能需要尝试在应用程序中添加代码来捕获 SIGFPE 并处理那里的情况。

不知道你正在使用什么语言,并且(更重要的是)不用担心很长一段时间捕获信号,我不确定你将如何添加代码,但也许这个问题的答案(如何在 Linux C++ 中捕获系统级异常?)会有帮助的。

If you are moving to a POSIX compliant system (like QNX or Linux), you might want to try adding code in your application to catch SIGFPE and handle the condition there.

Not know what language you are using, and (more importantly) not having worried about catching signals in a long time, I'm not sure exactly how you would add the code, but perhaps the answers to this question (How do I catch system-level exceptions in Linux C++?) will help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文