Revision 6e06d515
b/linux-user/syscall.c | ||
---|---|---|
7699 | 7699 |
ret = -TARGET_EOPNOTSUPP; |
7700 | 7700 |
switch (arg1) { |
7701 | 7701 |
case TARGET_SSI_IEEE_FP_CONTROL: |
7702 |
case TARGET_SSI_IEEE_RAISE_EXCEPTION: |
|
7703 | 7702 |
{ |
7704 | 7703 |
uint64_t swcr, fpcr, orig_fpcr; |
7705 | 7704 |
|
7706 |
if (get_user_u64 (swcr, arg2)) |
|
7705 |
if (get_user_u64 (swcr, arg2)) {
|
|
7707 | 7706 |
goto efault; |
7708 |
orig_fpcr = cpu_alpha_load_fpcr (cpu_env); |
|
7707 |
} |
|
7708 |
orig_fpcr = cpu_alpha_load_fpcr(cpu_env); |
|
7709 | 7709 |
fpcr = orig_fpcr & FPCR_DYN_MASK; |
7710 | 7710 |
|
7711 | 7711 |
/* Copied from linux ieee_swcr_to_fpcr. */ |
... | ... | |
7719 | 7719 |
fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); |
7720 | 7720 |
fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41; |
7721 | 7721 |
|
7722 |
cpu_alpha_store_fpcr (cpu_env, fpcr);
|
|
7722 |
cpu_alpha_store_fpcr(cpu_env, fpcr); |
|
7723 | 7723 |
ret = 0; |
7724 |
} |
|
7725 |
break; |
|
7726 |
|
|
7727 |
case TARGET_SSI_IEEE_RAISE_EXCEPTION: |
|
7728 |
{ |
|
7729 |
uint64_t exc, fpcr, orig_fpcr; |
|
7730 |
int si_code; |
|
7731 |
|
|
7732 |
if (get_user_u64(exc, arg2)) { |
|
7733 |
goto efault; |
|
7734 |
} |
|
7724 | 7735 |
|
7725 |
if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) { |
|
7726 |
/* Old exceptions are not signaled. */ |
|
7727 |
fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); |
|
7736 |
orig_fpcr = cpu_alpha_load_fpcr(cpu_env); |
|
7728 | 7737 |
|
7729 |
/* If any exceptions set by this call, and are unmasked, |
|
7730 |
send a signal. */ |
|
7731 |
/* ??? FIXME */ |
|
7738 |
/* We only add to the exception status here. */ |
|
7739 |
fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35); |
|
7740 |
|
|
7741 |
cpu_alpha_store_fpcr(cpu_env, fpcr); |
|
7742 |
ret = 0; |
|
7743 |
|
|
7744 |
/* Old exceptions are not signaled. */ |
|
7745 |
fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); |
|
7746 |
|
|
7747 |
/* If any exceptions set by this call, |
|
7748 |
and are unmasked, send a signal. */ |
|
7749 |
si_code = 0; |
|
7750 |
if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) { |
|
7751 |
si_code = TARGET_FPE_FLTRES; |
|
7752 |
} |
|
7753 |
if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) { |
|
7754 |
si_code = TARGET_FPE_FLTUND; |
|
7755 |
} |
|
7756 |
if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) { |
|
7757 |
si_code = TARGET_FPE_FLTOVF; |
|
7758 |
} |
|
7759 |
if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) { |
|
7760 |
si_code = TARGET_FPE_FLTDIV; |
|
7761 |
} |
|
7762 |
if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) { |
|
7763 |
si_code = TARGET_FPE_FLTINV; |
|
7764 |
} |
|
7765 |
if (si_code != 0) { |
|
7766 |
target_siginfo_t info; |
|
7767 |
info.si_signo = SIGFPE; |
|
7768 |
info.si_errno = 0; |
|
7769 |
info.si_code = si_code; |
|
7770 |
info._sifields._sigfault._addr |
|
7771 |
= ((CPUArchState *)cpu_env)->pc; |
|
7772 |
queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); |
|
7732 | 7773 |
} |
7733 | 7774 |
} |
7734 | 7775 |
break; |
Also available in: Unified diff