Statistics
| Branch: | Revision:

root / user-exec.c @ c2162a8b

History | View | Annotate | Download (19.3 kB)

1
/*
2
 *  User emulator execution
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "config.h"
20
#include "cpu.h"
21
#include "dyngen-exec.h"
22
#include "disas.h"
23
#include "tcg.h"
24

    
25
#undef EAX
26
#undef ECX
27
#undef EDX
28
#undef EBX
29
#undef ESP
30
#undef EBP
31
#undef ESI
32
#undef EDI
33
#undef EIP
34
#include <signal.h>
35
#ifdef __linux__
36
#include <sys/ucontext.h>
37
#endif
38

    
39
//#define DEBUG_SIGNAL
40

    
41
static void exception_action(CPUState *env1)
42
{
43
#if defined(TARGET_I386)
44
    raise_exception_err_env(env1, env1->exception_index, env1->error_code);
45
#else
46
    cpu_loop_exit(env1);
47
#endif
48
}
49

    
50
/* exit the current TB from a signal handler. The host registers are
51
   restored in a state compatible with the CPU emulator
52
 */
53
void cpu_resume_from_signal(CPUState *env1, void *puc)
54
{
55
#ifdef __linux__
56
    struct ucontext *uc = puc;
57
#elif defined(__OpenBSD__)
58
    struct sigcontext *uc = puc;
59
#endif
60

    
61
    env = env1;
62

    
63
    /* XXX: restore cpu registers saved in host registers */
64

    
65
    if (puc) {
66
        /* XXX: use siglongjmp ? */
67
#ifdef __linux__
68
#ifdef __ia64
69
        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
70
#else
71
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
72
#endif
73
#elif defined(__OpenBSD__)
74
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
75
#endif
76
    }
77
    env->exception_index = -1;
78
    longjmp(env->jmp_env, 1);
79
}
80

    
81
/* 'pc' is the host PC at which the exception was raised. 'address' is
82
   the effective address of the memory exception. 'is_write' is 1 if a
83
   write caused the exception and otherwise 0'. 'old_set' is the
84
   signal set which should be restored */
85
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
86
                                    int is_write, sigset_t *old_set,
87
                                    void *puc)
88
{
89
    TranslationBlock *tb;
90
    int ret;
91

    
92
    if (cpu_single_env) {
93
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
94
    }
95
#if defined(DEBUG_SIGNAL)
96
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
97
                pc, address, is_write, *(unsigned long *)old_set);
98
#endif
99
    /* XXX: locking issue */
100
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
101
        return 1;
102
    }
103

    
104
    /* see if it is an MMU fault */
105
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
106
    if (ret < 0) {
107
        return 0; /* not an MMU fault */
108
    }
109
    if (ret == 0) {
110
        return 1; /* the MMU fault was handled without causing real CPU fault */
111
    }
112
    /* now we have a real cpu fault */
113
    tb = tb_find_pc(pc);
114
    if (tb) {
115
        /* the PC is inside the translated code. It means that we have
116
           a virtual CPU fault */
117
        cpu_restore_state(tb, env, pc);
118
    }
119

    
120
    /* we restore the process signal mask as the sigreturn should
121
       do it (XXX: use sigsetjmp) */
122
    sigprocmask(SIG_SETMASK, old_set, NULL);
123
    exception_action(env);
124

    
125
    /* never comes here */
126
    return 1;
127
}
128

    
129
#if defined(__i386__)
130

    
131
#if defined(__APPLE__)
132
#include <sys/ucontext.h>
133

    
134
#define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
135
#define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
136
#define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
137
#define MASK_sig(context)    ((context)->uc_sigmask)
138
#elif defined(__NetBSD__)
139
#include <ucontext.h>
140

    
141
#define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
142
#define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
143
#define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
144
#define MASK_sig(context)    ((context)->uc_sigmask)
145
#elif defined(__FreeBSD__) || defined(__DragonFly__)
146
#include <ucontext.h>
147

    
148
#define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
149
#define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
150
#define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
151
#define MASK_sig(context)    ((context)->uc_sigmask)
152
#elif defined(__OpenBSD__)
153
#define EIP_sig(context)     ((context)->sc_eip)
154
#define TRAP_sig(context)    ((context)->sc_trapno)
155
#define ERROR_sig(context)   ((context)->sc_err)
156
#define MASK_sig(context)    ((context)->sc_mask)
157
#else
158
#define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
159
#define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
160
#define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
161
#define MASK_sig(context)    ((context)->uc_sigmask)
162
#endif
163

    
164
int cpu_signal_handler(int host_signum, void *pinfo,
165
                       void *puc)
