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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [math-emu/] [reg_div.S] - Diff between revs 1623 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1623 Rev 1765
        .file   "reg_div.S"
        .file   "reg_div.S"
/*---------------------------------------------------------------------------+
/*---------------------------------------------------------------------------+
 |  reg_div.S                                                                |
 |  reg_div.S                                                                |
 |                                                                           |
 |                                                                           |
 | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
 | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
 |                                                                           |
 |                                                                           |
 | Copyright (C) 1992,1993,1994,1995                                         |
 | Copyright (C) 1992,1993,1994,1995                                         |
 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
 |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
 |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
 |                                                                           |
 |                                                                           |
 | Call from C as:                                                           |
 | Call from C as:                                                           |
 |   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                     |
 |   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                     |
 |                                    unsigned int control_word)             |
 |                                    unsigned int control_word)             |
 |                                                                           |
 |                                                                           |
 +---------------------------------------------------------------------------*/
 +---------------------------------------------------------------------------*/
#include "exception.h"
#include "exception.h"
#include "fpu_emu.h"
#include "fpu_emu.h"
.text
.text
ENTRY(reg_div)
ENTRY(reg_div)
        pushl   %ebp
        pushl   %ebp
        movl    %esp,%ebp
        movl    %esp,%ebp
#ifndef NON_REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
        subl    $28,%esp        /* Needed by divide_kernel */
        subl    $28,%esp        /* Needed by divide_kernel */
#endif NON_REENTRANT_FPU
#endif NON_REENTRANT_FPU
        pushl   %esi
        pushl   %esi
        pushl   %edi
        pushl   %edi
        pushl   %ebx
        pushl   %ebx
        movl    PARAM1,%esi
        movl    PARAM1,%esi
        movl    PARAM2,%ebx
        movl    PARAM2,%ebx
        movl    PARAM3,%edi
        movl    PARAM3,%edi
        movb    TAG(%esi),%al
        movb    TAG(%esi),%al
        orb     TAG(%ebx),%al
        orb     TAG(%ebx),%al
        jne     L_div_special           /* Not (both numbers TW_Valid) */
        jne     L_div_special           /* Not (both numbers TW_Valid) */
#ifdef DENORM_OPERAND
#ifdef DENORM_OPERAND
/* Check for denormals */
/* Check for denormals */
        cmpl    EXP_UNDER,EXP(%esi)
        cmpl    EXP_UNDER,EXP(%esi)
        jg      xL_arg1_not_denormal
        jg      xL_arg1_not_denormal
        call    SYMBOL_NAME(denormal_operand)
        call    SYMBOL_NAME(denormal_operand)
        orl     %eax,%eax
        orl     %eax,%eax
        jnz     fpu_Arith_exit
        jnz     fpu_Arith_exit
xL_arg1_not_denormal:
xL_arg1_not_denormal:
        cmpl    EXP_UNDER,EXP(%ebx)
        cmpl    EXP_UNDER,EXP(%ebx)
        jg      xL_arg2_not_denormal
        jg      xL_arg2_not_denormal
        call    SYMBOL_NAME(denormal_operand)
        call    SYMBOL_NAME(denormal_operand)
        orl     %eax,%eax
        orl     %eax,%eax
        jnz     fpu_Arith_exit
        jnz     fpu_Arith_exit
