OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [include/] [i386-signal.h] - Blame information for rev 757

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 757 jeremybenn
// i386-signal.h - Catch runtime signals and turn them into exceptions
2
// on an i386 based Linux system.
3
 
4
/* Copyright (C) 1998, 1999, 2001, 2002, 2006, 2007, 2011
5
   Free Software Foundation
6
 
7
   This file is part of libgcj.
8
 
9
This software is copyrighted work licensed under the terms of the
10
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
11
details.  */
12
 
13
 
14
#ifdef __i386__
15
 
16
#ifndef JAVA_SIGNAL_H
17
#define JAVA_SIGNAL_H 1
18
 
19
#include <signal.h>
20
#include <sys/syscall.h>
21
 
22
#define HANDLE_SEGV 1
23
#define HANDLE_FPE 1
24
 
25
#define SIGNAL_HANDLER(_name)                                   \
26
static void _Jv_##_name (int, siginfo_t *,                      \
27
                         void *_p __attribute__ ((__unused__)))
28
 
29
#define HANDLE_DIVIDE_OVERFLOW                                          \
30
do                                                                      \
31
{                                                                       \
32
  struct ucontext *_uc = (struct ucontext *)_p;                         \
33
  gregset_t &_gregs = _uc->uc_mcontext.gregs;                           \
34
  unsigned char *_eip = (unsigned char *)_gregs[REG_EIP];               \
35
                                                                        \
36
  /* According to the JVM spec, "if the dividend is the negative        \
37
   * integer of largest possible magnitude for the type and the         \
38
   * divisor is -1, then overflow occurs and the result is equal to     \
39
   * the dividend.  Despite the overflow, no exception occurs".         \
40
                                                                        \
41
   * We handle this by inspecting the instruction which generated the   \
42
   * signal and advancing ip to point to the following instruction.     \
43
   * As the instructions are variable length it is necessary to do a    \
44
   * little calculation to figure out where the following instruction   \
45
   * actually is.                                                       \
46
                                                                        \
47
  */                                                                    \
48
                                                                        \
49
  /* Detect a signed division of Integer.MIN_VALUE.  */                 \
50
  if (_eip[0] == 0xf7)                                                   \
51
    {                                                                   \
52
      bool _min_value_dividend = false;                                 \
53
      unsigned char _modrm = _eip[1];                                   \
54
                                                                        \
55
      if (((_modrm >> 3) & 7) == 7) /* Signed divide */                 \
56
        {                                                               \
57
          _min_value_dividend =                                         \
58
            _gregs[REG_EAX] == (greg_t)0x80000000UL;                    \
59
        }                                                               \
60
                                                                        \
61
      if (_min_value_dividend)                                          \
62
        {                                                               \
63
          unsigned char _rm = _modrm & 7;                               \
64
          _gregs[REG_EDX] = 0; /* the remainder is zero */               \
65
          switch (_modrm >> 6)                                          \
66
            {                                                           \
67
            case 0:  /* register indirect */                             \
68
              if (_rm == 5)   /* 32-bit displacement */                 \
69
                _eip += 4;                                              \
70
              if (_rm == 4)  /* A SIB byte follows the ModR/M byte */   \
71
                _eip += 1;                                              \
72
              break;                                                    \
73
            case 1:  /* register indirect + 8-bit displacement */       \
74
              _eip += 1;                                                \
75
              if (_rm == 4)  /* A SIB byte follows the ModR/M byte */   \
76
                _eip += 1;                                              \
77
              break;                                                    \
78
            case 2:  /* register indirect + 32-bit displacement */      \
79
              _eip += 4;                                                \
80
              if (_rm == 4)  /* A SIB byte follows the ModR/M byte */   \
81
                _eip += 1;                                              \
82
              break;                                                    \
83
            case 3:                                                     \
84
              break;                                                    \
85
            }                                                           \
86
          _eip += 2;                                                    \
87
          _gregs[REG_EIP] = (greg_t)_eip;                               \
88
          return;                                                       \
89
        }                                                               \
90
    }                                                                   \
91
}                                                                       \
92
while (0)
93
 
94
/* We use kernel_sigaction here because we're calling the kernel
95
   directly rather than via glibc.  The sigaction structure that the
96
   syscall uses is a different shape from the one in userland and not
97
   visible to us in a header file so we define it here.  */
98
 
99
extern "C"
100
{
101
  struct kernel_sigaction
102
  {
103
    void (*k_sa_sigaction)(int,siginfo_t *,void *);
104
    unsigned long k_sa_flags;
105
    void (*k_sa_restorer) (void);
106
    sigset_t k_sa_mask;
107
  };
108
}
109
 
110
#define MAKE_THROW_FRAME(_exception)
111
 
112
#define RESTORE(name, syscall) RESTORE2 (name, syscall)
113
#define RESTORE2(name, syscall)                 \
114
asm                                             \
115
  (                                             \
116
   ".text\n"                                    \
117
   ".byte 0  # Yes, this really is necessary\n" \
118
   "    .align 16\n"                            \
119
   "__" #name ":\n"                             \
120
   "    movl $" #syscall ", %eax\n"             \
121
   "    int  $0x80"                             \
122
   );
123
 
124
/* The return code for realtime-signals.  */
125
RESTORE (restore_rt, __NR_rt_sigreturn)
126
void restore_rt (void) asm ("__restore_rt")
127
  __attribute__ ((visibility ("hidden")));
128
 
129
#define INIT_SEGV                                               \
130
do                                                              \
131
  {                                                             \
132
    struct kernel_sigaction act;                                \
133
    act.k_sa_sigaction = _Jv_catch_segv;                        \
134
    sigemptyset (&act.k_sa_mask);                               \
135
    act.k_sa_flags = SA_SIGINFO|0x4000000;                      \
136
    act.k_sa_restorer = restore_rt;                             \
137
    syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL, _NSIG / 8); \
138
  }                                                             \
139
while (0)
140
 
141
#define INIT_FPE                                                \
142
do                                                              \
143
  {                                                             \
144
    struct kernel_sigaction act;                                \
145
    act.k_sa_sigaction = _Jv_catch_fpe;                         \
146
    sigemptyset (&act.k_sa_mask);                               \
147
    act.k_sa_flags = SA_SIGINFO|0x4000000;                      \
148
    act.k_sa_restorer = restore_rt;                             \
149
    syscall (SYS_rt_sigaction, SIGFPE, &act, NULL, _NSIG / 8);  \
150
  }                                                             \
151
while (0)
152
 
153
/* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
154
 * instead of the standard sigaction().  This is necessary because of
155
 * the shenanigans above where we increment the PC saved in the
156
 * context and then return.  This trick will only work when we are
157
 * called _directly_ by the kernel, because linuxthreads wraps signal
158
 * handlers and its wrappers do not copy the sigcontext struct back
159
 * when returning from a signal handler.  If we return from our divide
160
 * handler to a linuxthreads wrapper, we will lose the PC adjustment
161
 * we made and return to the faulting instruction again.  Using
162
 * syscall(SYS_sigaction) causes our handler to be called directly
163
 * by the kernel, bypassing any wrappers.
164
 
165
 * Also, there may not be any unwind info in the linuxthreads
166
 * library's signal handlers and so we can't unwind through them
167
 * anyway.  */
168
 
169
#endif /* JAVA_SIGNAL_H */
170
 
171
#else /* __i386__ */
172
 
173
/* This is for the 64-bit subsystem on i386.  */
174
 
175
#define sigcontext_struct sigcontext
176
#include <java-signal-aux.h>
177
 
178
#endif /* __i386__ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.