1 Reply Latest reply on Apr 17, 2018 1:41 AM by Al Hill

    Get Status Word and Handle X87 FPU Exception

    winkss

      I wrote a test code to generate and handle an overflow exception.

      #include <stdio.h>
      #include <signal.h>
      void getStatus() {
          short status;
          __asm__(
              "fnstsw %0\n\t":"=m"(status)
          );
          printf("0x%x\n", status);
      }
      void setUnmask() {
          int cw = 0x366;
          __asm__(
              "fldcw %0\n\t"::"m"(cw)
          );
      }
      /// Get the status register content of X87 FPU. 
      short getExcepFlag() {
          short status;
          __asm__(
               "fnstsw %0\n\t":"=m"(status):"m"(status)
          );
          return status;
      }
      int fpu(int value) {
          int result = -1;
          for (int i = 0; i < 10; ++i) {
              __asm__(
                  "fldl %0\n\t":"=m"(result):"m"(value)
              );
              printf("normal\n");
              getStatus();
          }
          return result;
      }
      void sigHandler(int sig) {
          printf("Get an exception\n");
          long temp;
          short status = getExcepFlag();
          printf("0x%x\n", status);
          if (status & 0x00C0 == 0x00C0) {
              if (status & 0x0200 == 0x0200) {
                  __asm__("fnclex\n\t");
                  __asm__("fstp %0\n\t":"+m"(temp):"m"(temp));
              } else {
      
              }
          }    return;
      }
      int main() {
          setUnmask();
          signal(SIGFPE, sigHandler);
          fpu(123);
      }
      

      However, the result was not the same as what I expected.

      First, if I did fldl 9 times(change i<10 to i<9), the status word showed there was an exception. (SW was 0x82c3) But my signal handler didn't get a signal and printed nothing.

      Second, after fldl was executed 10 times, the sigHandler worked. But the returned value status was always 0x0, it seemed that the SW was cleared. Therefore my handler couldn't determine which was the exception.

      Finally, the sigHandler would be executed infinite times. The printing wouldn't stop itself.

      I have read D.3.4, Volume 1, Developer's Manual, and found some similar situations. But I am confused about that whether can I deal with the exception with C/C++ and signal(), because the examples are all written in assembly code.

      My environment is Ubuntu 17.10.