s390.md ("udivsi3"): Ensure trap is generated for division by zero.
authorUlrich Weigand <uweigand@de.ibm.com>
Wed, 14 Jul 2004 13:09:09 +0000 (13:09 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Wed, 14 Jul 2004 13:09:09 +0000 (13:09 +0000)
gcc/ChangeLog:

* config/s390/s390.md ("udivsi3"): Ensure trap is generated
for division by zero.
("umodsi3"): Likewise.

libjava/ChangeLog:

* configure.host (DIVIDESPEC) [s390*-*-*]: Set to
-fno-use-divide-subroutine.
* include/s390-signal.h: Include <ucontext.h> and <limits.h>.
(HANDLE_FPE): Define.
(SIGNAL_HANDLER): Change third argument to ucontext_t *.
(struct old_s390_kernel_sigaction): Likewise for k_sa_handler.
(HANDLE_DIVIDE_OVERFLOW): Define.

From-SVN: r84683

gcc/ChangeLog
gcc/config/s390/s390.md
libjava/ChangeLog
libjava/configure.host
libjava/include/s390-signal.h

index ef5f5b6f2207e9c917ba74d6d92274eee0a00d89..98278ae5a5c8cfbd978e87bc97062e58c38f49fc 100644 (file)
@@ -1,3 +1,9 @@
+2004-07-14  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.md ("udivsi3"): Ensure trap is generated
+       for division by zero.
+       ("umodsi3"): Likewise.
+
 2004-07-14  Richard Sandiford  <rsandifo@redhat.com>
 
        * config/mips/mips.c (mips_output_move): When generating mips16 code,
index 1a53e71cd8b0045634c75056cb2b5cab8020bc9a..8a95d0cc3ab3af8b79412cba553e134386d53ce2 100644 (file)
       emit_move_insn (operands[0], const0_rtx);
       emit_insn (gen_cmpsi (operands[2], operands[1]));
       emit_jump_insn (gen_bgtu (label3));
-      emit_insn (gen_cmpsi (operands[2], const1_rtx));
+      emit_insn (gen_cmpsi (operands[2], const0_rtx));
       emit_jump_insn (gen_blt (label2));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_beq (label1));
       emit_move_insn(operands[0], operands[1]);
       emit_insn (gen_cmpsi (operands[2], operands[1]));
       emit_jump_insn (gen_bgtu (label3));
-      emit_insn (gen_cmpsi (operands[2], const1_rtx));
+      emit_insn (gen_cmpsi (operands[2], const0_rtx));
       emit_jump_insn (gen_blt (label2));
       emit_insn (gen_cmpsi (operands[2], const1_rtx));
       emit_jump_insn (gen_beq (label1));
index c64f2e943f1cc21feb64317417b9e0d2c8330798..4a2f6454e0f6e1888300c9b0c8b1b7c4793a289f 100644 (file)
@@ -1,3 +1,13 @@
+2004-07-14  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * configure.host (DIVIDESPEC) [s390*-*-*]: Set to 
+       -fno-use-divide-subroutine.
+       * include/s390-signal.h: Include <ucontext.h> and <limits.h>.
+       (HANDLE_FPE): Define.
+       (SIGNAL_HANDLER): Change third argument to ucontext_t *.
+       (struct old_s390_kernel_sigaction): Likewise for k_sa_handler.
+       (HANDLE_DIVIDE_OVERFLOW): Define.
+
 2004-07-14  Michael Koch  <konqueror@gmx.de> 
            Matthias Klose  <doko@debian.org> 
 
index 947392766bffaa7bb623c3171aef6fc4a47f19d2..4cef1b8a5d130c3581250d90f950ce0fd2ea8b33 100644 (file)
@@ -138,6 +138,7 @@ case "${host}" in
   s390*-*)
        sysdeps_dir=s390
        libgcj_interpreter=yes
+       DIVIDESPEC=-fno-use-divide-subroutine
        enable_hash_synchronization_default=yes
        ;;
   sparc*-*)
