root/kernel/FPU-emu/reg_div.S

/* [previous][next][first][last][top][bottom][index][help] */
   1         .file   "reg_div.S"
   2 /*---------------------------------------------------------------------------+
   3  |  reg_div.S                                                                |
   4  |                                                                           |
   5  | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
   6  |                                                                           |
   7  | Copyright (C) 1992,1993                                                   |
   8  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   9  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
  10  |                                                                           |
  11  | Call from C as:                                                           |
  12  |   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                     |
  13  |                                    unsigned int control_word)             |
  14  |                                                                           |
  15  +---------------------------------------------------------------------------*/
  16 
  17 #include "exception.h"
  18 #include "fpu_asm.h"
  19 
  20 .text
  21         .align 2
  22 
  23 .globl  _reg_div
  24 _reg_div:
  25         pushl   %ebp
  26         movl    %esp,%ebp
  27 
  28         pushl   %esi
  29         pushl   %edi
  30         pushl   %ebx
  31 
  32         movl    PARAM1,%esi
  33         movl    PARAM2,%ebx
  34         movl    PARAM3,%edi
  35 
  36         movb    TAG(%esi),%al
  37         orb     TAG(%ebx),%al
  38 
  39         jne     L_div_special           // Not (both numbers TW_Valid)
  40 
  41 
  42 // Both arguments are TW_Valid
  43         movl    EXP(%esi),%edx
  44         movl    EXP(%ebx),%eax
  45         subl    %eax,%edx
  46         addl    EXP_BIAS,%edx
  47         movl    %edx,EXP(%edi)
  48 
  49         movb    TW_Valid,TAG(%edi)
  50 
  51         movb    SIGN(%esi),%cl
  52         cmpb    %cl,SIGN(%ebx)
  53         setne   (%edi)        // Set the sign, requires SIGN_NEG=1, SIGN_POS=0
  54 
  55 //      add     $SIGL_OFFSET,%ebx
  56 //      add     $SIGL_OFFSET,%esi
  57 
  58         jmp     _divide_kernel
  59 
  60 
  61 /*-----------------------------------------------------------------------*/
  62 L_div_special:
  63         cmpb    TW_NaN,TAG(%esi)        // A NaN with anything to give NaN
  64         je      L_arg1_NaN
  65 
  66         cmpb    TW_NaN,TAG(%ebx)        // A NaN with anything to give NaN
  67         jne     L_no_NaN_arg
  68 
  69 // Operations on NaNs
  70 L_arg1_NaN:
  71 L_arg2_NaN:
  72         pushl   %edi
  73         pushl   %ebx
  74         pushl   %esi
  75         call    _real_2op_NaN
  76         jmp     LDiv_exit
  77 
  78 // Invalid operations
  79 L_zero_zero:
  80 L_inf_inf:
  81         pushl   %esi
  82         call    _arith_invalid
  83         jmp     LDiv_exit
  84 
  85 L_no_NaN_arg:
  86         cmpb    TW_Infinity,TAG(%esi)
  87         jne     L_arg1_not_inf
  88 
  89         cmpb    TW_Infinity,TAG(%ebx)
  90         je      L_inf_inf               // invalid operation
  91 
  92         // Note that p16-9 says that infinity/0 returns infinity
  93         jmp     L_copy_arg1             // Answer is Inf
  94 
  95 L_arg1_not_inf:
  96         cmpb    TW_Zero,TAG(%ebx)       // Priority to div-by-zero error
  97         jne     L_arg2_not_zero
  98 
  99         cmpb    TW_Zero,TAG(%esi)
 100         je      L_zero_zero             // invalid operation
 101 
 102 // Division by zero error
 103         pushl   %esi
 104         movb    SIGN(%esi),%al
 105         xorb    SIGN(%ebx),%al
 106         pushl   %eax                    // lower 8 bits have the sign
 107         call    _divide_by_zero
 108         jmp     LDiv_exit
 109 
 110 L_arg2_not_zero:
 111         cmpb    TW_Infinity,TAG(%ebx)
 112         jne     L_arg2_not_inf
 113 
 114         jmp     L_return_zero           // Answer is zero
 115 
 116 L_arg2_not_inf:
 117         cmpb    TW_Zero,TAG(%esi)
 118         jne     L_unknown_tags
 119 
 120 L_copy_arg1:
 121         movb    TAG(%esi),%ax
 122         movb    %ax,TAG(%edi)
 123         movl    EXP(%esi),%eax
 124         movl    %eax,EXP(%edi)
 125         movl    SIGL(%esi),%eax
 126         movl    %eax,SIGL(%edi)
 127         movl    SIGH(%esi),%eax
 128         movl    %eax,SIGH(%edi)
 129 
 130         movb    SIGN(%esi),%cl
 131         cmpb    %cl,SIGN(%ebx)
 132         jne     LDiv_negative_result
 133 
 134         movb    SIGN_POS,SIGN(%edi)
 135         jmp     LDiv_exit
 136 
 137 LDiv_set_result_sign:
 138         movb    SIGN(%esi),%cl
 139         cmpb    %cl,SIGN(%edi)
 140         jne     LDiv_negative_result
 141 
 142         movb    SIGN_POS,SIGN(%ebx)
 143         jmp     LDiv_exit
 144 
 145         .align 2,0x90
 146 LDiv_negative_result:
 147         movb    SIGN_NEG,SIGN(%edi)
 148 
 149 LDiv_exit:
 150         leal    -12(%ebp),%esp
 151 
 152         popl    %ebx
 153         popl    %edi
 154         popl    %esi
 155         leave
 156         ret
 157 
 158 
 159 L_return_zero:
 160         movb    TW_Zero,TAG(%edi)
 161         jmp     LDiv_set_result_sign
 162 
 163 L_unknown_tags:
 164         push    EX_INTERNAL | 0x208
 165         call    EXCEPTION
 166 
 167         // Generate a NaN for unknown tags
 168         movl    _CONST_QNaN,%eax
 169         movl    %eax,(%edi)
 170         movl    _CONST_QNaN+4,%eax
 171         movl    %eax,SIGL(%edi)
 172         movl    _CONST_QNaN+8,%eax
 173         movl    %eax,SIGH(%edi)
 174         jmp     LDiv_exit

/* [previous][next][first][last][top][bottom][index][help] */