; math_tan_cot.asm ; ; Assembly language source for the tangent ; and cotangent functions: include math.inc include aoalib.inc ; tan- ; ; Computes tan(st0) by using the fsincos instruction. ; ; The x87 fsincos instruction requires the operand to be in the ; range -2**63..2**63. If it is outside this range, the sincos ; instruction leaves ST0 unchanged and sets the C2 flag in the ; FP status register. This function will handle the case of ; st0 being outside this range (it will compute the remainder ; of st0 divided by 2pi prior to computing fsincos). .code math_tan proc push rax ; Because the vast majority of the time, tan(x) ; is invoked for small values (e.g., less than 360 degrees), ; we'll just execute fptan and adjust things if fptan ; fails. fptan fstsw ax test ah, 100b jz goodTan ; fptan failed. We need to reduce the value ; to a range smaller than _/+2**63. We'll ; put it in the range -2pi..+2pi. ; ; Get the value into the range -2pi..2pi: fldpi ; Compute 2pi (the divisor) fldpi faddp fld st(1) mod2pi: fprem1 fstsw ax ; Determine if we are done (c2=0) and ah, 100b jnz mod2pi fstp st(2) fstp st(0) ; Okay, now that we've got it in range, ; recompute the sincos value. fptan goodTan: fstp st(0) ; Remove the 1.0 pushed on the stack. pop rax ret math_tan endp ; The cotangent is just 1/tan. math_cot proc call math_tan fld1 fdivrp ret math_cot endp end