Statistics
| Branch: | Revision:

root / user-exec.c @ 3627757e

History | View | Annotate | Download (19.4 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(CPUArchState *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(CPUArchState *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(uintptr_t 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 && h2g_valid(address)
101
        && page_unprotect(h2g(address), pc, puc)) {
102
        return 1;
103
    }
104

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

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

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

    
130
#if defined(__i386__)
131

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

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

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

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

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

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

    
193
#elif defined(__x86_64__)
194

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

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

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

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

    
239
#elif defined(_ARCH_PPC)
240

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

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

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

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

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

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

    
355
#elif defined(__alpha__)
356

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

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

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

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

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

    
442
#elif defined(__arm__)
443

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

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

    
464
#elif defined(__mc68000)
465

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

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

    
482
#elif defined(__ia64)
483

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

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

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

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

    
517
#elif defined(__s390__)
518

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

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

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

    
570
#elif defined(__mips__)
571

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

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

    
586
#elif defined(__hppa__)
587

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

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

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

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

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

    
628
#else
629

    
630
#error host CPU specific signal handler needed
631

    
632
#endif