166
{
167
    siginfo_t *info = pinfo;
168
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
169
    ucontext_t *uc = puc;
170
#elif defined(__OpenBSD__)
171
    struct sigcontext *uc = puc;
172
#else
173
    struct ucontext *uc = puc;
174
#endif
175
    unsigned long pc;
176
    int trapno;
177

    
178
#ifndef REG_EIP
179
/* for glibc 2.1 */
180
#define REG_EIP    EIP
181
#define REG_ERR    ERR
182
#define REG_TRAPNO TRAPNO
183
#endif
184
    pc = EIP_sig(uc);
185
    trapno = TRAP_sig(uc);
186
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
187
                             trapno == 0xe ?
188
                             (ERROR_sig(uc) >> 1) & 1 : 0,
189
                             &MASK_sig(uc), puc);
190
}
191

    
192
#elif defined(__x86_64__)
193

    
194
#ifdef __NetBSD__
195
#define PC_sig(context)       _UC_MACHINE_PC(context)
196
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
197
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
198
#define MASK_sig(context)     ((context)->uc_sigmask)
199
#elif defined(__OpenBSD__)
200
#define PC_sig(context)       ((context)->sc_rip)
201
#define TRAP_sig(context)     ((context)->sc_trapno)
202
#define ERROR_sig(context)    ((context)->sc_err)
203
#define MASK_sig(context)     ((context)->sc_mask)
204
#elif defined(__FreeBSD__) || defined(__DragonFly__)
205
#include <ucontext.h>
206

    
207
#define PC_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
208
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
209
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
210
#define MASK_sig(context)     ((context)->uc_sigmask)
211
#else
212
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
213
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
214
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
215
#define MASK_sig(context)     ((context)->uc_sigmask)
216
#endif
217

    
218
int cpu_signal_handler(int host_signum, void *pinfo,
219
                       void *puc)
220
{
221
    siginfo_t *info = pinfo;
222
    unsigned long pc;
223
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
224
    ucontext_t *uc = puc;
225
#elif defined(__OpenBSD__)
226
    struct sigcontext *uc = puc;
227
#else
228
    struct ucontext *uc = puc;
229
#endif
230

    
231
    pc = PC_sig(uc);
232
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
233
                             TRAP_sig(uc) == 0xe ?
234
                             (ERROR_sig(uc) >> 1) & 1 : 0,
235
                             &MASK_sig(uc), puc);
236
}
237

    
238
#elif defined(_ARCH_PPC)
239

    
240
/***********************************************************************
241
 * signal context platform-specific definitions
242
 * From Wine
243
 */
244
#ifdef linux
245
/* All Registers access - only for local access */
246
#define REG_sig(reg_name, context)              \
247
    ((context)->uc_mcontext.regs->reg_name)