xL_arg2_not_denormal:
xL_arg2_not_denormal:
#endif DENORM_OPERAND
#endif DENORM_OPERAND
/* Both arguments are TW_Valid */
/* Both arguments are TW_Valid */
        movb    TW_Valid,TAG(%edi)
        movb    TW_Valid,TAG(%edi)
        movb    SIGN(%esi),%cl
        movb    SIGN(%esi),%cl
        cmpb    %cl,SIGN(%ebx)
        cmpb    %cl,SIGN(%ebx)
        setne   (%edi)        /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
        setne   (%edi)        /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
        movl    EXP(%esi),%edx
        movl    EXP(%esi),%edx
        movl    EXP(%ebx),%eax
        movl    EXP(%ebx),%eax
        subl    %eax,%edx
        subl    %eax,%edx
        addl    EXP_BIAS,%edx
        addl    EXP_BIAS,%edx
        movl    %edx,EXP(%edi)
        movl    %edx,EXP(%edi)
        jmp     SYMBOL_NAME(divide_kernel)
        jmp     SYMBOL_NAME(divide_kernel)
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
L_div_special:
L_div_special:
        cmpb    TW_NaN,TAG(%esi)        /* A NaN with anything to give NaN */
        cmpb    TW_NaN,TAG(%esi)        /* A NaN with anything to give NaN */
        je      L_arg1_NaN
        je      L_arg1_NaN
        cmpb    TW_NaN,TAG(%ebx)        /* A NaN with anything to give NaN */
        cmpb    TW_NaN,TAG(%ebx)        /* A NaN with anything to give NaN */
        jne     L_no_NaN_arg
        jne     L_no_NaN_arg
/* Operations on NaNs */
/* Operations on NaNs */
L_arg1_NaN:
L_arg1_NaN:
L_arg2_NaN:
L_arg2_NaN:
        pushl   %edi                    /* Destination */
        pushl   %edi                    /* Destination */
        pushl   %esi
        pushl   %esi
        pushl   %ebx                    /* Ordering is important here */
        pushl   %ebx                    /* Ordering is important here */
        call    SYMBOL_NAME(real_2op_NaN)
        call    SYMBOL_NAME(real_2op_NaN)
        jmp     LDiv_exit
        jmp     LDiv_exit
/* Invalid operations */
/* Invalid operations */
L_zero_zero:
L_zero_zero:
L_inf_inf:
L_inf_inf:
        pushl   %edi                    /* Destination */
        pushl   %edi                    /* Destination */
        call    SYMBOL_NAME(arith_invalid) /* 0/0 or Infinity/Infinity */
        call    SYMBOL_NAME(arith_invalid) /* 0/0 or Infinity/Infinity */
        jmp     LDiv_exit
        jmp     LDiv_exit
L_no_NaN_arg:
L_no_NaN_arg:
        cmpb    TW_Infinity,TAG(%esi)
        cmpb    TW_Infinity,TAG(%esi)
        jne     L_arg1_not_inf
        jne     L_arg1_not_inf
        cmpb    TW_Infinity,TAG(%ebx)
        cmpb    TW_Infinity,TAG(%ebx)
        je      L_inf_inf               /* invalid operation */
        je      L_inf_inf               /* invalid operation */
        cmpb    TW_Valid,TAG(%ebx)
        cmpb    TW_Valid,TAG(%ebx)
        je      L_inf_valid
        je      L_inf_valid
#ifdef PARANOID
#ifdef PARANOID
        /* arg2 must be zero or valid */
        /* arg2 must be zero or valid */
        cmpb    TW_Zero,TAG(%ebx)
        cmpb    TW_Zero,TAG(%ebx)
        ja      L_unknown_tags
        ja      L_unknown_tags
#endif PARANOID
#endif PARANOID
        /* Note that p16-9 says that infinity/0 returns infinity */
        /* Note that p16-9 says that infinity/0 returns infinity */
        jmp     L_copy_arg1             /* Answer is Inf */
        jmp     L_copy_arg1             /* Answer is Inf */
L_inf_valid:
L_inf_valid:
#ifdef DENORM_OPERAND
#ifdef DENORM_OPERAND
        cmpl    EXP_UNDER,EXP(%ebx)
        cmpl    EXP_UNDER,EXP(%ebx)
        jg      L_copy_arg1             /* Answer is Inf */
        jg      L_copy_arg1             /* Answer is Inf */
        call    SYMBOL_NAME(denormal_operand)
        call    SYMBOL_NAME(denormal_operand)
        orl     %eax,%eax
        orl     %eax,%eax
        jnz     fpu_Arith_exit
        jnz     fpu_Arith_exit
