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

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