mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
![Matt Waddel](/assets/img/avatar_default.png)
Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Matt Waddel <Matt.Waddel@freescale.com> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
185 lines
4.6 KiB
ArmAsm
185 lines
4.6 KiB
ArmAsm
|
|
|
| x_ovfl.sa 3.5 7/1/91
|
|
|
|
|
| fpsp_ovfl --- FPSP handler for overflow exception
|
|
|
|
|
| Overflow occurs when a floating-point intermediate result is
|
|
| too large to be represented in a floating-point data register,
|
|
| or when storing to memory, the contents of a floating-point
|
|
| data register are too large to be represented in the
|
|
| destination format.
|
|
|
|
|
| Trap disabled results
|
|
|
|
|
| If the instruction is move_out, then garbage is stored in the
|
|
| destination. If the instruction is not move_out, then the
|
|
| destination is not affected. For 68881 compatibility, the
|
|
| following values should be stored at the destination, based
|
|
| on the current rounding mode:
|
|
|
|
|
| RN Infinity with the sign of the intermediate result.
|
|
| RZ Largest magnitude number, with the sign of the
|
|
| intermediate result.
|
|
| RM For pos overflow, the largest pos number. For neg overflow,
|
|
| -infinity
|
|
| RP For pos overflow, +infinity. For neg overflow, the largest
|
|
| neg number
|
|
|
|
|
| Trap enabled results
|
|
| All trap disabled code applies. In addition the exceptional
|
|
| operand needs to be made available to the users exception handler
|
|
| with a bias of $6000 subtracted from the exponent.
|
|
|
|
|
|
|
|
|
|
| Copyright (C) Motorola, Inc. 1990
|
|
| All Rights Reserved
|
|
|
|
|
| For details on the license for this file, please see the
|
|
| file, README, in this same directory.
|
|
|
|
X_OVFL: |idnt 2,1 | Motorola 040 Floating Point Software Package
|
|
|
|
|section 8
|
|
|
|
#include "fpsp.h"
|
|
|
|
|xref ovf_r_x2
|
|
|xref ovf_r_x3
|
|
|xref store
|
|
|xref real_ovfl
|
|
|xref real_inex
|
|
|xref fpsp_done
|
|
|xref g_opcls
|
|
|xref b1238_fix
|
|
|
|
.global fpsp_ovfl
|
|
fpsp_ovfl:
|
|
link %a6,#-LOCAL_SIZE
|
|
fsave -(%a7)
|
|
moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
|
|
fmovemx %fp0-%fp3,USER_FP0(%a6)
|
|
fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
|
|
|
|
|
|
|
| The 040 doesn't set the AINEX bit in the FPSR, the following
|
|
| line temporarily rectifies this error.
|
|
|
|
|
bsetb #ainex_bit,FPSR_AEXCEPT(%a6)
|
|
|
|
|
bsrl ovf_adj |denormalize, round & store interm op
|
|
|
|
|
| if overflow traps not enabled check for inexact exception
|
|
|
|
|
btstb #ovfl_bit,FPCR_ENABLE(%a6)
|
|
beqs ck_inex
|
|
|
|
|
btstb #E3,E_BYTE(%a6)
|
|
beqs no_e3_1
|
|
bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
|
|
bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
|
|
bsrl b1238_fix
|
|
movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
|
|
orl #sx_mask,E_BYTE(%a6)
|
|
no_e3_1:
|
|
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
|
|
fmovemx USER_FP0(%a6),%fp0-%fp3
|
|
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
|
|
frestore (%a7)+
|
|
unlk %a6
|
|
bral real_ovfl
|
|
|
|
|
| It is possible to have either inex2 or inex1 exceptions with the
|
|
| ovfl. If the inex enable bit is set in the FPCR, and either
|
|
| inex2 or inex1 occurred, we must clean up and branch to the
|
|
| real inex handler.
|
|
|
|
|
ck_inex:
|
|
| move.b FPCR_ENABLE(%a6),%d0
|
|
| and.b FPSR_EXCEPT(%a6),%d0
|
|
| andi.b #$3,%d0
|
|
btstb #inex2_bit,FPCR_ENABLE(%a6)
|
|
beqs ovfl_exit
|
|
|
|
|
| Inexact enabled and reported, and we must take an inexact exception.
|
|
|
|
|
take_inex:
|
|
btstb #E3,E_BYTE(%a6)
|
|
beqs no_e3_2
|
|
bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
|
|
bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
|
|
bsrl b1238_fix
|
|
movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
|
|
orl #sx_mask,E_BYTE(%a6)
|
|
no_e3_2:
|
|
moveb #INEX_VEC,EXC_VEC+1(%a6)
|
|
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
|
|
fmovemx USER_FP0(%a6),%fp0-%fp3
|
|
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
|
|
frestore (%a7)+
|
|
unlk %a6
|
|
bral real_inex
|
|
|
|
ovfl_exit:
|
|
bclrb #E3,E_BYTE(%a6) |test and clear E3 bit
|
|
beqs e1_set
|
|
|
|
|
| Clear dirty bit on dest resister in the frame before branching
|
|
| to b1238_fix.
|
|
|
|
|
bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no
|
|
bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
|
|
bsrl b1238_fix |test for bug1238 case
|
|
|
|
movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
|
|
orl #sx_mask,E_BYTE(%a6)
|
|
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
|
|
fmovemx USER_FP0(%a6),%fp0-%fp3
|
|
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
|
|
frestore (%a7)+
|
|
unlk %a6
|
|
bral fpsp_done
|
|
e1_set:
|
|
moveml USER_DA(%a6),%d0-%d1/%a0-%a1
|
|
fmovemx USER_FP0(%a6),%fp0-%fp3
|
|
fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
|
|
unlk %a6
|
|
bral fpsp_done
|
|
|
|
|
|
|
| ovf_adj
|
|
|
|
|
ovf_adj:
|
|
|
|
|
| Have a0 point to the correct operand.
|
|
|
|
|
btstb #E3,E_BYTE(%a6) |test E3 bit
|
|
beqs ovf_e1
|
|
|
|
lea WBTEMP(%a6),%a0
|
|
bras ovf_com
|
|
ovf_e1:
|
|
lea ETEMP(%a6),%a0
|
|
|
|
ovf_com:
|
|
bclrb #sign_bit,LOCAL_EX(%a0)
|
|
sne LOCAL_SGN(%a0)
|
|
|
|
bsrl g_opcls |returns opclass in d0
|
|
cmpiw #3,%d0 |check for opclass3
|
|
bnes not_opc011
|
|
|
|
|
|
|
| FPSR_CC is saved and restored because ovf_r_x3 affects it. The
|
|
| CCs are defined to be 'not affected' for the opclass3 instruction.
|
|
|
|
|
moveb FPSR_CC(%a6),L_SCR1(%a6)
|
|
bsrl ovf_r_x3 |returns a0 pointing to result
|
|
moveb L_SCR1(%a6),FPSR_CC(%a6)
|
|
bral store |stores to memory or register
|
|
|
|
not_opc011:
|
|
bsrl ovf_r_x2 |returns a0 pointing to result
|
|
bral store |stores to memory or register
|
|
|
|
|end
|