#endif DENORM_OPERAND
#endif DENORM_OPERAND
        jmp     L_copy_arg1             /* Answer is Inf */
        jmp     L_copy_arg1             /* Answer is Inf */
L_arg1_not_inf:
L_arg1_not_inf:
        cmpb    TW_Zero,TAG(%ebx)       /* Priority to div-by-zero error */
        cmpb    TW_Zero,TAG(%ebx)       /* Priority to div-by-zero error */
        jne     L_arg2_not_zero
        jne     L_arg2_not_zero
        cmpb    TW_Zero,TAG(%esi)
        cmpb    TW_Zero,TAG(%esi)
        je      L_zero_zero             /* invalid operation */
        je      L_zero_zero             /* invalid operation */
#ifdef PARANOID
#ifdef PARANOID
        /* arg1 must be valid */
        /* arg1 must be valid */
        cmpb    TW_Valid,TAG(%esi)
        cmpb    TW_Valid,TAG(%esi)
        ja      L_unknown_tags
        ja      L_unknown_tags
#endif PARANOID
#endif PARANOID
/* Division by zero error */
/* Division by zero error */
        pushl   %edi                    /* destination */
        pushl   %edi                    /* destination */
        movb    SIGN(%esi),%al
        movb    SIGN(%esi),%al
        xorb    SIGN(%ebx),%al
        xorb    SIGN(%ebx),%al
        pushl   %eax                    /* lower 8 bits have the sign */
        pushl   %eax                    /* lower 8 bits have the sign */
        call    SYMBOL_NAME(divide_by_zero)
        call    SYMBOL_NAME(divide_by_zero)
        jmp     LDiv_exit
        jmp     LDiv_exit
L_arg2_not_zero:
L_arg2_not_zero:
        cmpb    TW_Infinity,TAG(%ebx)
        cmpb    TW_Infinity,TAG(%ebx)
        jne     L_arg2_not_inf
        jne     L_arg2_not_inf
#ifdef DENORM_OPERAND
#ifdef DENORM_OPERAND
        cmpb    TW_Valid,TAG(%esi)
        cmpb    TW_Valid,TAG(%esi)
        jne     L_return_zero
        jne     L_return_zero
        cmpl    EXP_UNDER,EXP(%esi)
        cmpl    EXP_UNDER,EXP(%esi)
        jg      L_return_zero           /* Answer is zero */
        jg      L_return_zero           /* Answer is zero */
        call    SYMBOL_NAME(denormal_operand)
        call    SYMBOL_NAME(denormal_operand)
        orl     %eax,%eax
        orl     %eax,%eax
        jnz     fpu_Arith_exit
        jnz     fpu_Arith_exit
#endif DENORM_OPERAND
#endif DENORM_OPERAND
        jmp     L_return_zero           /* Answer is zero */
        jmp     L_return_zero           /* Answer is zero */
L_arg2_not_inf:
L_arg2_not_inf:
#ifdef PARANOID
#ifdef PARANOID
        cmpb    TW_Zero,TAG(%esi)
        cmpb    TW_Zero,TAG(%esi)
        jne     L_unknown_tags
        jne     L_unknown_tags
#endif PARANOID
#endif PARANOID
        /* arg1 is zero, arg2 is not Infinity or a NaN */
        /* arg1 is zero, arg2 is not Infinity or a NaN */
#ifdef DENORM_OPERAND
#ifdef DENORM_OPERAND
        cmpl    EXP_UNDER,EXP(%ebx)
        cmpl    EXP_UNDER,EXP(%ebx)
        jg      L_copy_arg1             /* Answer is zero */
        jg      L_copy_arg1             /* Answer is zero */
        call    SYMBOL_NAME(denormal_operand)
        call    SYMBOL_NAME(denormal_operand)
        orl     %eax,%eax
        orl     %eax,%eax
        jnz     fpu_Arith_exit
        jnz     fpu_Arith_exit