248
/* Gpr Registers access  */
249
#define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
250
/* Program counter */
251
#define IAR_sig(context)                       REG_sig(nip, context)
252
/* Machine State Register (Supervisor) */
253
#define MSR_sig(context)                       REG_sig(msr, context)
254
/* Count register */
255
#define CTR_sig(context)                       REG_sig(ctr, context)
256
/* User's integer exception register */
257
#define XER_sig(context)                       REG_sig(xer, context)
258
/* Link register */
259
#define LR_sig(context)                        REG_sig(link, context)
260
/* Condition register */
261
#define CR_sig(context)                        REG_sig(ccr, context)
262

    
263
/* Float Registers access  */
264
#define FLOAT_sig(reg_num, context)                                     \
265
    (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
266
#define FPSCR_sig(context) \
267
    (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
268
/* Exception Registers access */
269
#define DAR_sig(context)                       REG_sig(dar, context)
270
#define DSISR_sig(context)                     REG_sig(dsisr, context)
271
#define TRAP_sig(context)                      REG_sig(trap, context)
272
#endif /* linux */
273

    
274
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
275
#include <ucontext.h>
276
#define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
277
#define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
278
#define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
279
#define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
280
#define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
281
#define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
282
/* Exception Registers access */
283
#define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
284
#define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
285
#define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
286
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
287

    
288
#ifdef __APPLE__
289
#include <sys/ucontext.h>
290
typedef struct ucontext SIGCONTEXT;
291
/* All Registers access - only for local access */
292
#define REG_sig(reg_name, context)              \
293
    ((context)->uc_mcontext->ss.reg_name)
294
#define FLOATREG_sig(reg_name, context)         \
295
    ((context)->uc_mcontext->fs.reg_name)
296
#define EXCEPREG_sig(reg_name, context)         \
297
    ((context)->uc_mcontext->es.reg_name)
298
#define VECREG_sig(reg_name, context)           \
299
    ((context)->uc_mcontext->vs.reg_name)
300
/* Gpr Registers access */
301
#define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
302
/* Program counter */
303
#define IAR_sig(context)                       REG_sig(srr0, context)
304
/* Machine State Register (Supervisor) */
305
#define MSR_sig(context)                       REG_sig(srr1, context)
306
#define CTR_sig(context)                       REG_sig(ctr, context)
307
/* Link register */
308
#define XER_sig(context)                       REG_sig(xer, context)
309
/* User's integer exception register */
310
#define LR_sig(context)                        REG_sig(lr, context)
311
/* Condition register */
312
#define CR_sig(context)                        REG_sig(cr, context)
313
/* Float Registers access */
314
#define FLOAT_sig(reg_num, context)             \
315
    FLOATREG_sig(fpregs[reg_num], context)
316
#define FPSCR_sig(context)                      \
317
    ((double)FLOATREG_sig(fpscr, context))
318
/* Exception Registers access */
319
/* Fault registers for coredump */
320
#define DAR_sig(context)                       EXCEPREG_sig(dar, context)
321
#define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
322
/* number of powerpc exception taken */
323
#define TRAP_sig(context)                      EXCEPREG_sig(exception, context)
324
#endif /* __APPLE__ */
325

    
326
int cpu_signal_handler(int host_signum, void *pinfo,
327
                       void *puc)
328
{
329
    siginfo_t *info = pinfo;
330
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
331
    ucontext_t *uc = puc;
332
#else
333
    struct ucontext *uc = puc;
334
#endif
335
    unsigned long pc;
336
    int is_write;
337

    
338
    pc = IAR_sig(uc);
339
    is_write = 0;
340
#if 0
341
    /* ppc 4xx case */
342
    if (DSISR_sig(uc) & 0x00800000) {
343
        is_write = 1;
344
    }
345
#else
346
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
347
        is_write = 1;
348
    }
349
#endif
350
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
351
                             is_write, &uc->uc_sigmask, puc);
352
}
353

    
354
#elif defined(__alpha__)
355

    
356
int cpu_signal_handler(int host_signum, void *pinfo,
357
                           void *puc)
358
{
359
    siginfo_t *info = pinfo;
360
    struct ucontext *uc = puc;
361
    uint32_t *pc = uc->uc_mcontext.sc_pc;
362
    uint32_t insn = *pc;
363
    int is_write = 0;
364

    
365
    /* XXX: need kernel patch to get write flag faster */
366
    switch (insn >> 26) {
367
    case 0x0d: /* stw */
368
    case 0x0e: /* stb */
369
    case 0x0f: /* stq_u */
370
    case 0x24: /* stf */
371
    case 0x25: /* stg */
372
    case 0x26: /* sts */
373
    case 0x27: /* stt */
374
    case 0x2c: /* stl */
375
    case 0x2d: /* stq */
376
    case 0x2e: /* stl_c */
377
    case 0x2f: /* stq_c */
378
        is_write = 1;
379
    }
380

    
381
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
382
                             is_write, &uc->uc_sigmask, puc);
