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