index 743c398830b110e6e6311eed8a312e5e961fdd74..fe965bd2b460f8aab713121d0a3b765a535c59c1 100644 (file)
@@ -15,18 +15,170 @@ details.  */
 
 #include <signal.h>
 #include <sys/syscall.h>
+#include <ucontext.h>
+#include <limits.h>
 
 #define HANDLE_SEGV 1
-#undef HANDLE_FPE
+#define HANDLE_FPE 1
 
 #define SIGNAL_HANDLER(_name)  \
-static void _name (int, siginfo_t *, void *)
+static void _name (int, siginfo_t *_si __attribute__((unused)), \
+                  ucontext_t *_uc __attribute__((unused)))
 
 /* We no longer need to fiddle with the PSW address in the signal handler;
    this is now all handled correctly in MD_FALLBACK_FRAME_STATE_FOR.  */
 #define MAKE_THROW_FRAME(_exception)
 
 
+/* According to the JVM spec, "if the dividend is the negative integer 
+   of the smallest magnitude and the divisor is -1, then overflow occurs 
+   and the result is equal to the dividend.  Despite the overflow, no 
+   exception occurs".
+
+   We handle this by inspecting the instruction which generated the signal,
+   and if dividend and divisor are as above, we simply return from the signal
+   handler.  This causes execution to continue after the instruction.  
+   Before returning, we the set result registers as expected.  */
+
+#define HANDLE_DIVIDE_OVERFLOW                                         \
+do                                                                     \
+{                                                                      \
+  unsigned char *_eip = (unsigned char *)                              \
+    __builtin_extract_return_addr (_si->si_addr);                      \
+  unsigned long *_regs = _uc->uc_mcontext.gregs;                       \
+  int _r1, _r2, _d2, _x2, _b2;                                         \
+                                                                       \
+  /* First, a couple of helper routines to decode instructions.  */    \
+  struct _decode                                                       \
+    {                                                                  \
+      /* Decode RR instruction format.  */                             \
+      static inline int _is_rr (unsigned char *_eip,                   \
+                               unsigned char _op,                      \
+                               int *_r1, int *_r2)                     \
+      {                                                                        \
+       if (_eip[0] == _op)                                             \
+         {                                                             \
+           *_r1 = _eip[1] >> 4;                                        \
+           *_r2 = _eip[1] & 0xf;                                       \
+           return 1;                                                   \
+         }                                                             \
+       return 0;                                                       \
+      }                                                                        \
+                                                                       \
+      /* Decode RX instruction format.  */                             \
+      static inline int _is_rx (unsigned char *_eip,                   \
+                               unsigned char _op,                      \
+                               int *_r1, int *_d2, int *_x2, int *_b2) \
+      {                                                                        \
+       if (_eip[0] == _op)                                             \
+         {                                                             \
+           *_r1 = _eip[1] >> 4;                                        \
+           *_x2 = _eip[1] & 0xf;                                       \
+           *_b2 = _eip[2] >> 4;                                        \
+           *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3];                    \
+           return 1;                                                   \
+         }                                                             \
+       return 0;                                                       \
+      }                                                                        \
+                                                                       \
+      /* Decode RRE instruction format.  */                            \
+      static inline int _is_rre (unsigned char *_eip,                  \
+                                unsigned char _op1, unsigned char _op2,\
+                                int *_r1, int *_r2)                    \
+      {                                                                        \
+       if (_eip[0] == _op1 && _eip[1] == _op2)                         \
+         {                                                             \
+           *_r1 = _eip[3] >> 4;                                        \
+           *_r2 = _eip[3] & 0xf;                                       \
+           return 1;                                                   \
+         }                                                             \
+       return 0;                                                       \
+      }                                                                        \
+                                                                       \
+      /* Decode RXY instruction format.  */                            \
+      static inline int _is_rxy (unsigned char *_eip,                  \
+                                unsigned char _op1, unsigned char _op2,\
+                                int *_r1, int *_d2, int *_x2, int *_b2)\
+      {                                                                        \
+       if (_eip[0] == _op1 && _eip[5] == _op2)                         \
+         {                                                             \
+           *_r1 = _eip[1] >> 4;                                        \
+           *_x2 = _eip[1] & 0xf;                                       \
+           *_b2 = _eip[2] >> 4;                                        \
+           *_d2 = ((_eip[2] & 0xf) << 8) + _eip[3] + (_eip[4] << 12);  \
+           /* We have a 20-bit signed displacement.  */                \
+           *_d2 = (*_d2 ^ 0x80000) - 0x80000;                          \
+           return 1;                                                   \
+         }                                                             \
+       return 0;                                                       \
+      }                                                                        \
+                                                                       \
+      /* Compute effective address.  */                                        \
+      static inline unsigned long _eff (unsigned long *_regs,          \
+                                       long _d, int _x, int _b)        \
+      {                                                                        \
+       return _d + (_x? _regs[_x] : 0) + (_b? _regs[_b] : 0);          \
+      }                                                                        \
+    };                                                                 \
+                                                                       \
+                                                                       \
+  /* DR r1,r2 */                                                       \
+  if (_decode::_is_rr (_eip, 0x1d, &_r1, &_r2)                         \
+      && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN       \
+      && (int) _regs[_r2] == -1)                                       \
+    {                                                                  \
+      _regs[_r1] &= ~0xffffffff;                                       \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+  /* D r1,d2(x2,b2) */                                                 \
+  if (_decode::_is_rx (_eip, 0x5d, &_r1, &_d2, &_x2, &_b2)             \
+      && (int) _regs[_r1] == -1 && (int) _regs[_r1+1] == INT_MIN       \
+      && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1)          \
+    {                                                                  \
+      _regs[_r1] &= ~0xffffffff;                                       \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+  /* DSGR r1,r2 */                                                     \
+  if (_decode::_is_rre (_eip, 0xb9, 0x0d, &_r1, &_r2)                  \
+      && (long) _regs[_r1+1] == LONG_MIN                               \
+      && (long) _regs[_r2] == -1L)                                     \
+    {                                                                  \
+      _regs[_r1] = 0;                                                  \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+  /* DSGFR r1,r2 */                                                    \
+  if (_decode::_is_rre (_eip, 0xb9, 0x1d, &_r1, &_r2)                  \
+      && (long) _regs[_r1+1] == LONG_MIN                               \
+      && (int) _regs[_r2] == -1)                                       \
+    {                                                                  \
+      _regs[_r1] = 0;                                                  \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+  /* DSG r1,d2(x2,b2) */                                               \
+  if (_decode::_is_rxy (_eip, 0xe3, 0x0d, &_r1, &_d2, &_x2, &_b2)      \
+      && (long) _regs[_r1+1] == LONG_MIN                               \
+      && *(long *) _decode::_eff (_regs, _d2, _x2, _b2) == -1L)                \
+    {                                                                  \
+      _regs[_r1] = 0;                                                  \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+  /* DSGF r1,d2(x2,b2) */                                              \
+  if (_decode::_is_rxy (_eip, 0xe3, 0x1d, &_r1, &_d2, &_x2, &_b2)      \
+      && (long) _regs[_r1+1] == LONG_MIN                               \
+      && *(int *) _decode::_eff (_regs, _d2, _x2, _b2) == -1)          \
+    {                                                                  \
+      _regs[_r1] = 0;                                                  \
+      return;                                                          \
+    }                                                                  \
+                                                                       \
+}                                                                      \
+while (0)
+
 /* For an explanation why we cannot simply use sigaction to
    install the handlers, see i386-signal.h.  */
 
@@ -36,7 +188,7 @@ static void _name (int, siginfo_t *, void *)
    visible to us in a header file so we define it here.  */
 
 struct old_s390_kernel_sigaction {
-       void (*k_sa_handler) (int, siginfo_t *, void *);
+       void (*k_sa_handler) (int, siginfo_t *, ucontext_t *);
        unsigned long k_sa_mask;
        unsigned long k_sa_flags;
        void (*sa_restorer) (void);