383
}
384
#elif defined(__sparc__)
385

    
386
int cpu_signal_handler(int host_signum, void *pinfo,
387
                       void *puc)
388
{
389
    siginfo_t *info = pinfo;
390
    int is_write;
391
    uint32_t insn;
392
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
393
    uint32_t *regs = (uint32_t *)(info + 1);
394
    void *sigmask = (regs + 20);
395
    /* XXX: is there a standard glibc define ? */
396
    unsigned long pc = regs[1];
397
#else
398
#ifdef __linux__
399
    struct sigcontext *sc = puc;
400
    unsigned long pc = sc->sigc_regs.tpc;
401
    void *sigmask = (void *)sc->sigc_mask;
402
#elif defined(__OpenBSD__)
403
    struct sigcontext *uc = puc;
404
    unsigned long pc = uc->sc_pc;
405
    void *sigmask = (void *)(long)uc->sc_mask;
406
#endif
407
#endif
408

    
409
    /* XXX: need kernel patch to get write flag faster */
410
    is_write = 0;
411
    insn = *(uint32_t *)pc;
412
    if ((insn >> 30) == 3) {
413
        switch ((insn >> 19) & 0x3f) {
414
        case 0x05: /* stb */
415
        case 0x15: /* stba */
416
        case 0x06: /* sth */
417
        case 0x16: /* stha */
418
        case 0x04: /* st */
419
        case 0x14: /* sta */
420
        case 0x07: /* std */
421
        case 0x17: /* stda */
422
        case 0x0e: /* stx */
423
        case 0x1e: /* stxa */
424
        case 0x24: /* stf */
425
        case 0x34: /* stfa */
426
        case 0x27: /* stdf */
427
        case 0x37: /* stdfa */
428
        case 0x26: /* stqf */
429
        case 0x36: /* stqfa */
430
        case 0x25: /* stfsr */
431
        case 0x3c: /* casa */
432
        case 0x3e: /* casxa */
433
            is_write = 1;
434
            break;
435
        }
436
    }
437
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
438
                             is_write, sigmask, NULL);
439
}
440

    
441
#elif defined(__arm__)
442

    
443
int cpu_signal_handler(int host_signum, void *pinfo,
444
                       void *puc)
445
{
446
    siginfo_t *info = pinfo;
447
    struct ucontext *uc = puc;
448
    unsigned long pc;
449
    int is_write;
450

    
451
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
452
    pc = uc->uc_mcontext.gregs[R15];
453
#else
454
    pc = uc->uc_mcontext.arm_pc;
455
#endif
456
    /* XXX: compute is_write */
457
    is_write = 0;
458
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
459
                             is_write,
460
                             &uc->uc_sigmask, puc);
461
}
462

    
463
#elif defined(__mc68000)
464

    
465
int cpu_signal_handler(int host_signum, void *pinfo,
466
                       void *puc)
467
{
468
    siginfo_t *info = pinfo;
469
    struct ucontext *uc = puc;
470
    unsigned long pc;
471
    int is_write;
472

    
473
    pc = uc->uc_mcontext.gregs[16];
474
    /* XXX: compute is_write */
475
    is_write = 0;
476
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
477
                             is_write,
478
                             &uc->uc_sigmask, puc);
479
}
480

    
481
#elif defined(__ia64)
482

    
483
#ifndef __ISR_VALID
484
  /* This ought to be in <bits/siginfo.h>... */
485
# define __ISR_VALID    1
486
#endif
487

    
488
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
489
{
490
    siginfo_t *info = pinfo;
491
    struct ucontext *uc = puc;
492
    unsigned long ip;
493
    int is_write = 0;
494

    
495
    ip = uc->uc_mcontext.sc_ip;
496
    switch (host_signum) {
497
    case SIGILL:
498
    case SIGFPE:
499
    case SIGSEGV:
500
    case SIGBUS:
501
    case SIGTRAP:
502
        if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
503
            /* ISR.W (write-access) is bit 33:  */
504
            is_write = (info->si_isr >> 33) & 1;
505
        }
506
        break;
507

    
508
    default:
509
        break;
510
    }