#endif DENORM_OPERAND
#endif DENORM_OPERAND
L_copy_arg1:
L_copy_arg1:
        movb    TAG(%esi),%ax
        movb    TAG(%esi),%ax
        movb    %ax,TAG(%edi)
        movb    %ax,TAG(%edi)
        movl    EXP(%esi),%eax
        movl    EXP(%esi),%eax
        movl    %eax,EXP(%edi)
        movl    %eax,EXP(%edi)
        movl    SIGL(%esi),%eax
        movl    SIGL(%esi),%eax
        movl    %eax,SIGL(%edi)
        movl    %eax,SIGL(%edi)
        movl    SIGH(%esi),%eax
        movl    SIGH(%esi),%eax
        movl    %eax,SIGH(%edi)
        movl    %eax,SIGH(%edi)
LDiv_set_result_sign:
LDiv_set_result_sign:
        movb    SIGN(%esi),%cl
        movb    SIGN(%esi),%cl
        cmpb    %cl,SIGN(%ebx)
        cmpb    %cl,SIGN(%ebx)
        jne     LDiv_negative_result
        jne     LDiv_negative_result
        movb    SIGN_POS,SIGN(%edi)
        movb    SIGN_POS,SIGN(%edi)
        xorl    %eax,%eax               /* Valid result */
        xorl    %eax,%eax               /* Valid result */
        jmp     LDiv_exit
        jmp     LDiv_exit
LDiv_negative_result:
LDiv_negative_result:
        movb    SIGN_NEG,SIGN(%edi)
        movb    SIGN_NEG,SIGN(%edi)
        xorl    %eax,%eax               /* Valid result */
        xorl    %eax,%eax               /* Valid result */
LDiv_exit:
LDiv_exit:
#ifndef NON_REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
        leal    -40(%ebp),%esp
        leal    -40(%ebp),%esp
#else
#else
        leal    -12(%ebp),%esp
        leal    -12(%ebp),%esp
#endif NON_REENTRANT_FPU
#endif NON_REENTRANT_FPU
        popl    %ebx
        popl    %ebx
        popl    %edi
        popl    %edi
        popl    %esi
        popl    %esi
        leave
        leave
        ret
        ret
L_return_zero:
L_return_zero:
        xorl    %eax,%eax
        xorl    %eax,%eax
        movl    %eax,SIGH(%edi)
        movl    %eax,SIGH(%edi)
        movl    %eax,SIGL(%edi)
        movl    %eax,SIGL(%edi)
        movl    EXP_UNDER,EXP(%edi)
        movl    EXP_UNDER,EXP(%edi)
        movb    TW_Zero,TAG(%edi)
        movb    TW_Zero,TAG(%edi)
        jmp     LDiv_set_result_sign
        jmp     LDiv_set_result_sign
#ifdef PARANOID
#ifdef PARANOID
L_unknown_tags:
L_unknown_tags:
        pushl   EX_INTERNAL | 0x208
        pushl   EX_INTERNAL | 0x208
        call    EXCEPTION
        call    EXCEPTION
        /* Generate a NaN for unknown tags */
        /* Generate a NaN for unknown tags */
        movl    SYMBOL_NAME(CONST_QNaN),%eax
        movl    SYMBOL_NAME(CONST_QNaN),%eax
        movl    %eax,(%edi)
        movl    %eax,(%edi)
        movl    SYMBOL_NAME(CONST_QNaN)+4,%eax
        movl    SYMBOL_NAME(CONST_QNaN)+4,%eax
        movl    %eax,SIGL(%edi)
        movl    %eax,SIGL(%edi)
        movl    SYMBOL_NAME(CONST_QNaN)+8,%eax
        movl    SYMBOL_NAME(CONST_QNaN)+8,%eax
        movl    %eax,SIGH(%edi)
        movl    %eax,SIGH(%edi)
        jmp     LDiv_exit               /* %eax is nz */
        jmp     LDiv_exit               /* %eax is nz */
#endif PARANOID
#endif PARANOID
 
 

powered by: WebSVN 2.1.0

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