511
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
512
                             is_write,
513
                             (sigset_t *)&uc->uc_sigmask, puc);
514
}
515

    
516
#elif defined(__s390__)
517

    
518
int cpu_signal_handler(int host_signum, void *pinfo,
519
                       void *puc)
520
{
521
    siginfo_t *info = pinfo;
522
    struct ucontext *uc = puc;
523
    unsigned long pc;
524
    uint16_t *pinsn;
525
    int is_write = 0;
526

    
527
    pc = uc->uc_mcontext.psw.addr;
528

    
529
    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
530
       of the normal 2 arguments.  The 3rd argument contains the "int_code"
531
       from the hardware which does in fact contain the is_write value.
532
       The rt signal handler, as far as I can tell, does not give this value
533
       at all.  Not that we could get to it from here even if it were.  */
534
    /* ??? This is not even close to complete, since it ignores all
535
       of the read-modify-write instructions.  */
536
    pinsn = (uint16_t *)pc;
537
    switch (pinsn[0] >> 8) {
538
    case 0x50: /* ST */
539
    case 0x42: /* STC */
540
    case 0x40: /* STH */
541
        is_write = 1;
542
        break;
543
    case 0xc4: /* RIL format insns */
544
        switch (pinsn[0] & 0xf) {
545
        case 0xf: /* STRL */
546
        case 0xb: /* STGRL */
547
        case 0x7: /* STHRL */
548
            is_write = 1;
549
        }
550
        break;
551
    case 0xe3: /* RXY format insns */
552
        switch (pinsn[2] & 0xff) {
553
        case 0x50: /* STY */
554
        case 0x24: /* STG */
555
        case 0x72: /* STCY */
556
        case 0x70: /* STHY */
557
        case 0x8e: /* STPQ */
558
        case 0x3f: /* STRVH */
559
        case 0x3e: /* STRV */
560
        case 0x2f: /* STRVG */
561
            is_write = 1;
562
        }
563
        break;
564
    }
565
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
566
                             is_write, &uc->uc_sigmask, puc);
567
}
568

    
569
#elif defined(__mips__)
570

    
571
int cpu_signal_handler(int host_signum, void *pinfo,
572
                       void *puc)
573
{
574
    siginfo_t *info = pinfo;
575
    struct ucontext *uc = puc;
576
    greg_t pc = uc->uc_mcontext.pc;
577
    int is_write;
578

    
579
    /* XXX: compute is_write */
580
    is_write = 0;
581
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
582
                             is_write, &uc->uc_sigmask, puc);
583
}
584

    
585
#elif defined(__hppa__)
586

    
587
int cpu_signal_handler(int host_signum, void *pinfo,
588
                       void *puc)
589
{
590
    struct siginfo *info = pinfo;
591
    struct ucontext *uc = puc;
592
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
593
    uint32_t insn = *(uint32_t *)pc;
594
    int is_write = 0;
595

    
596
    /* XXX: need kernel patch to get write flag faster.  */
597
    switch (insn >> 26) {
598
    case 0x1a: /* STW */
599
    case 0x19: /* STH */
600
    case 0x18: /* STB */
601
    case 0x1b: /* STWM */
602
        is_write = 1;
603
        break;
604

    
605
    case 0x09: /* CSTWX, FSTWX, FSTWS */
606
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
607
        /* Distinguish from coprocessor load ... */
608
        is_write = (insn >> 9) & 1;
609
        break;
610

    
611
    case 0x03:
612
        switch ((insn >> 6) & 15) {
613
        case 0xa: /* STWS */
614
        case 0x9: /* STHS */
615
        case 0x8: /* STBS */
616
        case 0xe: /* STWAS */
617
        case 0xc: /* STBYS */
618
            is_write = 1;
619
        }
620
        break;
621
    }
622

    
623
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
624
                             is_write, &uc->uc_sigmask, puc);
625
}
626

    
627
#else
628

    
629
#error host CPU specific signal handler needed
630

    
631
#endif