|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: .file "trans.s"
26:
27: .ident "@(#)kern-fp:trans.s 1.1"
28: // *****************************************************************************
29: //
30: // t r a n s . m o d
31: // =================
32: //
33: // ===============================================================
34: // intel corporation proprietary information
35: // this software is supplied under the terms of a license
36: // agreement or non-disclosure agreement with intel corporation
37: // and may not be copied nor disclosed except in accordance with
38: // the terms of that agreement.
39: // ===============================================================
40: //
41: // public procedures:
42: // arctan, exp, log, splog, tan, move_10_bytes
43: // move_constant, test_5w, ,test_6w, test_4w, test_3w, clear_5w, clear_6w
44: // set_5w, set_6w,set_4w, set_3w, left_shift_result_cl
45: // left_shift_frac1_cl, left_shift_frac2_cl
46: // right_shift_result_cl,right_shift_frac1_cl
47: // right_shift_frac2_cl,right_shift,left_shift
48: // sticky_right_shift,addition_normalize
49: // subtraction_normalize,one_left_normalize
50: // gradual_underflow,left_shift_frac1_1,sin,cos,sincos
51: //
52: // *****************************************************************************
53: //
54: //
55: //...october 16, 1986...
56: //
57: //$nolist
58: #include "fp_e80387.h"
59: //$list
60: .text //a_med segment er public
61: //
62: // extrn put_si_result,do_exchange,addx,subx
63: // extrn divx,divid,round,underflow_response
64: // extrn log_divx,decompose,mult,mulx
65: // extrn overflow_response,sp_subadd,stack_full_
66: // extrn pop_free,put_op1_result,set_p_error
67: // extrn set_u_error,get_precision,do_exchange_leave_a_bit
68: //
69: .globl two_arg_trans
70: .globl exp
71: .globl log
72: .globl splog
73: .globl move_10_bytes
74: .globl tan
75: .globl move_constant
76: .globl test_5w
77: .globl test_6w
78: .globl test_4w
79: .globl test_3w
80: .globl clear_5w
81: .globl clear_6w
82: .globl set_5w
83: .globl set_6w
84: .globl set_4w
85: .globl set_3w
86: .globl left_shift_frac1_cl
87: .globl left_shift_result_cl
88: .globl left_shift_frac2_cl
89: .globl right_shift_frac1_cl
90: .globl right_shift_frac2_cl
91: .globl right_shift_result_cl
92: .globl right_shift
93: .globl left_shift
94: .globl gradual_underflow
95: .globl addition_normalize
96: .globl sticky_right_shift
97: .globl one_left_normalize
98: .globl subtraction_normalize
99: .globl left_shift_frac1_1
100: .globl sin
101: .globl cos
102: .globl sincos
103: //
104: //
105: add_half_pattern:
106: .value 0x80,0,0,0,0
107: add_half_pattern_1:
108: .value 0x8000,0,0,0,0
109: constant_ln2_ov_6:
110: .value 0,0,0,0x1ff5,0x0ec98
111: constant_2_ov_ln2:
112: .value 0x0bbc0,0x17f0,0x295c,0x0aa3b,0x00b8
113: constant_one:
114: .value 0,0,0,0,0x100
115: constant_six:
116: .value 0,0,0,0,0x0c000
117: constant_sqrt_of_2:
118: .value 0x8400,0x0de64,0x33f9,0x04f3,0x0b5
119: constant_3_ov_ln2:
120: .value 0,0x0f48d,0x0511,0x0ac5f,0x8a7f
121: constant_one_1:
122: .value 0,0,0,0,0x8000
123: //
124: // this constant has been decreased by 1 to compensate
125: // for the bits lost during right shift.
126: //
127: constant_c0h:
128: .value 0x0ff00,0x0ffff,0x0ffff,0x0ffff,0x0bf
129: //
130: log_constant:
131: .value 0x09fa0,0x0d687,0x039fb,0x0c01a,0x095 //1
132: .value 0x0f260,0x0dc57,0x05e68,0x0d3c2,0x0a4 //2
133: .value 0x0fd20,0x0b43c,0x0cfde,0x000d1,0x0ae //3
134: .value 0x0e680,0x098b3,0x0d648,0x01fb7,0x0b3 //4
135: .value 0x089c0,0x0ec39,0x0ac77,0x0d69b,0x0b5 //5
136: .value 0x05380,0x0914c,0x02e16,0x03cb4,0x0b7 //6
137: .value 0x0fc80,0x0428b,0x0b778,0x0f285,0x0b7 //7
138: .value 0x056e0,0x063ba,0x06bd5,0x04e23,0x0b8 //8
139: .value 0x031e0,0x0ab26,0x0f853,0x07c1f,0x0b8 //9
140: .value 0x0fd60,0x0a2a0,0x0ba1f,0x09329,0x0b8 //a
141: .value 0x057c0,0x0be18,0x07bca,0x09eb1,0x0b8 //b
142: .value 0x070a0,0x0fe44,0x0150d,0x0a476,0x0b8 //c
143: .value 0x0aa60,0x09b1b,0x08fd2,0x0a758,0x0b8 //d
144: .value 0x09460,0x09ae9,0x0d8be,0x0a8c9,0x0b8 //e
145: .value 0x03380,0x02572,0x08017,0x0a982,0x0b8 //f
146: //
147: tan_constant:
148: .value 0x034c0,0x068c2,0x0a221,0x00fda,0x0c9 //0
149: .value 0x04580,0x0da7b,0x02b0d,0x06338,0x0ed //1
150: .value 0x01560,0x006eb,0x0c964,0x0dbaf,0x0fa //2
151: .value 0x032c0,0x07b6e,0x0d561,0x0add4,0x0fe //3
152: .value 0x036c0,0x0ef4e,0x0b967,0x0aadd,0x0ff //4
153: .value 0x04280,0x0b125,0x0dd4b,0x0eaad,0x0ff //5
154: .value 0x0bbe0,0x094d5,0x0dddb,0x0faaa,0x0ff //6
155: .value 0x06800,0x0d4b9,0x0addd,0x0feaa,0x0ff //7
156: .value 0x04bc0,0x0ddb9,0x0aadd,0x0ffaa,0x0ff //8
157: .value 0x04ba0,0x0dddd,0x0aaad,0x0ffea,0x0ff //9
158: .value 0x0dba0,0x0dddd,0x0aaaa,0x0fffa,0x0ff //a
159: .value 0x0dde0,0x0addd,0x0aaaa,0x0fffe,0x0ff //b
160: .value 0x0dde0,0x0aadd,0x0aaaa,0x0ffff,0x0ff //c
161: .value 0x0dde0,0x0aaad,0x0eaaa,0x0ffff,0x0ff //d
162: .value 0x0dde0,0x0aaaa,0x0faaa,0x0ffff,0x0ff //e
163: .value 0x0ade0,0x0aaaa,0x0feaa,0x0ffff,0x0ff //f
164: //
165: // *******************************************************************************
166: //
167: at_case_table:
168: .long at_round,case_1,case_2,case_3
169: //
170: two_arg_trans_table:
171: .long at_non_0,log,splog
172: //
173: //...the following jump tables refer to the following op1/op2 cases
174: //
175: // (where v=valid, z=zero, f=infinity, and d=denormal):
176: // v/v,v/z,v/f,v/d,z/v,z/z,z/f,z/d,f/v,f/z,f/f,f/d,d/v,d/z,d/f and d/d,
177: // in that order ..
178: //
179: // arctan2_table is first
180: //
181: special_table:
182: .long handle_non_special_cases,sign_y_hapi
183: .long sign_y_pi_or_0,only_op2_denormd
184: .long sign_y_pi_or_0,at_both_0
185: .long sign_y_pi_or_0,derror_sign_y_pi_or_0
186: .long sign_y_hapi,sign_y_hapi
187: .long handle_non_special_cases,derror_sign_y_hapi
188: .long only_op1_denormd,derror_sign_y_hapi
189: .long derror_sign_y_pi_or_0,both_ops_denormd
190: //
191: // log_table is second, 64 bytes after arctan2_table
192: //
193: .long handle_non_special_cases,op2_signed_by_op1_vs_1
194: .long inv_or_op2_signed_by_op1_vs_1,only_op2_denormd
195: .long zerror_flip_sign_y_inf,op_unsupp
196: .long zerror_flip_sign_op2,zerror_flip_sign_y_inf
197: .long sign_y_op1,op_unsupp
198: .long op2,derror_sign_y_op1
199: .long only_op1_denormd,derror_flip_sign_op2
200: .long derror_flip_sign_op2,both_ops_denormd
201: //
202: // splog_table is third (and last), 128 bytes after arctan2_table
203: //
204: .long handle_non_special_cases,exor_signed_op2
205: .long exor_signed_op2,only_op2_denormd
206: .long exor_signed_op1,exor_signed_op2
207: .long op_unsupp,derror_exor_signed_op1
208: .long sign_y_op1,op_unsupp
209: .long op2,derror_sign_y_op1
210: .long only_op1_denormd,derror_exor_signed_op2
211: .long derror_exor_signed_op2,both_ops_denormd
212: //
213: // *****************************************************************************
214: //
215: // ***********************************************************************
216: // atan_core:
217: // *********
218: //
219: // function:
220: // calculates arc tangent of (y/x), where
221: // 0 < y/x < 1 ; op2 = x, op1 = y.
222: //
223: // inputs:
224: // assumes that operand1 and operand2 are set up.
225: //
226: // outputs:
227: // result in global record 12; possible underflow
228: // and inexact errors.
229: //
230: // data accessed:
231: // - expon1 word_frac1
232: // - lsb_frac1 msb_frac1
233: // - offset_operand1 expon2
234: // - lsb_frac2 offset_operand2
235: // - offset_result result_sign
236: // - result_tag result_expon
237: // - result_word_frac msb_result
238: // - offset_of_result_frac offset_cop
239: // - offset_dop siso
240: //
241: // data changed:
242: // - expon1 frac1
243: // - frac2 result_sign
244: // - result_expon result_frac
245: // - siso
246: //
247: // procedures called:
248: // put_si_result right_shift left_shift
249: // move_10_bytes move_constant addx
250: //subx mulx accel_divx (replaces divx)
251: // divid one_left_normalize round
252: // addition_normalize underflow_response pop_free
253: // test_5w set_p_error set_u_error
254: //
255: // **********************************************************************
256: ALIGN
257: atan_core: //proc
258: push %gs:sr_masks // save precision control
259: // and dword ptr %gs:sr_masks, 0fffff3ffh; set rounding control to nearest
260: orl $0x0300,%gs:sr_masks // set precision control to prec64
261: orb $inexact_mask,%gs:sr_errors // always inexact
262: movb positive,result_sign(%ebp)// result is always positive
263: movw $0,siso // clear siso
264: mov dword_expon2,%eax
265: sub dword_expon1,%eax
266: mov %eax,dword_exp_tmp
267: cmp $15,%eax
268: jle atn_pseudo_div
269: cmp $63,%eax
270: //
271: //tiny argument
272: //
273: jg atn_divide
274: jmp atn_rat_appx
275: ALIGN
276: atn_divide:
277: call divid // floating-point divide
278: //
279: //post operation rounding
280: //
281: call post_op_round // d.e. precision rounding
282: //
283: //error check
284: //
285: mov dword_result_expon,%eax
286: cmp $0,%eax
287: jg atn_put_atn_f
288: jl atn_put_atn // underflow of core has occurred.
289: mov $offset_result+frac64,%edi
290: call test_4w // note that ax is 0 here.
291: jnz atn_put_atn // underflow of core has occurred.
292: atn_zero:
293: movb special,result_tag(%ebp)
294: jmp atn_put_atn
295: ALIGN
296: //
297: atn_pseudo_div:
298: call right_shift_frac2_8
299: call right_shift_frac1_8
300: atn_loop_back_1:
301: call subx
302: shlw $1,siso
303: cmpb $0,msb_result
304: jnz atn_shift_left
305: call move_result_cop // cop is 67 bits temp
306: mov $offset_operand1,%edi
307: call right_shift_dword_exp_tmp
308: call addx
309: call move_result_frac1
310: mov $add_half_pattern,%esi
311: call add_frac2 // add 1/2 round
312: call move_result_frac2
313: andl $0x0ff000000,dword_frac2(%ebp) // frac2 = 64 bits x
314: call move_cop_frac1 // frac1 = 67 bits y
315: incw siso
316: cmpb $0,msb_result
317: je atn_shift_left
318: mov $1,%ecx
319: call right_shift_frac2_cl
320: andl $0x0ff000000,dword_frac2(%ebp)
321: jmp atn_merge_0
322: ALIGN
323: atn_shift_left:
324: call left_shift_frac1_1
325: atn_merge_0:
326: incl dword_exp_tmp
327: cmp $15,dword_exp_tmp
328: jna atn_loop_back_1
329: mov $7,%ecx
330: call left_shift_frac1_cl
331: andl $0x0e0000000,dword_frac1(%ebp)
332: movl $15,dword_exp_tmp
333: call left_shift_frac2_8
334: atn_rat_appx:
335: // the following call used to be to divx instead of accel_divx:
336: call accel_divx // y/x --> z (67)
337: call move_result_frac1
338: mov $9,%ecx
339: call right_shift_frac1_cl
340: andl $0x0ffe00000,dword_frac1(%ebp)
341: call move_result_frac2
342: call right_shift_frac2_8
343: andl $0x0ffe00000,dword_frac2(%ebp)
344: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac
345: call move_result_cop
346: call addx
347: call move_result_dop //dop = new y (67)
348: call move_cop_frac1
349: call move_cop_frac2
350: mov $30,%ecx
351: call right_shift_frac1_cl // perform short multiply
352: movl $0,dword_frac1(%ebp)
353: mov $30,%ecx
354: call left_shift_frac1_cl
355: call mulx
356: mov $offset_result,%edi
357: call right_shift_dword_exp_tmp
358: movb $0x0c0,msb_result
359: call move_result_frac2 // new x (64)
360: andl $0x0e0000000,dword_frac2(%ebp)
361: cmpb $0,msb_dop
362: movb $1,%al
363: mov $7,%ecx
364: jne atn_merge_1
365: movb $0,%al
366: mov $8,%ecx
367: atn_merge_1:
368: push %eax //save al
369: mov $offset_dop+frac80,%edi
370: call left_shift
371: call move_dop_frac1
372: // the following call used to be to divx instead of accel_divx:
373: call accel_divx
374: andl $0x0e0000000,result_dword_frac(%ebp)// theta is here
375: pop %eax
376: shrb $1,%al
377: mov $7,%ecx
378: jnb atn_merge_2
379: mov $6,%ecx
380: atn_merge_2:
381: call right_shift_result_cl
382: call move_result_frac1
383: atn_loop_back_2:
384: shrw $1,siso
385: jnb atn_q_bit_not_set
386: mov $10,%eax
387: mull dword_exp_tmp
388: add $tan_constant,%eax
389: mov %eax,%esi
390: call add_frac2
391: call move_result_frac1
392: atn_q_bit_not_set:
393: cmpw $0,siso
394: jz atn_end_loop
395: mov $1,%ecx
396: call right_shift_frac1_cl
397: andl $0x0ffe00000,dword_frac1(%ebp)
398: decl dword_exp_tmp
399: jmp atn_loop_back_2
400: ALIGN
401: atn_end_loop:
402: cmpb $0,msb_frac1
403: mov $8,%ecx
404: je atn_merge_3
405: mov $7,%ecx
406: decl dword_exp_tmp
407: atn_merge_3:
408: call left_shift_frac1_cl
409: movl $0x3ffe,dword_expon1
410: mov dword_exp_tmp,%eax
411: sub %eax,dword_expon1
412: mov $offset_operand1,%edi
413: call one_left_normalize
414: call move_frac1_result// added when add_half1_frac below was cut
415: mov dword_expon1,%eax
416: mov %eax,dword_result_expon
417: // call add_half1_frac2
418: atn_put_atn_f:
419: movb valid,result_tag(%ebp) // valid result
420: atn_put_atn:
421: pop %gs:sr_masks // restore precision control
422: ret
423: //atan_core endp
424: //
425: //
426: // *******************************************************************************
427: //
428: ALIGN
429: move_unpacked_0_to_edi: //proc
430:
431: movl $0,(%ebp,%edi)
432: movl $0,frac64(%ebp,%edi)
433: movl $0,frac32(%ebp,%edi)
434: movl $0x10000*SPECIAL+POSITIVE,sign(%ebp,%edi)
435: movl $0,expon(%ebp,%edi)
436: ret
437:
438: //move_unpacked_0_to_edi endp
439: //
440: // *******************************************************************************
441: //
442: ALIGN
443: move_unpacked_hapi_to_edi: //proc
444:
445: movl $0,(%ebp,%edi)
446: movl $0x2168c235,frac64(%ebp,%edi)
447: movl $0x0c90fdaa2,frac32(%ebp,%edi)
448: movl $0x10000*VALID+POSITIVE,sign(%ebp,%edi)
449: movl $0x3fff,expon(%ebp,%edi)
450: ret
451:
452: //move_unpacked_hapi_to_edi endp
453: //
454: // *******************************************************************************
455: //
456: //
457: // *******************************************************************************
458:
459: ALIGN
460: at_non_0: //proc
461:
462: movb sign1(%ebp),%dl
463: movb sign2(%ebp),%dh
464: movb positive,sign1(%ebp)
465: movb positive,sign2(%ebp)
466: movb %dh,%bl
467: and $8,%ebx
468: at_cmpr_ops: // this compare assumes same-
469: // signed, normalized comparands
470: mov dword_expon2,%eax
471: cmp dword_expon1,%eax
472: jg take_atan
473: jl at_switch_ops
474: mov dword_frac1+frac32(%ebp),%eax
475: cmp dword_frac2+frac32(%ebp),%eax
476: jg take_atan
477: jl at_switch_ops
478: mov dword_frac1+frac64(%ebp),%eax
479: cmp dword_frac2+frac64(%ebp),%eax
480: jg take_atan
481: jl at_switch_ops
482: at_ops_eql:
483: mov $offset_result,%edi
484: call move_unpacked_hapi_to_edi
485: decl dword_result_expon // make pi/4
486: or %ebx,%ebx
487: jz at_sign_adjust
488: jmp hapi_to_op1
489: ALIGN
490: at_switch_ops:
491: push %ebx
492: call swap_ops // edx preserved
493: pop %ebx
494: or $4,%ebx
495: take_atan:
496: push %ebx // save operand signs
497: push %edx // save table index
498: call atan_core
499: pop %edx
500: pop %ebx
501: or %ebx,%ebx
502: jnz hapi_to_op1
503: at_underflow_:
504: mov dword_result_expon,%eax
505: cmp $0,%eax
506: jg at_round
507: jl at_underflow
508: cmpb special,result_tag(%ebp)
509: je at_round_report
510: at_underflow: // underflow
511: push %edx // save sign info
512: call underflow_response
513: pop %edx // restore sign info
514: orb underflow_mask,%gs:sr_errors
515: jmp at_sign_adjust
516: ALIGN
517: hapi_to_op1:
518: mov $offset_operand1,%edi
519: call move_unpacked_hapi_to_edi
520: jmp *%cs:at_case_table(%ebx)
521: ALIGN
522: //
523: case_3:
524: movb $add_op,operation_type(%ebp)
525: jmp at_to_op2
526: ALIGN
527: case_2:
528: incl dword_expon1 // make pi
529: case_1:
530: movb $sub_op,operation_type(%ebp)
531: at_to_op2:
532: push %edx
533: // push ebx
534: lea dword_frac2(%ebp),%edi
535: lea result_dword_frac(%ebp),%esi
536: call move_op_to_op
537: call subadd
538: // pop ebx
539: pop %edx
540: at_round:
541: push %gs:sr_masks
542: orl $0x0300,%gs:sr_masks // set precision control to prec64
543: push %edx
544: call post_op_round
545: pop %edx
546: pop %gs:sr_masks
547: at_round_report:
548: cmpw $0,rnd_history
549: je at_sign_adjust
550: orb $inexact_mask,%gs:sr_errors
551: cmpb true,added_one
552: jne at_sign_adjust
553: orb $a_mask,%gs:sr_flags
554: at_sign_adjust:
555: movb %dl,result_sign(%ebp)
556: at_exit:
557: ret
558:
559: //at_non_0 endp
560: //
561: // *******************************************************************************
562: //
563: //
564: ALIGN
565: two_arg_trans: //proc
566:
567: jz two_arg_special_case_ // branch if no stack error
568: call set_stk_u_error // stack underflow occurred
569: testb invalid_mask,%gs:sr_masks// if unmasked, just return
570: jnz return_indef // else, return indefinite
571: two_arg_unmasked_exit:
572: ret
573: ALIGN
574: return_indef:
575: call put_indefinite
576: jmp get_result_ptr
577: ALIGN
578: two_arg_special_case_:
579: andb $~a_mask,%gs:sr_flags // clear a-bit initially
580: movzbl tag1(%ebp),%ebx // both operands valid?
581: orb tag2(%ebp),%bl
582: jnz two_arg_special_case
583: handle_non_special_cases:
584: movzbl operation_type(%ebp),%ebx// call log/splog/arctan2
585: subb $arctan_op,%bl // to do the operation
586: je main_call // ebx has offset of at_non_0 container
587: cmpb $log_op-arctan_op,%bl
588: je log_of_neg_num_
589: cmpl $0x3fff,dword_expon1
590: jg op_unsupp
591: jl get_splog_offset
592: weed_out_neg_1:
593: cmpb positive,sign1(%ebp)
594: je op_unsupp
595: cmpl $0x080000000,dword_frac1+frac32(%ebp)
596: jne op_unsupp
597: cmp $0,dword_frac1+frac64(%ebp)
598: jne op_unsupp
599: jmp zerror_flip_sign_y_inf
600: ALIGN
601: get_splog_offset:
602: mov $8,%ebx // ebx has offset of splog container
603: jmp main_call
604: ALIGN
605: log_of_neg_num_:
606: cmpb positive,sign1(%ebp)
607: jne op_unsupp
608: mov $4,%ebx // ebx has offset of log container
609: main_call:
610: call *%cs:two_arg_trans_table(%ebx)
611: get_result_ptr:
612: mov $offset_result,%edi
613: got_result_ptr:
614: mov offset_result_rec,%esi
615: jmp put_arith_result
616: ALIGN
617: //
618: both_ops_denormd:
619: orb denorm_mask,%gs:sr_errors
620: testb denorm_mask,%gs:sr_masks
621: jz two_arg_unmasked_exit
622: mov $offset_operand1,%edi
623: call norm_denorm
624: op2_denormd:
625: mov $offset_operand2,%edi
626: call norm_denorm
627: jmp handle_non_special_cases
628: ALIGN
629: only_op1_denormd:
630: orb denorm_mask,%gs:sr_errors
631: testb denorm_mask,%gs:sr_masks
632: jz two_arg_unmasked_exit
633: mov $offset_operand1,%edi
634: call norm_denorm
635: jmp handle_non_special_cases
636: ALIGN
637: only_op2_denormd:
638: orb denorm_mask,%gs:sr_errors
639: testb denorm_mask,%gs:sr_masks
640: jz two_arg_unmasked_exit
641: jmp op2_denormd
642: ALIGN
643: //
644: two_arg_special_case:
645: testb $0x10,%bl // al contains (ebp).tag1 or (ebp).tag2
646: jz op1_nan_
647: op_unsupp:
648: orb invalid_mask,%gs:sr_errors// here, at least one op is unsupported.
649: testb invalid_mask,%gs:sr_masks
650: jz two_arg_unmasked_exit
651: jmp return_indef
652: ALIGN
653: op1_nan_: // here, neither op is unsupported.
654: cmpb inv,tag1(%ebp)
655: je op1_snan_
656: cmpb inv,tag2(%ebp)
657: jne non_nan_supp_ops
658: jmp signal_invalid_
659: ALIGN
660: op1_snan_:
661: testb $0x40,msb_frac1
662: jz invalid_operand
663: op2_also_nan_:
664: cmpb inv,tag2(%ebp)
665: jne jmp_set_up_nan_return
666: signal_invalid_:
667: testb $0x40,msb_frac2
668: jnz jmp_set_up_nan_return
669: invalid_operand:
670: orb invalid_mask,%gs:sr_errors// invalid operand sets
671: testb invalid_mask,%gs:sr_masks
672: jz two_arg_unmasked_exit // i-error, if unmasked
673: jmp_set_up_nan_return:
674: jmp set_up_nan_return
675: ALIGN
676: non_nan_supp_ops:
677: movb tag1(%ebp),%bh
678: movzbl operation_type(%ebp),%eax
679: subb $arctan_op,%al
680: je get_tag2 // eax now holds base of arctan table
681: cmpb $log_op-arctan_op,%al
682: je only_neg_0_ok
683: cmpl $0x3fff,dword_expon1
684: jl get_splog_table
685: je weed_out_neg_1
686: cmpl $0x7fff,dword_expon1
687: jne op_unsupp
688: cmpb positive,sign1(%ebp)
689: jne op_unsupp
690: get_splog_table:
691: mov $128,%eax // eax now holds base of splog table
692: jmp get_tag2
693: ALIGN
694: only_neg_0_ok:
695: cmpb positive,sign1(%ebp)
696: je log_table_base_to_eax
697: cmpb special,%bh
698: jne op_unsupp
699: log_table_base_to_eax:
700: mov $64,%eax // eax now holds base of log table
701: get_tag2:
702: movb tag2(%ebp),%bl
703: testb $0x04,%bh
704: jz op2_denorm_
705: movb $3,%bh // indicate op1 is denorm
706: op2_denorm_:
707: testb $0x04,%bl
708: jz get_index
709: movb $3,%bl // indicate op2 is denorm
710: get_index:
711: and $0x0303,%ebx // form index to special operation table
712: // bx=4*(4*masked_tag1 + masked_tag2),
713: // where masked_tag = 0 for valid,
714: shlb $2,%bh //1 for zero,
715: //2 for infinity
716: addb %bh,%bl //3 for denormd
717: xorb %bh,%bh
718: shl $2,%ebx
719: add_base:
720: add %eax,%ebx // (e)bx = case offset
721: jmp *%cs:special_table(%ebx) // jump to special case
722: ALIGN
723: //
724: derror_sign_y_pi_or_0:
725: orb denorm_mask,%gs:sr_errors
726: testb denorm_mask,%gs:sr_masks
727: jz two_arg_unmasked_exit // if unmasked, return
728: sign_y_pi_or_0:
729: cmpb positive,sign2(%ebp)
730: je sign_y_0
731: sign_y_pi:
732: mov $offset_result,%edi
733: call move_unpacked_hapi_to_edi
734: incl dword_result_expon // make pi
735: jmp at_spcl_sign_adjust
736: ALIGN
737:
738: derror_sign_y_hapi:
739: orb denorm_mask,%gs:sr_errors
740: testb denorm_mask,%gs:sr_masks
741: jz two_arg_unmasked_exit // if unmasked, return
742: sign_y_hapi:
743: mov $offset_result,%edi
744: call move_unpacked_hapi_to_edi
745: jmp at_spcl_sign_adjust
746: ALIGN
747:
748: at_both_0:
749: cmpb positive,sign2(%ebp)
750: jne sign_y_pi
751: sign_y_0:
752: mov $offset_result,%edi
753: call move_unpacked_0_to_edi
754:
755: at_spcl_sign_adjust:
756: movb sign1(%ebp),%dl
757: movb %dl,result_sign(%ebp)
758: jmp get_result_ptr
759: ALIGN
760:
761: zerror_flip_sign_y_inf:
762: orb zero_divide_mask,%gs:sr_errors
763: testb zero_divide_mask,%gs:sr_masks
764: jz two_arg_unmasked_exit
765: flip_sign_y_inf:
766: movl $0x080000000,dword_frac1+frac32(%ebp)
767: movl $0x10000*INFINITY+POSITIVE,sign1(%ebp)
768: movl $0x7fff,dword_expon1
769: flip_sign_y_op1:
770: mov $offset_operand1,%edi
771: flip_sign_y_to_edi:
772: movb sign2(%ebp),%dl
773: notb %dl
774: movb %dl,sign(%ebp,%edi)
775: jmp got_result_ptr
776: ALIGN
777:
778: //zerror_derror_flip_sign_y_inf:
779: // or %gs:sr_errors, zero_divide_mask
780: // test %gs:sr_masks, zero_divide_mask
781: // jz two_arg_unmasked_exit
782: // or %gs:sr_errors, denorm_mask
783: // test %gs:sr_masks, denorm_mask
784: // jz two_arg_unmasked_exit
785: // jmp short flip_sign_y_inf
786:
787: derror_sign_y_op1:
788: orb denorm_mask,%gs:sr_errors
789: testb denorm_mask,%gs:sr_masks
790: jz two_arg_unmasked_exit
791: sign_y_op1:
792: mov $offset_operand1,%edi
793: sign_y_to_edi:
794: movb sign2(%ebp),%dl
795: movb %dl,sign(%ebp,%edi)
796: jmp got_result_ptr
797: ALIGN
798:
799: inv_or_op2_signed_by_op1_vs_1:
800: cmpl $0x3fff,dword_expon1
801: jg op2
802: jl flip_sign_op2
803: cmpl $0x80000000,dword_frac1+frac32(%ebp)
804: ja op2
805: cmp $0,dword_frac1+frac64(%ebp)
806: jne op2
807: jmp op_unsupp
808: ALIGN
809:
810: zerror_flip_sign_op2:
811: orb zero_divide_mask,%gs:sr_errors
812: testb zero_divide_mask,%gs:sr_masks
813: jz two_arg_unmasked_exit
814: jmp flip_sign_op2
815: ALIGN
816:
817: op2_signed_by_op1_vs_1:
818: cmpl $0x3fff,dword_expon1
819: jge op2
820: flip_sign_op2:
821: notb sign2(%ebp)
822: op2:
823: mov $offset_operand2,%edi
824: jmp got_result_ptr
825: ALIGN
826:
827: derror_flip_sign_op2:
828: orb denorm_mask,%gs:sr_errors
829: testb denorm_mask,%gs:sr_masks
830: jz two_arg_unmasked_exit
831: jmp flip_sign_op2
832: ALIGN
833:
834: derror_exor_signed_op2:
835: orb denorm_mask,%gs:sr_errors
836: testb denorm_mask,%gs:sr_masks
837: jz two_arg_unmasked_exit
838: exor_signed_op2:
839: movb sign1(%ebp),%dl
840: xorb %dl,sign2(%ebp)
841: jmp op2
842: ALIGN
843:
844: derror_exor_signed_op1:
845: orb denorm_mask,%gs:sr_errors
846: testb denorm_mask,%gs:sr_masks
847: jz two_arg_unmasked_exit
848: exor_signed_op1:
849: movb sign2(%ebp),%dl
850: xorb %dl,sign1(%ebp)
851: op1:
852: mov $offset_operand1,%edi
853: jmp got_result_ptr
854: ALIGN
855:
856: //two_arg_trans endp
857: //
858: ALIGN
859: push_5_dw_at_esi: //proc
860:
861: pop %ebx // ebx <-- return address
862: push (%ebp,%esi)
863: push frac64(%ebp,%esi)
864: push frac32(%ebp,%esi)
865: push sign(%ebp,%esi)
866: push expon(%ebp,%esi)
867: jmp *%ebx
868:
869: //push_5_dw_at_esi endp
870:
871: // **********************************************************************
872: // **********************************************************************
873:
874: ALIGN
875: pop_5_dw_at_esi: //proc
876:
877: pop %ebx // ebx <-- return address
878: pop expon(%ebp,%esi)
879: pop sign(%ebp,%esi)
880: pop frac32(%ebp,%esi)
881: pop frac64(%ebp,%esi)
882: pop (%ebp,%esi)
883: jmp *%ebx
884:
885: //pop_5_dw_at_esi endp
886:
887: // **********************************************************************
888: ALIGN
889: move_unpacked_1_to_esi: //proc
890:
891: movl $0,(%ebp,%esi)
892: movl $0,frac64(%ebp,%esi)
893: movl $0x080000000,frac32(%ebp,%esi)
894: // mov positive+0x10000*valid,sign(%ebp,%esi)
895: movl $0x10000*VALID+POSITIVE,sign(%ebp,%esi)
896: movl $0x3fff,expon(%ebp,%esi)
897: ret
898:
899: //move_unpacked_1_to_esi endp
900: // **********************************************************************
901: // ***********************************************************************
902: // exp:
903: // ***
904: // function:
905: // calculates 2**x - 1, where 0 <= x < 1/2.
906: // inputs:
907: // assumes that operand1 is set up.
908: //
909: // outputs:
910: // result in global record 12; possible underflow
911: // and inexact errors.
912: //
913: // data accessed:
914: // - offset_operand1 tag1
915: // - expon1 word_frac1
916: // - lsb_frac1 offset_operand1
917: // - sign2 expon2
918: // - offset_operand2 offset_result
919: // - result_tag result_expon
920: // - lsb_result msb_result
921: // - offset_result siso
922: // - offset_cop
923: //
924: // data changed:
925: // - expon1 lsb_frac1
926: // - sign2 expon2
927: // - result_tag msb_result
928: // - siso
929: //
930: // procedures called:
931: // put_si_result right_shift left_shift
932: // move_10_bytes move_constant addx
933: // subx mulx divx
934: // addition_normalize round divid
935: // log_constant underflow_response set_p_error
936: //
937: // ***********************************************************************
938: ALIGN
939: exp_core: //proc
940: //
941: //pseudo_division
942: //
943: movw $0,siso // clear siso
944: mov $0x3fff,%eax
945: sub dword_expon1,%eax // dword_expon1 < 3fffh
946: cmp $63,%eax
947: jg exp_tiny_argument
948: mov %eax,dword_expon1
949: cmp $15,%eax
950: ja exp_rat_appx // impossible that eax <= 0
951: call right_shift_frac1_8
952: exp_loop_back_1:
953: mov $10,%eax
954: mull dword_expon1
955: add $log_constant-10,%eax
956: mov %eax,%esi
957: call sub_frac2
958: shlw $1,siso
959: cmpb $0,msb_result
960: jne exp_merge_0
961: call move_result_frac1
962: andl $0x0ffe00000,dword_frac1(%ebp)
963: incw siso
964: exp_merge_0:
965: incl dword_expon1
966: cmp $15,dword_expon1
967: ja exp_branch_1
968: call left_shift_frac1_1
969: jmp exp_loop_back_1
970: ALIGN
971: exp_tiny_argument:
972: movb positive,sign2(%ebp)
973: movl $0x3fff,dword_expon2
974: mov $constant_2_ov_ln2,%esi
975: call move_constant_frac2
976: call left_shift_frac2_8 // tiny argument
977: call divid // floating-point divide
978: call post_op_round
979: exp_put_exp_jmp:
980: jmp exp_put_exp_f
981: ALIGN
982: //
983: //pre_rat_appx
984: //
985: exp_branch_1:
986: movl $15,dword_expon1
987: call left_shift_frac1_8
988: exp_rat_appx:
989: call move_frac1_cop
990: //
991: //80287 short multiply (does 67-bit by 34-bit multiplication only).
992: //
993: movb $30,%cl
994: call right_shift_frac1_cl
995: and $0,dword_frac1(%ebp)
996: movb $30,%cl
997: call left_shift_frac1_cl
998: call mulx
999: call move_result_frac1
1000: andl $0x0e0000000,dword_frac1(%ebp)
1001: mov $constant_ln2_ov_6,%esi
1002: call mul_frac2
1003: mov dword_expon1,%ecx
1004: add $10,%ecx
1005: call right_shift_result_cl
1006: andl $0x0ffe00000,result_dword_frac(%ebp)
1007: call move_cop_frac1
1008: call right_shift_frac1_8
1009: call move_result_frac2
1010: call subx
1011: mov dword_expon1,%ecx
1012: inc %ecx
1013: call right_shift_result_cl
1014: andl $0x0ffe00000,result_dword_frac(%ebp)
1015: call move_result_frac2
1016: mov $constant_2_ov_ln2,%esi
1017: call sub_frac1
1018: call move_cop_frac1
1019: call move_result_frac2
1020: call left_shift_frac2_8
1021: // the following call used to be to divx instead of accel_divx:
1022: call accel_divx
1023: mov $8,%ecx
1024: call right_shift_result_cl
1025: andl $0x0ffe00000,result_dword_frac(%ebp)
1026:
1027: //
1028: //pseudo_multiply
1029: //
1030: exp_loop_back_2:
1031: shrw $1,siso
1032: jnb exp_merge_2
1033: call move_result_frac1
1034: call move_result_frac2
1035: mov dword_expon1,%ecx
1036: call right_shift_frac2_cl
1037: andl $0x0ffe00000,dword_frac2(%ebp)
1038: orw $0x80,8+word_frac2
1039: call addx
1040: exp_merge_2:
1041: cmpw $0,siso
1042: je exp_almost_end
1043: call right_shift_result_1
1044: andl $0x0ffe00000,result_dword_frac(%ebp)
1045: decl dword_expon1
1046: jmp exp_loop_back_2
1047: ALIGN
1048: exp_almost_end:
1049: movb $8,%cl
1050: cmpb $0,msb_result
1051: je exp_merge_3
1052: movb $7,%cl
1053: decl dword_expon1
1054: exp_merge_3:
1055: call left_shift_result_cl
1056: mov $0x3fff,%eax
1057: sub dword_expon1,%eax
1058: mov %eax,dword_result_expon
1059: // mov positive+valid\*0x10000,result_sign(%ebp)
1060: movl $0x10000*VALID+POSITIVE,result_sign(%ebp)
1061: testb $0x80,msb_result
1062: jne exp_add_half_round
1063: //
1064: //normalize x
1065: //
1066: movb $1,%cl
1067: call left_shift_result_cl
1068: decl dword_result_expon
1069: exp_add_half_round:
1070: call move_result_frac1
1071: call add_half1_frac2
1072: exp_put_exp_f:
1073: ret
1074:
1075: //exp_core endp
1076: // **********************************************************************
1077: ALIGN
1078: neg_exp_core: //proc
1079: notb sign1(%ebp)
1080: call exp_core
1081: lea result_dword_frac(%ebp),%esi
1082: lea dword_frac2(%ebp),%edi
1083: call move_op_to_op
1084: mov $offset_operand1,%esi
1085: call move_unpacked_1_to_esi
1086: movb negative,sign1(%ebp)
1087: movb $sub_op,operation_type(%ebp)
1088: mov $offset_result,%esi
1089: call push_5_dw_at_esi
1090: call subadd
1091: call post_op_round
1092: lea result_dword_frac(%ebp),%esi
1093: lea dword_frac2(%ebp),%edi
1094: call move_op_to_op
1095: mov $offset_operand1,%esi
1096: call pop_5_dw_at_esi
1097: call divid // floating-point divide
1098: call post_op_round
1099: exp_neg_core_exit:
1100: ret
1101:
1102: //neg_exp_core endp
1103: // **********************************************************************
1104: ALIGN
1105: exp: //proc
1106: call one_result_op1_chk
1107: jnz exp_non_zero
1108: garb_out:
1109: jmp put_op1_result
1110: ALIGN
1111: //
1112: exp_non_zero:
1113: cmpl $0x3fff,dword_expon1
1114: jg garb_out
1115: jl more_than_half_
1116: more_than_1_:
1117: cmpl $0x080000000,dword_frac1+frac32(%ebp)
1118: ja garb_out
1119: cmp $0,dword_frac1+frac64(%ebp)
1120: jne garb_out
1121: cmpb positive,sign1(%ebp)
1122: je garb_out // answer is 1, already in op1
1123: decl dword_expon1
1124: jmp garb_out // answer is -1/2.
1125: ALIGN
1126: more_than_half_:
1127: orb $inexact_mask,%gs:sr_errors // set inexact error flag
1128: push %gs:sr_masks // save precision control
1129: orl $0x0300,%gs:sr_masks // set precision control to prec64
1130: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest
1131: cmpl $0x3ffe,dword_expon1
1132: je maybe_half
1133: cmpb positive,sign1(%ebp)
1134: jne tween_neg_half_and_0
1135: jmp tween_0_and_half
1136: ALIGN
1137: maybe_half:
1138: cmpl $0x080000000,dword_frac1+frac32(%ebp)
1139: ja tween_half_and_1
1140: cmp $0,dword_frac1+frac64(%ebp)
1141: jne tween_half_and_1
1142: cmpb positive,sign1(%ebp)
1143: jne tween_neg_half_and_0
1144: tween_0_and_half:
1145: call exp_core
1146: //
1147: //error checking
1148: //
1149: exp_uflow_:
1150: mov dword_result_expon,%ecx
1151: cmp $0,%ecx
1152: jle exp_underflow
1153: movb valid,result_tag(%ebp) //valid result
1154: jmp exp_exit
1155: ALIGN
1156: exp_underflow:
1157: call underflow_response
1158: orb underflow_mask,%gs:sr_errors
1159: exp_exit:
1160: cmpb true,added_one
1161: jne exp_restore
1162: orb $a_mask,%gs:sr_flags
1163: exp_restore:
1164: pop %gs:sr_masks // restore precision and rounding controls
1165: mov $offset_result,%edi
1166: jmp put_si_result
1167: ALIGN
1168: tween_neg_half_and_0:
1169: call neg_exp_core
1170: jmp exp_uflow_
1171: ALIGN
1172: tween_half_and_1:
1173: cmpb positive,sign1(%ebp)
1174: jne tween_neg_1_and_neg_half
1175: mov $offset_operand2,%esi
1176: call move_unpacked_1_to_esi
1177: movb $sub_op,operation_type(%ebp)
1178: call subadd
1179: call post_op_round
1180: lea result_dword_frac(%ebp),%esi
1181: lea dword_frac1(%ebp),%edi
1182: call move_op_to_op
1183: call neg_exp_core
1184: lea result_dword_frac(%ebp),%esi
1185: lea dword_frac1(%ebp),%edi
1186: call move_op_to_op
1187: mov $offset_operand2,%esi
1188: call move_unpacked_1_to_esi
1189: movb $add_op,operation_type(%ebp)
1190: call subadd
1191: call post_op_round
1192: incl dword_result_expon
1193: lea result_dword_frac(%ebp),%esi
1194: lea dword_frac1(%ebp),%edi
1195: call move_op_to_op
1196: mov $offset_operand2,%esi
1197: call move_unpacked_1_to_esi
1198: movb $sub_op,operation_type(%ebp)
1199: call subadd
1200: call post_op_round
1201: jmp exp_exit
1202: ALIGN
1203: tween_neg_1_and_neg_half:
1204: mov $offset_operand2,%esi
1205: call move_unpacked_1_to_esi
1206: movb $add_op,operation_type(%ebp)
1207: call subadd
1208: call post_op_round
1209: lea result_dword_frac(%ebp),%esi
1210: lea dword_frac1(%ebp),%edi
1211: call move_op_to_op
1212: call exp_core
1213: lea result_dword_frac(%ebp),%esi
1214: lea dword_frac1(%ebp),%edi
1215: call move_op_to_op
1216: mov $offset_operand2,%esi
1217: call move_unpacked_1_to_esi
1218: movb $add_op,operation_type(%ebp)
1219: call subadd
1220: call post_op_round
1221: lea result_dword_frac(%ebp),%esi
1222: lea dword_frac1(%ebp),%edi
1223: call move_op_to_op
1224: decl dword_expon1
1225: mov $offset_operand2,%esi
1226: call move_unpacked_1_to_esi
1227: movb $sub_op,operation_type(%ebp)
1228: call subadd
1229: call post_op_round
1230: jmp exp_exit
1231: ALIGN
1232:
1233: //exp endp
1234: // ***********************************************************************
1235: //
1236: // ***************************************************************************
1237: // log:
1238: // ***
1239: // function:
1240: // calculates y times log(x) or y times log(1 + x).
1241: //
1242: // inputs:
1243: // assumes that operand1 and operand2 are set up;
1244: // op1 = x, op2 = y.
1245: //
1246: // outputs:
1247: // possible underflow, overflow, or inexact errors
1248: //
1249: // data accessed:
1250: // - operation_type offset_result_rec
1251: // - sign1 expon1
1252: // - offset_operand1 offset_operand2
1253: // - tag2 sign2
1254: // - expon2 word_frac2
1255: // - msb_frac2 offset_operand2
1256: // - offset_result result_tag
1257: // - result_sign result_expon
1258: // - result_word_frac msb_result
1259: // - msb_result offset_result
1260: // - result2_tag result2_sign
1261: // - msb_result2 log_loop_ct
1262: // - offset_cop offset_dop
1263: // - siso
1264: //
1265: // data changed:
1266: // - sign1 sign2
1267: // - msb_frac2 word_frac2
1268: // - result_tag result_sign
1269: // - result_frac offset_result
1270: // - result2_tag result2_sign
1271: // - msb_result2 log_loop_ct
1272: // - siso
1273: //
1274: // procedures called:
1275: // put_result right_shift left_shift
1276: // move_10_bytes move_constant addx
1277: // subx mulx accel_divx (for log_divx)
1278: // one_left_normalize addition_normalize log_constant
1279: // test_5w subtraction_normalize test_4w
1280: // underflow_response overflow_response decompose
1281: // pop_free sp_subadd mult
1282: // round get_precision set_p_error
1283: //
1284: // ***********************************************************************
1285: ALIGN
1286: log: //proc
1287: movb valid,result2_tag(%ebp)
1288: jmp log_entry
1289: ALIGN
1290: splog:
1291: movb special,result2_tag(%ebp) // flag for special log
1292: log_entry:
1293: push %gs:sr_masks // save precision control
1294: // and dword ptr %gs:sr_masks, 0fffff3ffh; set rounding control to nearest
1295: orl $0x0300,%gs:sr_masks // set precision control to prec64
1296: mov $offset_cop+frac80,%edi
1297: call move_frac2 // temp store y, cop <- frac(y)
1298: movb tag2(%ebp),%al
1299: movb %al,lsb_cop
1300: mov dword_expon2,%eax // log_loop_ct <- expo(y)
1301: mov %eax,log_loop_ct
1302: movb sign2(%ebp),%al // lsb_result2 <- sign2
1303: movb %al,lsb_result2
1304: movb positive,result2_sign(%ebp)// used for sign of result
1305: cmpb valid,result2_tag(%ebp) // after log core
1306: jnz log_special_log // result sign same as result2
1307: call right_shift_frac1_8
1308: mov $constant_sqrt_of_2,%esi
1309: call sub_frac2
1310: cmpb $0,msb_result
1311: jne log_small_lg
1312: jmp log_large_lg
1313: ALIGN
1314: log_sp_negative_x:
1315: call move_frac1_result
1316: movb negative,result2_sign(%ebp)
1317: jmp log_core
1318: ALIGN
1319: log_special_log:
1320: // mov edi, offset_operand1 ; weed out the special case
1321: // call test_6w ; where x = 0. result should
1322: // jz log_splog_zero ; be exact signed zero.
1323: mov dword_expon1,%eax // log x not 0
1324: mov %eax,dword_result_expon
1325: cmpb positive,sign1(%ebp)
1326: jne log_sp_negative_x
1327: call move_frac1_frac2
1328: mov $0x3fff,%ecx
1329: sub dword_expon1,%ecx
1330: cmp $72,%ecx
1331: jbe log_sp_label_1
1332: mov $72,%ecx
1333: log_sp_label_1:
1334: call right_shift_frac2_cl
1335: movw word_frac2,%cx
1336: and $0x1fff,%ecx
1337: or %ecx,%edx
1338: jz log_non_sticky
1339: orw $0x2000,word_frac2
1340: log_non_sticky:
1341: orb $0x80,msb_frac2
1342: andl $0x0e0000000,dword_frac2(%ebp)
1343: jmp log_div
1344: ALIGN
1345: //
1346: // frac(x) < sqrt(2)
1347: //
1348: log_small_lg:
1349: call left_shift_frac1_8
1350: call move_frac1_result
1351: mov $1,%ecx
1352: call left_shift_result_cl
1353: mov $offset_result+frac80,%edi
1354: call test_5w
1355: jz log_power_of_two
1356: movl $0x3ffe,dword_result_expon
1357: mov $offset_result,%edi
1358: call subtraction_normalize
1359: call move_frac1_frac2
1360: call move_result_frac1
1361: log_div:
1362: // the following call used to be to log_divx instead of accel_divx:
1363: push log_loop_ct
1364: call accel_divx
1365: pop log_loop_ct
1366: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac
1367: jmp log_merge_lg
1368: ALIGN
1369: //
1370: // x = 2 ** n
1371: //
1372: log_power_of_two:
1373: call decompose
1374: log_mul:
1375: mov $offset_operand1+frac80,%edi
1376: call test_5w
1377: jnz log_x_not_0
1378: // call log_round ; round the result
1379: log_splog_zero:
1380: movb special,tag1(%ebp) // zero tag
1381: movb lsb_result2,%al
1382: xorb %al,sign1(%ebp)
1383: lea dword_frac1(%ebp),%esi
1384: lea result_dword_frac(%ebp),%edi
1385: call move_op_to_op
1386: jmp log_restore_user_controls
1387: ALIGN
1388: log_x_not_0:
1389: // cmp lsb_cop, special
1390: // jne log_y_not_zero
1391: //
1392: //y=0
1393: //
1394: // xor eax, eax
1395: // mov edi, offset result_dword_frac + 4
1396: // call set_4w
1397: // mov dword_result_expon, eax
1398: // mov dword ptr (ebp).result_sign, special*10000h
1399: // mov al, (ebp).sign1
1400: // xor al, lsb_result2
1401: // mov (ebp).result_sign, al
1402: // jmp short log_finish_up
1403: //log_y_not_zero:
1404: andl $0x0ff000000,dword_cop(%ebp)
1405: call move_cop_frac2 // restore y into op2
1406: mov log_loop_ct,%eax
1407: mov %eax,dword_expon2
1408: movb lsb_result2,%al
1409: movb %al,sign2(%ebp)
1410: call mult
1411: call post_op_round // round the result
1412: //
1413: //error checking
1414: //
1415: mov dword_result_expon,%eax
1416: cmp $0x7ffe,%eax
1417: jg log_overflow
1418: cmp $0,%eax
1419: jl log_underflow
1420: jg log_set_tag_valid
1421: mov $offset_result+frac64,%edi
1422: call test_4w // eax = 0 here
1423: jnz log_underflow
1424: //
1425: //zero result
1426: //
1427: movb special,result_tag(%ebp)
1428: jmp log_round_report
1429: ALIGN
1430: log_set_tag_valid:
1431: movb valid,result_tag(%ebp)
1432: log_round_report:
1433: cmpw $0,rnd_history
1434: je log_restore_user_controls
1435: orb $inexact_mask,%gs:sr_errors
1436: cmpb true,added_one
1437: jne log_restore_user_controls
1438: orb $a_mask,%gs:sr_flags
1439: log_restore_user_controls:
1440: pop %gs:sr_masks
1441: log_exit:
1442: ret
1443: ALIGN
1444: //
1445: log_overflow:
1446: call overflow_response
1447: jmp log_restore_user_controls
1448: ALIGN
1449: log_underflow:
1450: call underflow_response
1451: jmp log_restore_user_controls
1452: ALIGN
1453: //
1454: //frac(x) > sqrt(2)
1455: //
1456: log_large_lg:
1457: incl dword_expon1
1458: call move_frac1_frac2
1459: mov $constant_one,%esi
1460: call sub_frac1
1461: mov $7,%ecx
1462: call left_shift_result_cl
1463: movb negative,result2_sign(%ebp) // set flag for large log
1464: movl $0x3fff,dword_result_expon
1465: log_merge_lg:
1466: mov $offset_result+frac80,%edi // dont normalize a zero
1467: call test_5w // is the result zero?
1468: jz log_core // yes, no need to normalize
1469: mov $offset_result,%edi
1470: call subtraction_normalize
1471: log_core:
1472: call move_result_frac2
1473: movw $0,siso // clear siso
1474: mov $0x3fff,%eax
1475: sub dword_result_expon,%eax
1476: mov %eax,dword_exp_tmp
1477: cmp $15,%eax
1478: ja log_rat_apx
1479: call move_result_frac1 // log pseudo divide
1480: mov $7,%ecx
1481: add dword_exp_tmp,%ecx
1482: call right_shift_frac1_cl
1483: call right_shift_frac2_8
1484: call addx
1485: cmpb $0,msb_result
1486: je log_loop_back_1
1487: andl $0x0ffe00000,result_dword_frac(%ebp)
1488: movb $0,msb_result
1489: call move_result_frac2
1490: movw $1,siso
1491: log_loop_back_1:
1492: shlw $1,siso
1493: call move_frac2_frac1
1494: mov dword_exp_tmp,%ecx
1495: call right_shift_frac1_cl
1496: orl $0x00800000,dword_frac1+frac32(%ebp)
1497: call addx
1498: cmpb $0,msb_result
1499: je log_merge_2
1500: andl $0x0ffe00000,result_dword_frac(%ebp)
1501: movb $0,msb_result
1502: call move_result_frac2
1503: incw siso
1504: log_merge_2:
1505: mov $1,%ecx
1506: call left_shift_frac2_cl
1507: incl dword_exp_tmp
1508: cmp $15,dword_exp_tmp
1509: jbe log_loop_back_1
1510: call left_shift_frac2_8
1511: //
1512: //rational approximation
1513: //
1514: log_rat_apx:
1515: orb $inexact_mask,%gs:sr_errors // set p flag
1516: call move_frac2_frac1
1517: call mulx
1518: mov dword_exp_tmp,%ecx
1519: cmp $72,%ecx
1520: jbe log_label_4
1521: mov $72,%ecx
1522: log_label_4:
1523: call right_shift_result_cl
1524: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac
1525: call move_result_frac2
1526: call subx
1527: call move_result_dop
1528: mov dword_exp_tmp,%ecx
1529: cmp $72,%ecx
1530: jbe log_label_5
1531: mov $72,%ecx
1532: log_label_5:
1533: call right_shift_frac1_cl
1534: andl $0x0e0000000,dword_frac1(%ebp)
1535: call move_frac1_frac2
1536: mov $constant_six,%esi
1537: call sub_frac1
1538: call move_result_frac1
1539: call move_dop_frac2
1540: mov dword_exp_tmp,%ecx
1541: inc %ecx
1542: cmp $72,%ecx
1543: jbe log_label_6
1544: mov $72,%ecx
1545: log_label_6:
1546: call right_shift_frac2_cl
1547: andl $0x0f0000000,dword_frac2(%ebp)
1548: call subx
1549: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac
1550: call move_dop_frac1
1551: call move_result_frac2
1552: // the following call used to be to log_divx instead of accel_divx:
1553: push log_loop_ct
1554: call accel_divx
1555: pop log_loop_ct
1556: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac
1557: call move_result_frac1
1558: mov $constant_3_ov_ln2,%esi
1559: call mul_frac2
1560: mov $7,%ecx
1561: call right_shift_result_cl
1562: decl dword_exp_tmp
1563: log_loop_back_2:
1564: shrw $1,siso
1565: jnb log_no_carry
1566: mov dword_exp_tmp,%esi
1567: dec %esi
1568: mov $10,%eax
1569: mul %esi
1570: mov %eax,%esi
1571: add $log_constant,%esi
1572: call move_constant_frac2
1573: call move_result_frac1
1574: call addx
1575: log_no_carry:
1576: cmpw $0,siso
1577: jz log_end_loop
1578: call right_shift_result_1
1579: decl dword_exp_tmp
1580: jmp log_loop_back_2
1581: ALIGN
1582: log_end_loop:
1583: mov $0x4007,%eax //4007 = 3fff + 8
1584: sub dword_exp_tmp,%eax
1585: mov %eax,dword_result_expon
1586: andl $0x0ffe00000,result_dword_frac(%ebp)
1587: mov $offset_result,%edi // dont normalize a zero
1588: call test_6w // is the result zero?
1589: jz log_end_log_core // yes, no need to normalize
1590: mov $offset_result,%edi
1591: call subtraction_normalize
1592: log_end_log_core:
1593: cmpb valid,result2_tag(%ebp)
1594: jnz log_special_log_end
1595: call decompose
1596: call move_result_frac2
1597: mov dword_result_expon,%eax
1598: mov %eax,dword_expon2
1599: movb $add_op,operation_type(%ebp)
1600: movb result2_sign(%ebp),%al
1601: movb %al,sign2(%ebp)
1602: call sp_subadd
1603: log_merge_4:
1604: call move_result_frac1
1605: movb result_sign(%ebp),%al
1606: movb %al,sign1(%ebp)
1607: mov dword_result_expon,%eax
1608: mov %eax,dword_expon1
1609: jmp log_mul
1610: ALIGN
1611: log_special_log_end:
1612: movb result2_sign(%ebp),%al
1613: movb %al,result_sign(%ebp)
1614: jmp log_merge_4
1615: ALIGN
1616: //
1617: //do round ; made into common subroutine for all
1618: //
1619: log_round:
1620: movb $1,lsb_result // fixed up such that
1621: // call get_precision
1622: post_op_round:
1623: movb prec64,%dl
1624: mov $offset_result,%edi // s = 1 always
1625: movb false,%al // not second rounding
1626: call round
1627: mov $offset_result,%edi
1628: movb $4,%ah // fall through
1629: //log endp
1630: //
1631: //
1632: // addition_normalize:
1633: //
1634: // function:
1635: // performs normalization after addition if necessary.
1636: //
1637: // inputs:
1638: // carry-out from addition in al upon entry.
1639: // fraction offset in di.
1640: //
1641: // outputs:
1642: // increments exponent and shifts 1 bit in from left if al=1.
1643: //
1644: // data accessed:
1645: //
1646: // data changed:
1647: //
1648: // procedures called:
1649: // sticky_right_shift
1650: //
1651: // *************************************************************************
1652: FALLSTHRU
1653: addition_normalize: //proc
1654: testb $0x01,%al //if low bit of al = 1,
1655: jnz right_shift_1 // then shift right 1
1656: ret // else, exit
1657: ALIGN
1658: right_shift_1:
1659: incl expon(%ebp,%edi) //increment exponent
1660: movb $1,%cl //shift right 1 bit
1661: //addition_normalize endp ; sticky_right_shift
1662: //
1663: // ***********************************************************************
1664: // sticky_right_shift:
1665: // ******************
1666: // function:
1667: // shifts a 10-byte number right by amount in
1668: // cl register. di contains offset of number.
1669: //
1670: // inputs:
1671: // low bit of al contains bit to inject from left.
1672: // (for shifts of more than one, the result is undefined
1673: // unless al contains zero).
1674: //
1675: // outputs:
1676: // the low-order bit of the number is *sticky*, ie, it is
1677: // left as a one if any ones were shifted out.
1678: //
1679: // data accessed:
1680: //
1681: // data changed:
1682: //
1683: // procedures called:
1684: // right_shift
1685: //
1686: // ***************************************************************************
1687: FALLSTHRU
1688: sticky_right_shift: //proc
1689: call right_shift //do right shift
1690: and %edx,%edx //edx <> 0 if 1s lost
1691: jz sticky_right_shift_done //done if no 1s lost
1692: orb $0x01,frac80(%ebp,%edi) //else, set sticky bit
1693: sticky_right_shift_done:
1694: ret
1695: //sticky_right_shift endp
1696: //
1697: // ************************************************************************
1698: // gradual_underflow:
1699: //
1700: // function:
1701: // changes an *underflowed* number to a legal,
1702: // denormalized number.
1703: //
1704: // input:
1705: // address of exponent and fraction in operands or result
1706: // (ptr in di register); minimum legal exponent(in
1707: // ax register).
1708: //
1709: // output:
1710: // denormalized fraction and adjusted exponent (in input
1711: // record)
1712: //
1713: // data accessed:; - expon word_frac
1714: //
1715: // data changed:
1716: // - expon word_frac
1717: //
1718: // procedures called:
1719: // sticky_right_shift
1720: //
1721: // ***********************************************************************
1722: ALIGN
1723: gradual_underflow: //proc
1724: mov %eax,%ecx // set exponent to minimum
1725: xchg expon(%ebp,%edi),%eax
1726: sub %eax,%ecx // form shift amount
1727: cmp $67,%ecx // (exponent - minimum exponent)
1728: jle do_right_shift
1729: mov $67,%ecx // shift amount must be <= 67
1730: do_right_shift:
1731: xorb %al,%al // byte to be shifted in from
1732: jmp sticky_right_shift // the left
1733: ALIGN
1734: //gradual_underflow endp
1735:
1736:
1737: // ******************************************************************************
1738: // two_result_op1_chk
1739: //
1740: // action:
1741: // for sincos and (two result) tan, checks the following and responds as
1742: // described:
1743: // 1. whether fetch_an_op discovered that the source from which
1744: // operand1 was to have been taken was empty. if so, sets stack
1745: // underflow exception, clears c-flag (indicating not incomplete
1746: // reduction), pops the return address of its caller so that it
1747: // returns directly to the e80387 executive routine, and, if the
1748: // invalid exception is unmasked, makes that return forthwith.
1749: // if the invalid exception is masked, this procedure prepares to
1750: // return via a jump to put_result by first setting edi so that
1751: // the nan indefinite put in operand1 by fetch_an_op will be
1752: // returned, and setting esi so that this returned value will be
1753: // pushed onto the stack. note that after this push, the former
1754: // stack top is unchanged; i.e., if it was empty as stack top, its
1755: // still empty as st(1).
1756: // 2. if operand1 was fetched from a non-empty source, clears
1757: // c-flag (indicating not incomplete reduction) and then checks
1758: // whether a push will be to a full position. if so, sets zf so
1759: // that return to e80387 executive after popping callers return
1760: // address and jumping to put_result does not falsely signal
1761: // masked stack underflow instead of correctly signaling stack
1762: // overflow.
1763: // 3. if push would be to an empty position, initializes the
1764: // before_error_signals used by put_result, clears the a-flag,
1765: // and checks tag of operand1.
1766: // a. if tag is unsupp or infinty, replaces operand1 by
1767: // the nan indefinite, then checks whether invalid operation
1768: // is masked. if not masked, sets invalid operation exception
1769: // flag and pops callers return address so that return is to
1770: // e80387 executive. if masked, copies the quiet nan in
1771: // operand1 to operand2, sets the signal_i_error? component of
1772: // before_error_signals to true, and returns to e80387
1773: // executive by popping callers return address and jumping to
1774: // do_exchange.
1775: // b. if tag is inv, checks whether the nan in operand1 is
1776: // signaling. if not, sets zf, pops callers return address,
1777: // sets edi and esi so that jump to put_result causes the
1778: // quiet nan in operand1 to be pushed onto 87 stack. if the
1779: // nan is signaling, sets its leading fraction bit, thereby
1780: // *quieting* it, and proceeds as in *a* above, but with the
1781: // *quietized* nan in place of the nan indefinite.
1782: // c. if tag is denormd, checks whether denormal exception
1783: // is masked. if not masked, sets denormal exception flag and
1784: // pops callers return address so that return is to e80387
1785: // executive. if masked, sets the signal_d_error component of
1786: // before_error_signals to true, normalizes operand1 and forces
1787: // zf = 0 (indicating non-zero operand1) before returning to
1788: // caller.
1789: // d. if tag is valid or special (signed, true zero), returns
1790: // to caller with zf clear or set, respectively.
1791: //
1792: //
1793: // ****************************************************************************
1794: ALIGN
1795: two_result_op1_chk: //proc
1796: jz is_stack_full_ // if no stack underflow, go on
1797: call set_stk_u_error // else, prepare for error exit
1798: andb $~c_mask,%gs:sr_flags // clear 87 c-flag
1799: testb invalid_mask,%gs:sr_masks
1800: jnz push_op1 // masked stack error, so return indef
1801: unmasked_exit:
1802: pop %eax // pop address of transcendental caller so
1803: two_res_quik_exit: // return is to e80387 executive procedure.
1804: ret
1805: ALIGN
1806: push_op1:
1807: mov $offset_operand1,%edi
1808: mov offset_result2_rec,%esi
1809: pop %eax // pop address of transcendental caller
1810: lahf // save zf to show if masked stack underflow
1811: jmp put_result // return is to e80387 executive procedure.
1812: ALIGN
1813: is_stack_full_:
1814: andb $~c_mask,%gs:sr_flags // clear 87 c-flag
1815: call stack_full_
1816: jz cntnu_chk
1817: set_zf:
1818: xor %eax,%eax
1819: jmp push_op1
1820: ALIGN
1821: cntnu_chk:
1822: movl $0,before_error_signals(%ebp)
1823: andb $~a_mask,%gs:sr_flags
1824: movb tag1(%ebp),%al // load tag for op1
1825: cmpb special,%al
1826: jbe ok_op
1827: cmpb denormd,%al
1828: jb inv_op
1829: je signal_d_error // elsif denormalized, then signal d_error
1830: mov $offset_operand1,%edi // infinity or unsupported,
1831: call set_up_indefinite // set up masked result
1832: jmp test_invalid_mask
1833: ALIGN
1834: inv_op:
1835: testb $0x40,msb_frac1 // elsif op1 nan, find what kind
1836: jnz set_zf // op1 is a qnan, so load it to tos
1837: orb $0x40,msb_frac1 // make nan quiet
1838: test_invalid_mask:
1839: testb invalid_mask,%gs:sr_masks
1840: jnz copy_nan
1841: orb invalid_mask,%gs:sr_errors
1842: jmp unmasked_exit
1843: ALIGN
1844: copy_nan:
1845: lea dword_frac1(%ebp),%esi // copy op1 to op2
1846: lea dword_frac2(%ebp),%edi
1847: call move_op_to_op
1848: signal_i_error:
1849: movb true,signal_i_error_
1850: pop %eax
1851: jmp do_exchange
1852: ALIGN
1853: signal_d_error:
1854: testb denorm_mask,%gs:sr_masks
1855: jnz set_up_d_error
1856: orb denorm_mask,%gs:sr_errors
1857: jmp unmasked_exit
1858: ALIGN
1859: set_up_d_error:
1860: movb true,signal_d_error_// op1 is denormal or pseudo-denormal
1861: mov $offset_operand1,%edi
1862: call norm_denorm // if d_error masked, make valid
1863: or $1,%eax // force zf = 0
1864: ok_op:
1865: ret // zf = 1 iff op1 is true zero
1866:
1867: //two_result_op1_chk endp
1868: //
1869: // ******************************************************************************
1870: // one_result_op1_chk
1871: //
1872: // action:
1873: // for sin and cos, checks the following and responds as
1874: // described:
1875: // 1. whether fetch_an_op discovered that the source from which
1876: // operand1 was to have been taken was empty. if so, sets stack
1877: // underflow exception, clears c-flag (indicating not incomplete
1878: // reduction), pops the return address of its caller so that it
1879: // returns directly to the e80387 executive routine, and, if the
1880: // invalid exception is unmasked, makes that return forthwith.
1881: // if the invalid exception is masked, this procedure prepares to
1882: // return via a jump to put_result by first setting edi so that
1883: // the nan indefinite put in operand1 by fetch_an_op will be
1884: // returned, and setting esi so that this returned value will be
1885: // pushed onto the stack. note that after this push, the former
1886: // stack top is unchanged; i.e., if it was empty as stack top, its
1887: // still empty as st(1).
1888: // 2. if operand1 was fetched from a non-empty source, clears
1889: // c-flag (indicating not incomplete reduction) and then checks
1890: // whether a push will be to a full position. if so, sets zf so
1891: // that return to e80387 executive after popping callers return
1892: // address and jumping to put_result does not falsely signal
1893: // masked stack underflow instead of correctly signaling stack
1894: // overflow.
1895: // 3. if push would be to an empty position, initializes the
1896: // before_error_signals used by put_result, clears the a-flag,
1897: // and checks tag of operand1.
1898: // a. if tag is unsupp or infinty, replaces operand1 by
1899: // the nan indefinite, then checks whether invalid operation
1900: // is masked. if not masked, sets invalid operation exception
1901: // flag and pops callers return address so that return is to
1902: // e80387 executive. if masked, copies the quiet nan in
1903: // operand1 to operand2, sets the signal_i_error? component of
1904: // before_error_signals to true, and returns to e80387
1905: // executive by popping callers return address and jumping to
1906: // do_exchange.
1907: // b. if tag is inv, checks whether the nan in operand1 is
1908: // signaling. if not, sets zf, pops callers return address,
1909: // sets edi and esi so that jump to put_result causes the
1910: // quiet nan in operand1 to be pushed onto 87 stack. if the
1911: // nan is signaling, sets its leading fraction bit, thereby
1912: // *quieting* it, and proceeds as in *a* above, but with the
1913: // *quietized* nan in place of the nan indefinite.
1914: // c. if tag is denormd, checks whether denormal exception
1915: // is masked. if not masked, sets denormal exception flag and
1916: // pops callers return address so that return is to e80387
1917: // executive. if masked, sets the signal_d_error component of
1918: // before_error_signals to true, normalizes operand1 and forces
1919: // zf = 0 (indicating non-zero operand1) before returning to
1920: // caller.
1921: // d. if tag is valid or special (signed, true zero), returns
1922: // to caller with zf clear or set, respectively.
1923: //
1924: //
1925: // ****************************************************************************
1926: ALIGN
1927: one_result_op1_chk: //proc
1928: jz check_tag1 // if no stack underflow, go on
1929: call set_stk_u_error // else, prepare for error exit
1930: andb $~c_mask,%gs:sr_flags // clear 87 c-flag
1931: testb invalid_mask,%gs:sr_masks
1932: jnz give_op1 // masked stack error, so return indef
1933: one_res_unmasked_exit:
1934: pop %eax // pop address of transcendental caller so
1935: one_res_quik_exit: // return is to e80387 executive procedure.
1936: ret
1937: ALIGN
1938: give_op1:
1939: pop %eax // pop address of transcendental caller so
1940: jmp put_op1_result // return is to e80387 executive procedure.
1941: ALIGN
1942: check_tag1:
1943: andb $~(a_mask+c_mask),%gs:sr_flags
1944: movb tag1(%ebp),%al // load tag for op1
1945: cmpb special,%al
1946: jle op1_ok
1947: cmpb denormd,%al
1948: jl op1_inv
1949: je op1_den // elsif denormalized, then signal d_error
1950: cmpb $exp_op,operation_type(%ebp)
1951: jne one_res_unsup
1952: cmpb unsupp,%al
1953: je one_res_unsup
1954: cmpb positive,sign1(%ebp) // op1 is +/- infinity
1955: je give_op1
1956: movl $0x3fff,dword_expon1
1957: jmp give_op1
1958: ALIGN
1959: one_res_unsup:
1960: mov $offset_operand1,%edi // infinity or unsupported,
1961: call set_up_indefinite // set up masked result
1962: jmp invalid_masked_
1963: ALIGN
1964: op1_inv:
1965: testb $0x40,msb_frac1 // elsif op1 nan, find what kind
1966: jnz give_op1 // op1 is a qnan, so return it
1967: orb $0x40,msb_frac1 // make nan quiet
1968: invalid_masked_:
1969: orb invalid_mask,%gs:sr_errors
1970: testb invalid_mask,%gs:sr_masks
1971: jz one_res_unmasked_exit
1972: jmp give_op1
1973: ALIGN
1974: op1_den:
1975: orb denorm_mask,%gs:sr_errors
1976: testb denorm_mask,%gs:sr_masks
1977: jz one_res_unmasked_exit
1978: mov $offset_operand1,%edi
1979: call norm_denorm // if d_error masked, make valid
1980: or $1,%eax // force zf = 0
1981: op1_ok:
1982: ret // zf = 1 iff op1 is true zero
1983:
1984: //one_result_op1_chk endp
1985: // ****************************************************************************
1986: ALIGN
1987: mod_qrtr_pi: //proc
1988: // 87 c-flag has been cleared by this point
1989: xor %eax,%eax
1990: movb operation_type(%ebp),%al
1991: movb sign1(%ebp),%ah
1992: mov %eax,trans_info // initialize cofunc_flag false (00h)
1993: // and cos_sign positive (00h)
1994: movb positive,sign1(%ebp)// take absolute value of op1
1995: movw $0,exp_tmp // initialize q and hi_q to 0.
1996: mov dword_expon1,%eax
1997: sub $0x3ffe,%eax
1998: jl reduction_done
1999: cmp $63,%eax
2000: jle do_reduction
2001: orb $c_mask,%gs:sr_flags // indicate incomplete reduction
2002: pop %eax // get rid of callers return address
2003: ret
2004: ALIGN
2005: do_reduction:
2006: movl $0x2168c235,dword_frac2+frac64(%ebp)
2007: movl $0x0c90fdaa2,dword_frac2+frac32(%ebp)
2008: movl $0x10000*VALID+POSITIVE,dword_frac2+sign(%ebp)
2009: movl $0x3ffe,dword_expon2
2010: sub %eax,dword_expon1
2011: inc %eax
2012: call remrx
2013: mov dword_frac1+frac64(%ebp),%eax
2014: or dword_frac1+frac32(%ebp),%eax
2015: jnz mod_not_0
2016: mov %eax,dword_frac1(%ebp) // here, eax = 0
2017: mov %eax,dword_expon1
2018: movl special,dword_frac1+tag(%ebp)
2019: jmp reduce_pi
2020: ALIGN
2021: mod_not_0:
2022: mov $offset_operand1,%edi
2023: call subtraction_normalize // returns with zf = 0.
2024: reduction_done:
2025: orb $inexact_mask,%gs:sr_errors // precision error unless zero mod
2026: //check_for_tan_op:
2027: // cmpb op_type, tan_op
2028: // je reduce_hapi
2029: reduce_pi:
2030: testb $4,q
2031: jz reduce_hapi
2032: notw res_signs // flip sign for both sin and cos
2033: reduce_hapi:
2034: testb $2,q
2035: jz reduce_qrpi
2036: notb cofunc_flag
2037: notb cos_sign
2038: // cmpb op_type, tan_op
2039: // jne reduce_qrpi
2040: // not sin_sign ; use sin_sign as tan_sign
2041: reduce_qrpi:
2042: testb $1,q
2043: jnz last_reduc
2044: ret // zf is set here
2045: ALIGN
2046: last_reduc:
2047: notb cofunc_flag // a zero mod will be changed here
2048: cmpb special,tag1(%ebp)
2049: jne mod_set_inexact
2050: cmpb $tan_op,op_type
2051: // je complementary_angle
2052: jne mod_set_inexact
2053: movb $0x80,msb_frac1
2054: movb valid,tag1(%ebp)
2055: movl $0x3fff,dword_expon1
2056: mov $offset_operand2,%esi
2057: call move_unpacked_1_to_esi
2058: add $4,%esp // get rid of return address
2059: jmp adjust_sign
2060: ALIGN
2061: mod_set_inexact: // a zero mod will be changed here
2062: orb $inexact_mask,%gs:sr_errors // to qrtr_pi, so precision error
2063: complementary_angle:
2064: movl $0,dword_frac2(%ebp)
2065: movl $0x2168c235,dword_frac2+frac64(%ebp)
2066: movl $0x0c90fdaa2,dword_frac2+frac32(%ebp)
2067: movl $0x10000*VALID+POSITIVE,dword_frac2+sign(%ebp)
2068: movl $0x3ffe,dword_expon2
2069: movb negative,sign1(%ebp)
2070: movb $add_op,operation_type(%ebp)
2071: call subadd
2072: push %gs:sr_masks
2073: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest
2074: call post_op_round
2075: pop %gs:sr_masks
2076: lea result_dword_frac(%ebp),%esi
2077: lea dword_frac1(%ebp),%edi
2078: call move_op_to_op
2079: ret
2080: //mod_qrtr_pi endp
2081: //
2082: // ******************************************************************************
2083: ALIGN
2084: tan_pseudo_divide: //proc
2085:
2086: movw $0,siso // clear siso
2087: mov %eax,dword_expon1
2088: cmp $16,%eax
2089: jg tan_rat_appx
2090: decl dword_expon1 // decrement expon1
2091: call right_shift_frac1_8
2092: tan_loop_back_1:
2093: mov $10,%eax
2094: mull dword_expon1
2095: add $tan_constant,%eax
2096: mov %eax,%esi
2097: call sub_frac2
2098: shlw $1,siso
2099: cmpb $0,msb_result
2100: jne tan_merge_0
2101: call move_result_frac1
2102: andl $0x0ffe00000,dword_frac1(%ebp)
2103: incw siso
2104: tan_merge_0:
2105: incl dword_expon1
2106: cmp $15,dword_expon1
2107: ja tan_branch_1
2108: call left_shift_frac1_1
2109: jmp tan_loop_back_1
2110: ALIGN
2111: tan_branch_1:
2112: call left_shift_frac1_8
2113: movl $0,dword_frac1(%ebp)
2114: tan_rat_appx:
2115: call move_frac1_cop // cop <- theta, cop tmp
2116: call mulx // theta * theta
2117: mov dword_expon1,%ecx
2118: shl $1,%ecx
2119: add $8,%ecx
2120: call right_shift_result_cl
2121: andl $0x0ff000000,result_dword_frac(%ebp) // 64 bits only
2122: call move_result_frac2
2123: mov $constant_c0h,%esi
2124: call sub_frac1 // x <- 1.1 - theta*theta
2125: call move_cop_frac2
2126: call right_shift_frac2_8
2127: call move_cop_frac1
2128: movb $9,%cl
2129: call right_shift_frac1_cl
2130: call move_result_cop // cop <- x
2131: call addx // y <- y + theta
2132: call right_shift_result_1
2133: call move_result_dop // dop <- y, dop
2134: decl dword_expon1 // is a 67 bits temp
2135: //
2136: //pseudo_multiply
2137: //
2138: tan_loop_back_2:
2139: shrw $1,siso
2140: jnb tan_merge_2
2141: call move_cop_frac1 // x
2142: call move_dop_frac2 // y
2143: call addx // x + y
2144: call move_result_dop // -> dop
2145: mov dword_expon1,%ecx
2146: shl $1,%ecx
2147: call right_shift_frac2_cl
2148: andl $0x0ffe00000,dword_frac2(%ebp)
2149: call subx // x - y*2(-2exp)
2150: call move_result_cop // -> cop
2151: andl $0x0ff000000,dword_cop(%ebp)
2152: tan_merge_2:
2153: cmpw $0,siso
2154: je tan_almost_end
2155: movb $1,%cl
2156: mov $offset_dop,%edi
2157: call right_shift_al0
2158: andl $0x0ffe00000,dword_dop(%ebp)
2159: decl dword_expon1
2160: jmp tan_loop_back_2
2161: ALIGN
2162: tan_almost_end:
2163: movb $8,%cl
2164: cmpb $0,msb_dop
2165: je tan_merge_3
2166: movb $7,%cl
2167: decl dword_expon1
2168: tan_merge_3:
2169: mov $offset_dop+frac80,%edi
2170: call left_shift
2171: call move_dop_frac1
2172: mov $0x3fff,%eax
2173: sub dword_expon1,%eax
2174: mov %eax,dword_expon1
2175: //
2176: //normalize y
2177: //
2178: mov $offset_operand1,%edi
2179: call subtraction_normalize
2180: //
2181: //now x
2182: //
2183: call move_cop_frac2
2184: call left_shift_frac2_8
2185: movl $0x3fff,dword_expon2
2186: movl $0x10000*VALID+POSITIVE,sign2(%ebp)
2187: //
2188: //normalize x
2189: //
2190: mov $offset_operand2,%edi
2191: call subtraction_normalize
2192: ret
2193: //tan_pseudo_divide endp
2194: //
2195: // ******************************************************************************
2196: //
2197: // tan:
2198: //
2199: // function:
2200: // calculates y and x such that y/x = tan(theta)
2201: //
2202: // inputs:
2203: // assumes that operand1 is set up (theta).
2204: //
2205: // outputs:
2206: // results in result records; y = result, x = result2.
2207: // error checking done.
2208: //
2209: // data accessed:
2210: // - result_rec_offset result2_rec_offset
2211: // - offset_operand1 expon1
2212: // - word_frac1 lsb_frac1
2213: // - offset_operand1 offset_operand2
2214: // - sign2 tag2
2215: // - expon2 lsb_frac2
2216: // - msb_frac2 offset_operand2
2217: // - lsb_result msb_result
2218: // - offset_result siso
2219: // - offset_cop lsb_cop
2220: // - offset_dop lsb_dop
2221: // - msb_dop
2222: //
2223: // data changed:
2224: // - expon1 word_frac1
2225: // - lsb_frac1 sign2
2226: // - tag2 expon2
2227: // - lsb_frac2 msb_result
2228: // - lsb_cop lsb_dop
2229: // - siso
2230: //
2231: // procedures called:
2232: // do_exchange stack_full? right_shift
2233: // left_shift move_10_bytes move_constant
2234: // addx subx mulx
2235: // subtraction_normalize test_5w set_p_error
2236: //
2237: // ***********************************************************************
2238: ALIGN
2239: tan: //proc
2240: call two_result_op1_chk
2241: get_report:
2242: jnz reduce_op1
2243: zero_modulus:
2244: mov $offset_operand2,%esi
2245: call move_unpacked_1_to_esi
2246: jmp do_exchange
2247: ALIGN
2248: reduce_op1:
2249: call mod_qrtr_pi
2250: cmpb special,tag1(%ebp)
2251: jne tan_tiny_
2252: cmpb true,cofunc_flag
2253: jne zero_modulus
2254: movl $0,dword_frac1(%ebp)
2255: movl $0,dword_frac1+frac64(%ebp)
2256: movl $0x080000000,dword_frac1+frac32(%ebp)
2257: movl $0x10000*INFINITY+POSITIVE,dword_frac1+sign(%ebp)
2258: movl $0x7fff,dword_frac1+expon(%ebp)
2259: movb true,signal_z_error_
2260: jmp zero_modulus
2261: ALIGN
2262: tan_tiny_:
2263: mov $0x3fff,%eax
2264: sub dword_expon1,%eax
2265: cmp $63,%eax
2266: jle tan_calc
2267: tan_tiny_argument:
2268: cmp $0x3fff,%eax
2269: jl op2_gets_1
2270: movb sin_sign,%al
2271: movb %al,sign1(%ebp)
2272: orb underflow_mask,%gs:sr_errors
2273: testb underflow_mask,%gs:sr_masks
2274: jnz need_grad_uflow
2275: addl wrap_around_constant,dword_expon1
2276: jmp zero_modulus
2277: ALIGN
2278: need_grad_uflow:
2279: mov $offset_operand1,%edi
2280: mov $1,%eax
2281: call gradual_underflow
2282: movl $0,dword_expon1
2283: movb denormd,tag1(%ebp)
2284: jmp zero_modulus
2285: ALIGN
2286: op2_gets_1:
2287: mov $offset_operand2,%esi
2288: call move_unpacked_1_to_esi
2289: cmpb true,cofunc_flag
2290: jne adjust_sign // straight divide superfluous
2291: movw res_signs,%ax
2292: movb %al,sign1(%ebp)
2293: movb %ah,sign2(%ebp)
2294: push %gs:sr_masks
2295: // and dword ptr %gs:sr_masks, 0fffff3ffh ; set rc = to_nearest
2296: orl $0x0300,%gs:sr_masks // set precision control to prec64
2297: push trans_info
2298: jmp reverse_div
2299: ALIGN
2300: tan_calc:
2301: push %gs:sr_masks
2302: // and dword ptr %gs:sr_masks, 0fffff3ffh ; set rc = to_nearest
2303: orl $0x0300,%gs:sr_masks // set precision control to prec64
2304: push trans_info
2305: call tan_pseudo_divide
2306: pop trans_info
2307: cotan_:
2308: movw res_signs,%ax
2309: movb %al,sign1(%ebp)
2310: movb %ah,sign2(%ebp)
2311: push trans_info
2312: cmpb true,cofunc_flag
2313: jne straight_div
2314: reverse_div:
2315: call op1_into_op2
2316: jmp get_a_bit
2317: ALIGN
2318: straight_div:
2319: call op2_into_op1
2320: get_a_bit:
2321: cmpb true,added_one
2322: jne move_tan_result
2323: orb $a_mask,%gs:sr_flags
2324: move_tan_result:
2325: lea result_dword_frac(%ebp),%esi
2326: lea dword_frac1(%ebp),%edi
2327: call move_op_to_op
2328: mov $offset_operand2,%esi
2329: call move_unpacked_1_to_esi
2330: pop trans_info
2331: pop %gs:sr_masks
2332: adjust_sign:
2333: movb sin_sign,%al
2334: xorb cos_sign,%al
2335: movb %al,sign1(%ebp)
2336: jump_do_exchange:
2337: jmp do_exchange_leave_a_bit
2338: ALIGN
2339: //tan endp
2340: //
2341: // **********************************************************************
2342: //
2343: ALIGN
2344: swap_ops: //proc
2345: mov $offset_operand1,%esi
2346: call push_5_dw_at_esi
2347: lea dword_frac2(%ebp),%esi
2348: lea dword_frac1(%ebp),%edi
2349: call move_op_to_op
2350: mov $offset_operand2,%esi
2351: call pop_5_dw_at_esi
2352: ret
2353: //swap_ops endp
2354: //
2355: // **********************************************************************
2356: //
2357: ALIGN
2358: op1_into_op2: //proc
2359: call swap_ops
2360: op2_into_op1:
2361: push %gs:sr_masks
2362: orl $0x0300,%gs:sr_masks // set precision control to prec64
2363: call divid // floating-point divide
2364: call post_op_round
2365: pop %gs:sr_masks
2366: ret
2367:
2368: //op1_into_op2 endp
2369: //
2370: // **********************************************************************
2371: //
2372: //
2373: ALIGN
2374: sin_specific: //proc
2375:
2376: mov $offset_result,%esi
2377: call push_5_dw_at_esi // save (x/y)
2378: call op2_into_op1 // result <-- (y/x)
2379: lea result_dword_frac(%ebp),%esi
2380: lea dword_frac1(%ebp),%edi
2381: call move_op_to_op // op1 <-- (y/x)
2382: mov $offset_operand2,%esi
2383: call pop_5_dw_at_esi // op2 <-- (x/y)
2384: orl $0x0f00,%gs:sr_masks // set rc to chop!
2385: movb $add_op,operation_type(%ebp)
2386: call subadd
2387: call post_op_round
2388: lea result_dword_frac(%ebp),%esi
2389: lea dword_frac2(%ebp),%edi
2390: call move_op_to_op // op2 <-- chop(x/y + y/x)
2391: mov $offset_operand1,%esi
2392: call move_unpacked_1_to_esi // op1 <-- 1
2393: incl dword_expon1 // op1 <-- 2
2394: call op2_into_op1 // res <-- chop{2/chop(x/y + y/x)}
2395: ret
2396:
2397: //sin_specific endp
2398: //
2399: //
2400: // *****************************************************************************
2401: //
2402: // sin:
2403: //
2404: ALIGN
2405: sin: //proc
2406: call one_result_op1_chk
2407: sin_report:
2408: jnz sin_reduce_op1
2409: movb $sin_op,op_type
2410: movb sign1(%ebp),%al
2411: movb %al,sin_sign
2412: sin_0_modulus:
2413: lea dword_frac1(%ebp),%esi
2414: lea result_dword_frac(%ebp),%edi
2415: call move_op_to_op
2416: jmp check_op_type
2417: ALIGN
2418: sin_reduce_op1:
2419: call mod_qrtr_pi
2420: cmpb special,tag1(%ebp)
2421: jne sin_tiny_
2422: // testb q, 1 ; was operand (2k+1)*qrtr_pi?
2423: // jz sin_cofunc? ; if so, set precision error
2424: // orb %gs:sr_errors, inexact_mask
2425: //sin_cofunc?:
2426: cmpb true,cofunc_flag
2427: jne sin_0_modulus
2428: jmp cos_0_modulus
2429: ALIGN
2430: sin_tiny_:
2431: cmpb true,cofunc_flag
2432: je check_cos_lim
2433: check_sin_lim:
2434: mov $0x3fff,%eax
2435: sub dword_expon1,%eax
2436: cmp $30,%eax
2437: jl sin_calc
2438: jg sin_tiny_argument
2439: cmpl $0x08d100000,dword_frac1+frac32(%ebp)
2440: ja sin_calc
2441: jb sin_0_modulus
2442: cmp $0,dword_frac1+frac64(%ebp)
2443: je sin_0_modulus
2444: sin_tiny_argument:
2445: cmp $0x3fff,%eax
2446: jl sin_0_modulus
2447: orb underflow_mask,%gs:sr_errors
2448: testb underflow_mask,%gs:sr_masks
2449: jnz sin_grad_uflow
2450: addl wrap_around_constant,dword_expon1
2451: jmp sin_0_modulus
2452: ALIGN
2453: sin_grad_uflow:
2454: mov $offset_operand1,%edi
2455: mov $1,%eax
2456: call gradual_underflow
2457: movl $0,dword_expon1
2458: movb denormd,tag1(%ebp)
2459: jmp sin_0_modulus
2460: ALIGN
2461: sin_calc:
2462: push trans_info
2463: push %gs:sr_masks
2464: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest
2465: orl $0x0300,%gs:sr_masks // set precision control to prec64
2466: // dec dword_expon1 ; compute tan((op1)/2)
2467: inc %eax // eax holds -(true_expon)
2468: call tan_pseudo_divide
2469: mov $offset_operand1,%esi
2470: call push_5_dw_at_esi // save y
2471: mov $offset_operand2,%esi
2472: call push_5_dw_at_esi // save x
2473: call op1_into_op2 // result <-- x/y
2474: mov $offset_operand2,%esi
2475: call pop_5_dw_at_esi // op2 <-- x
2476: mov $offset_operand1,%esi
2477: call pop_5_dw_at_esi // op1 <-- y
2478: call sin_specific
2479: pop %gs:sr_masks
2480: pop trans_info
2481: andb $~a_mask,%gs:sr_flags
2482: cmpb true,added_one
2483: jne check_op_type
2484: orb $a_mask,%gs:sr_flags
2485: jmp check_op_type
2486: ALIGN
2487:
2488: //sin endp
2489: //
2490: //-----------------------------------------------------------------------
2491: // cos:
2492: //
2493: //-----------------------------------------------------------------------
2494: //
2495: ALIGN
2496: cos_specific: //proc
2497:
2498: lea dword_frac1(%ebp),%esi
2499: lea dword_frac2(%ebp),%edi
2500: call move_op_to_op // op2 <-- x/y
2501: call mult // res <-- (x/y)**2
2502: call post_op_round
2503: lea result_dword_frac(%ebp),%esi
2504: lea dword_frac1(%ebp),%edi
2505: call move_op_to_op // op1 <-- (x/y)**2
2506: mov $offset_operand2,%esi
2507: call move_unpacked_1_to_esi // op2 <-- 1
2508: movb $add_op,operation_type(%ebp)
2509: call subadd
2510: call post_op_round // res <-- 1 + (x/y)**2
2511: lea result_dword_frac(%ebp),%esi
2512: lea dword_frac2(%ebp),%edi
2513: call move_op_to_op // op2 <-- 1 + (x/y)**2
2514: mov $offset_operand1,%esi
2515: call move_unpacked_1_to_esi // op1 <-- 1
2516: incl dword_expon1 // op1 <-- 2
2517: call op2_into_op1 // res <-- 2/(1 + (x/y)**2)
2518: lea result_dword_frac(%ebp),%esi
2519: lea dword_frac2(%ebp),%edi
2520: call move_op_to_op // op2 <-- 2/(1 + (x/y)**2)
2521: mov $offset_operand1,%esi
2522: call move_unpacked_1_to_esi // op1 <-- 1
2523: movb $sub_op,operation_type(%ebp)
2524: call subadd
2525: call post_op_round // res <-- 1 - {2/(1 + (x/y)**2)}
2526: ret
2527:
2528: //cos_specific endp
2529: //
2530: //-----------------------------------------------------------------------
2531: //
2532: ALIGN
2533: cos: //proc
2534: call one_result_op1_chk
2535: cos_report:
2536: jnz cos_reduce_op1
2537: movb $cos_op,op_type
2538: movb positive,cos_sign
2539: cos_0_modulus:
2540: mov $offset_result,%esi
2541: call move_unpacked_1_to_esi
2542: check_op_type:
2543: cmpb $cos_op,op_type
2544: je attach_cos_sign
2545: attach_sin_sign:
2546: movb sin_sign,%al
2547: jmp sign_done
2548: ALIGN
2549: attach_cos_sign:
2550: movb cos_sign,%al
2551: sign_done:
2552: movb %al,result_sign(%ebp)
2553: send_result:
2554: mov $offset_result,%edi
2555: jmp put_si_result
2556: ALIGN
2557: cos_reduce_op1:
2558: call mod_qrtr_pi
2559: cmpb special,tag1(%ebp)
2560: jne cos_tiny_
2561: // testb q, 1 ; was operand (2k+1)*qrtr_pi?
2562: // jz cos_cofunc? ; if so, set precision error
2563: // orb %gs:sr_errors, inexact_mask
2564: //cos_cofunc?:
2565: cmpb true,cofunc_flag
2566: jne cos_0_modulus
2567: movl $0,result_dword_frac(%ebp)
2568: movl $0,result_dword_frac+frac64(%ebp)
2569: movl $0,result_dword_frac+frac32(%ebp)
2570: movl $0x10000*SPECIAL+POSITIVE,result_sign(%ebp)
2571: movl $0,dword_result_expon
2572: jmp attach_cos_sign
2573: ALIGN
2574: cos_tiny_:
2575: cmpb true,cofunc_flag
2576: je check_sin_lim
2577: check_cos_lim:
2578: mov $0x3fff,%eax
2579: sub dword_expon1,%eax
2580: cmp $62,%eax
2581: jl cos_calc
2582: jg cos_0_modulus
2583: cmpl $0x080000000,dword_frac1+frac32(%ebp)
2584: ja cos_calc
2585: cmp $0,dword_frac1+frac64(%ebp)
2586: je cos_0_modulus
2587: cos_calc:
2588: push trans_info
2589: push %gs:sr_masks
2590: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest
2591: orl $0x0300,%gs:sr_masks // set precision control to prec64
2592: // dec dword_expon1 ; compute tan((op1)/2)
2593: inc %eax // eax holds -(true_expon)
2594: call tan_pseudo_divide
2595: call op1_into_op2 // result <-- x/y
2596: lea result_dword_frac(%ebp),%esi
2597: lea dword_frac1(%ebp),%edi
2598: call move_op_to_op // op1 <-- x/y
2599: call cos_specific // result <-- cos
2600: pop %gs:sr_masks
2601: pop trans_info
2602: andb $~a_mask,%gs:sr_flags
2603: cmpb true,added_one
2604: jne check_op_type
2605: orb $a_mask,%gs:sr_flags
2606: jmp check_op_type
2607:
2608: //cos endp
2609: //
2610: //
2611: // ***********************************************************************
2612: // sincos:
2613:
2614: ALIGN
2615: sincos: //proc
2616: call two_result_op1_chk
2617: combo_get_report:
2618: jnz combo_reduce_op1
2619: xor %eax,%eax
2620: movb sign1(%ebp),%ah
2621: mov %eax,trans_info
2622: combo_0_mod:
2623: mov $offset_operand2,%esi
2624: call move_unpacked_1_to_esi
2625: combo_cofunc_:
2626: cmpb true,cofunc_flag
2627: jne attach_signs
2628: switch_ops:
2629: call swap_ops
2630: attach_signs:
2631: movw res_signs,%ax
2632: movb %al,sign1(%ebp)
2633: movb %ah,sign2(%ebp)
2634: results_sent:
2635: jmp do_exchange
2636: ALIGN
2637: combo_reduce_op1:
2638: call mod_qrtr_pi
2639: cmpb special,tag1(%ebp)
2640: // jne combo_tiny?
2641: // testb q, 1
2642: jz combo_0_mod
2643: // orb %gs:sr_errors, inexact_mask
2644: // jmp short combo_0_mod
2645: combo_tiny_:
2646: mov $0x3fff,%eax
2647: sub dword_expon1,%eax
2648: cmp $62,%eax
2649: jl combo_sin_calc
2650: jg combo_tiny_arg
2651: cmpl $0x080000000,dword_frac1+frac32(%ebp)
2652: ja combo_sin_calc
2653: cmp $0,dword_frac1+frac64(%ebp)
2654: jne combo_sin_calc
2655: combo_tiny_arg:
2656: cmp $0x3fff,%eax
2657: jl combo_0_mod
2658: orb underflow_mask,%gs:sr_errors
2659: testb underflow_mask,%gs:sr_masks
2660: jnz combo_grad_uflow
2661: addl wrap_around_constant,dword_expon1
2662: jmp combo_0_mod
2663: ALIGN
2664: combo_grad_uflow:
2665: mov $offset_operand1,%edi
2666: mov $1,%eax
2667: call gradual_underflow
2668: movl $0,dword_expon1
2669: movb denormd,tag1(%ebp)
2670: jmp combo_0_mod
2671: ALIGN
2672: combo_sin_calc:
2673: push trans_info
2674: push %gs:sr_masks
2675: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest
2676: orl $0x0300,%gs:sr_masks // set precision control to prec64
2677: cmp $30,%eax
2678: jl push_flags
2679: jg force_zf_1
2680: cmpl $0x08d100000,dword_frac1+frac32(%ebp)
2681: ja push_flags
2682: jb force_zf_1
2683: cmp $0,dword_frac1+frac64(%ebp)
2684: jne push_flags
2685: force_zf_1:
2686: xor %ebx,%ebx // zf set iff arg is tiny for sin
2687: mov $offset_operand1,%esi // save tiny op1 as sin(op1)
2688: call push_5_dw_at_esi // does not affect flags or eax
2689: push_flags:
2690: pushf
2691: // dec dword_expon1 ; compute tan((op1)/2)
2692: inc %eax // eax holds -(true_expon)
2693: call tan_pseudo_divide
2694: popf
2695: jz calc_x_over_y
2696: mov $offset_operand1,%esi
2697: call push_5_dw_at_esi // save y
2698: mov $offset_operand2,%esi
2699: call push_5_dw_at_esi // save x
2700: calc_x_over_y:
2701: pushf
2702: call op1_into_op2 // result <-- x/y
2703: popf
2704: jz save_x_over_y
2705: mov $offset_operand2,%esi
2706: call pop_5_dw_at_esi // op2 <-- x
2707: mov $offset_operand1,%esi
2708: call pop_5_dw_at_esi // op1 <-- y
2709: save_x_over_y:
2710: mov $offset_result,%esi
2711: call push_5_dw_at_esi // save x/y
2712: jz combo_cos_calc
2713: pushf
2714: call sin_specific // result <-- sin
2715: popf
2716: combo_cos_calc:
2717: mov $offset_operand1,%esi
2718: call pop_5_dw_at_esi // op1 <-- x/y
2719: jz tiny_sin_cos_entry
2720: mov $offset_result,%esi
2721: call push_5_dw_at_esi // save computed sin
2722: tiny_sin_cos_entry:
2723: call cos_specific // result <-- cos
2724: mov $offset_operand1,%esi
2725: call pop_5_dw_at_esi // op1 <-- sin
2726: lea result_dword_frac(%ebp),%esi
2727: lea dword_frac2(%ebp),%edi
2728: call move_op_to_op // op2 <-- cos
2729: pop %gs:sr_masks
2730: pop trans_info
2731: jmp combo_cofunc_
2732:
2733: //sincos endp
2734: //
2735: //
2736: // ***********************************************************************
2737: // test_5w, test_4w, test_3w
2738: //
2739: // function:
2740: // test 3, 4, or 5 consecutive words for zero
2741: //
2742: // inputs:
2743: // least significant word pointed to by ss:(bp + di)
2744: // ax must be clear upon entry for test_4w and test_3w
2745: //
2746: // outputs:
2747: // if variable = 0, ax = 00000h; zf = 1
2748: // otherwise, ax = 0ffffh; zf = 0
2749: //
2750: // data accessed:
2751: //
2752: // data changed:
2753: //
2754: // *************************************************************************
2755: ALIGN
2756: test_5w: //proc
2757: movw 8(%ebp,%edi),%ax // dump the data into ax
2758: test_4w:
2759: orw 6(%ebp,%edi),%ax
2760: test_3w:
2761: orw 4(%ebp,%edi),%ax
2762: orw 2(%ebp,%edi),%ax
2763: orw (%ebp,%edi),%ax
2764: jnz its_not_zero // branch if the number is nonzero
2765: ret // return with ax = 00000h, zf = 1
2766: ALIGN
2767: its_not_zero:
2768: movw $0x0ffff,%ax // return with ax = 0ffffh, zf = 0
2769: ret
2770: //test_5w endp
2771: //
2772: ALIGN
2773: test_6w: //proc
2774: mov (%ebp,%edi),%eax // dump the data into ax
2775: or 4(%ebp,%edi),%eax
2776: or 8(%ebp,%edi),%eax
2777: jnz non_0 // branch if the number is nonzero
2778: ret // return with eax = 000000000h, zf = 1
2779: ALIGN
2780: non_0:
2781: mov $0x0ffffffff,%eax // return with eax = 0ffffffffh, zf = 0
2782: ret
2783: //test_6w endp
2784: //
2785: // ***********************************************************************
2786: // clear_5w, set_5w, set__4w, set_3w
2787: //
2788: // function:
2789: // sets 3, 4, or 5 consecutive words to zero or given value
2790: //
2791: // inputs:
2792: // least significant word pointed to by ss:(ebp + edi)
2793: // ax contains value given to store for set routines
2794: //
2795: // outputs:
2796: // ax contains zero for the clear_5w routine
2797: // eax * * * * clear_6w *
2798: // data accessed:
2799: //
2800: // data changed:
2801: //
2802: // *************************************************************************
2803: ALIGN
2804: clear_6w: //proc
2805: xor %eax,%eax
2806: set_6w:
2807: mov %eax,(%ebp,%edi) // store the value in eax
2808: mov %eax,4(%ebp,%edi)
2809: mov %eax,8(%ebp,%edi)
2810: ret
2811: ALIGN
2812: //clear_6w endp
2813: //
2814: ALIGN
2815: clear_5w: //proc
2816: xorw %ax,%ax
2817: set_5w:
2818: movw %ax,8(%ebp,%edi) // store the value in ax
2819: set_4w:
2820: movw %ax,6(%ebp,%edi)
2821: set_3w:
2822: movw %ax,4(%ebp,%edi)
2823: movw %ax,2(%ebp,%edi)
2824: movw %ax,(%ebp,%edi)
2825: ret
2826: //clear_5w endp
2827: //
2828: //
2829: // common entries to shift and move subroutines
2830: //
2831: // right_shift group
2832: //
2833: right_shift_dword_exp_tmp:
2834: mov dword_exp_tmp,%ecx
2835: shlb $1,%cl
2836: jmp right_shift_al0
2837: ALIGN
2838: right_shift_result_1:
2839: movb $1,%cl
2840: right_shift_result_cl:
2841: mov $offset_result,%edi
2842: jmp right_shift_al0
2843: ALIGN
2844: right_shift_frac2_8:
2845: movb $8,%cl
2846: right_shift_frac2_cl:
2847: mov $offset_operand2,%edi
2848: jmp right_shift_al0
2849: ALIGN
2850: right_shift_frac1_8:
2851: movb $8,%cl
2852: right_shift_frac1_cl:
2853: mov $offset_operand1,%edi
2854: right_shift_al0:
2855: movb $0,%al
2856: // **********************************************************************
2857: // right_shift:
2858: //
2859: // function:
2860: // shifts a 12-byte number right by amount in ecx register.
2861: //
2862: // inputs:
2863: // low bit of al contains bit to inject from left.
2864: // edi contains the offset of the least significant byte
2865: // of the 12-byte number.
2866: //
2867: // outputs:
2868: // on return, edx is non-zero if any ones have been shifted out.
2869: // edi has the same value it had upon entry.
2870: // data accessed:
2871: //
2872: // data changed:
2873: //
2874: // ***************************************************************************
2875: FALLSTHRU
2876: right_shift: //proc
2877: xor %edx,%edx // initialize edx, the *sticky word*
2878: rorb $1,%al // move lsb to msb
2879: movsbl %al,%eax // transmit sign to ah and hi_word(eax)
2880: push %eax // stack insert bit replica
2881: movb $2,%ch // one less than # of dwords to get bit-shifted
2882: cmpb $32,%cl // does shift_count exceed 31?
2883: jb bits_shft_rt // if not, just do the bit shifting;
2884: cmpb $96,%cl // does shift_count exceed 95?
2885: jb dwords_shft_rt // if not, proceed with dword shifts;
2886: je get_out_shfts // else, if shift_count exceeds 96
2887: orw %ax,%dx // then bit shifted in is also shifted out
2888: get_out_shfts:
2889: or (%ebp,%edi),%edx // all 3 dwords are *shifted out,*
2890: or 4(%ebp,%edi),%edx // and ord to edx
2891: or 8(%ebp,%edi),%edx
2892: movb %ah,%al // copy insert bit throughout eax
2893: mov %eax,(%ebp,%edi) //
2894: mov %eax,4(%ebp,%edi) //
2895: mov %eax,8(%ebp,%edi) // replace all 96 bits by insert bit.
2896: pop %eax
2897: ret
2898: ALIGN
2899: //
2900: dwords_shft_rt:
2901: push %ds // save a?msr
2902: push %ss // copy stack segment
2903: pop %ds // to ds
2904: // push %ss
2905: // pop %es // and es
2906: add %ebp,%edi
2907: mov %edi,%esi
2908: movb %cl,%bl // save bit_shft_count in bl
2909: and $0x60,%ecx // get dword_shft_count
2910: shr $5,%ecx // normalize dword_shft_count
2911: movb %cl,%al // save dword_shft_count in al
2912: dword_shft_chk:
2913: or (%esi),%edx
2914: add $4,%esi
2915: LOOP(dword_shft_chk)
2916: movl $3,%cx
2917: subb %al,%cl
2918: movb %cl,%bh
2919: push %eax
2920: FAST_MOVSL
2921: pop %eax
2922: movb %al,%cl
2923: movb %ah,%al
2924: FAST_STOSL
2925: sub $12,%edi // adjust edi
2926: sub %ebp,%edi // to value it had at entry
2927: pop %ds
2928: movw %bx,%cx
2929: bits_shft_rt:
2930: pop %eax
2931: push %edi
2932: push %eax
2933: mov (%ebp,%edi),%eax
2934: xor %ebx,%ebx
2935: shrdl %cl,%eax,%ebx // cl is interpreted mod 32
2936: or %ebx,%edx
2937: bit_shft_loop:
2938: mov 4(%ebp,%edi),%eax
2939: shrdl %cl,%eax,(%ebp,%edi)
2940: add $4,%edi
2941: decb %ch
2942: jnz bit_shft_loop
2943: pop %eax
2944: movb %ah,%al
2945: shrdl %cl,%eax,(%ebp,%edi)
2946: pop %edi
2947: right_shift_done:
2948: clc
2949: ret
2950: ALIGN
2951: //
2952: //right_shift endp
2953: //
2954: //
2955: // left_shift group
2956: //
2957: left_shift_result_cl:
2958: mov $offset_result+frac80,%edi
2959: jmp left_shift
2960: ALIGN
2961: left_shift_frac2_8:
2962: movb $8,%cl
2963: left_shift_frac2_cl:
2964: mov $offset_operand2+frac80,%edi
2965: jmp left_shift
2966: ALIGN
2967: left_shift_frac1_8:
2968: movb $8,%cl
2969: jmp left_shift_frac1_cl
2970: ALIGN
2971: left_shift_frac1_1:
2972: movb $1,%cl
2973: left_shift_frac1_cl:
2974: mov $offset_operand1+frac80,%edi
2975: // **************************************************************************
2976: // left_shift:
2977: //
2978: // function:
2979: // shifts a 10-byte number left by amount in cl reg.
2980: //
2981: // input:
2982: // di contains offset of low-byte.
2983: //
2984: // outputs:
2985: // bits shifted off the left end are lost.
2986: //
2987: // data accessed:
2988: //
2989: // data changed:
2990: //
2991: // ****************************************************************************
2992: FALLSTHRU
2993: left_shift: //proc
2994: cmpb $80,%cl // more than 80 bits?
2995: jle left_count // no, form left count
2996: movb $80,%cl // yes, 80 is the max
2997: left_count:
2998: movb %cl,%al // form byte count
2999: andb $0x78,%al // = bits 3-6 of amount
3000: jz leftover_bits // branch if count < 8
3001: push %ecx // stack bit count
3002: push %edi // stack frac offset
3003: push %ds // save a?msr
3004: cbtw // clear ah
3005: shrw $3,%ax // normalize byte count
3006: decw %ax
3007: mov $0x0009,%ecx // count = 10 - ax
3008: add %ecx,%edi
3009: movswl %ax,%eax
3010: sub %eax,%ecx // dest = ss:bp+si
3011: add %ebp,%edi
3012: mov %edi,%esi // dest = ss:bp+di
3013: sub %eax,%esi
3014: dec %esi
3015: push %ss // copy ss to ds and es
3016: pop %ds
3017: // push %ss
3018: // pop %es
3019: /* Note direction is not appropriate for FAST_MOVSB */
3020: push %eax
3021: 1:
3022: movb 0(%esi),%al
3023: movb %al,0(%edi)
3024: dec %esi
3025: dec %edi
3026: decl %ecx
3027: testl %ecx,%ecx
3028: jg 1b
3029:
3030: movb %cl,(%edi) // clear next byte
3031: pop %eax
3032: mov %eax,%ecx // form zero count
3033: mov %edi,%esi // form string offsets
3034: dec %edi
3035: /* Note direction is not appropriate for FAST_MOVSB */
3036: push %eax
3037: 1:
3038: movb 0(%esi),%al
3039: movb %al,0(%edi)
3040: dec %esi
3041: dec %edi
3042: decl %ecx
3043: testl %ecx,%ecx
3044: jg 1b
3045:
3046: pop %eax
3047: pop %ds // reload a?msr
3048: pop %edi // reload frac offset
3049: pop %ecx // reload bit count
3050: leftover_bits:
3051: and $0x00000007,%ecx // bits 0-2 = bit count
3052: jz left_shift_done // exit if all done
3053: FALLSTHRU
3054: left_shift_bits:
3055: shlw $1,(%ebp,%edi) // shift five words
3056: rclw $1,2(%ebp,%edi) // one bit left, using
3057: rclw $1,4(%ebp,%edi) // the carry flag out
3058: rclw $1,6(%ebp,%edi)
3059: rclw $1,8(%ebp,%edi)
3060: LOOP(left_shift_bits) // loop bit count times
3061: left_shift_done:
3062: ret
3063: //left_shift endp
3064: //
3065: // ************************************************************************
3066: // one_left_normalize:
3067: //
3068: // function:
3069: // normalizes following a multiplication.
3070: //
3071: // inputs:
3072: // assumes fraction is not zero. di = frac offset.
3073: //
3074: // outputs:
3075: // shifts fraction left and decrements exponent until
3076: // fraction normalized, but no more than one left shift.
3077: // zf is reset if the fraction is normalized upon return.
3078: //
3079: // data accessed:
3080: //
3081: // data changed:
3082: //
3083: // **************************************************************************
3084: ALIGN
3085: one_left_normalize: //proc
3086: testb $0x80,frac80+9(%ebp,%edi) //normalized?
3087: jnz one_left_norm_done //quit if normalized.
3088: push %edi // save frac offset
3089: mov $0x00000001,%ecx // load loop count
3090: add $2,%edi
3091: call left_shift_bits //shift 5 words left 1
3092: pop %edi // reload frac offset
3093: decl expon(%ebp,%edi) //decrement exponent
3094: testb $0x80,frac80+9(%ebp,%edi) //normalized?
3095: one_left_norm_done:
3096: ret
3097: //one_left_normalize endp
3098: // ***********************************************************************
3099: // subtraction_normalize:
3100: //
3101: // function:
3102: // normalizes following a subtraction.
3103: //
3104: // inputs:
3105: // assumes fraction is not zero. di = frac offset
3106: //
3107: // outputs:
3108: // shifts fraction left and decrements exponent
3109: // until fraction normalized.
3110: //
3111: // data accessed:
3112: //
3113: // data changed:
3114: //
3115: // *************************************************************************
3116: ALIGN
3117: subtraction_normalize: //proc
3118: call one_left_normalize // normalize one bit
3119: jz subtraction_normalize //quit when normalized.
3120: ret
3121: //subtraction_normalize endp
3122: //
3123: //
3124: // move_10_bytes group
3125: //
3126: move_frac2_frac1:
3127: mov $offset_operand1+2,%edi
3128: move_frac2:
3129: mov $offset_operand2+2,%esi
3130: jmp move_10_bytes
3131: ALIGN
3132: move_frac1_result:
3133: mov $offset_result+2,%edi
3134: jmp move_frac1
3135: ALIGN
3136: move_frac1_cop:
3137: mov $offset_cop+2,%edi
3138: call move_frac1
3139: move_frac1_frac2:
3140: mov $offset_operand2+2,%edi
3141: move_frac1:
3142: mov $offset_operand1+2,%esi
3143: jmp move_10_bytes
3144: ALIGN
3145: move_dop_frac2:
3146: mov $offset_operand2+2,%edi
3147: jmp move_dop
3148: ALIGN
3149: move_dop_frac1:
3150: mov $offset_operand1+2,%edi
3151: move_dop:
3152: mov $offset_dop+2,%esi
3153: jmp move_10_bytes
3154: ALIGN
3155: move_cop_frac2:
3156: mov $offset_operand2+2,%edi
3157: jmp move_cop
3158: ALIGN
3159: move_cop_frac1:
3160: mov $offset_operand1+2,%edi
3161: move_cop:
3162: mov $offset_cop+2,%esi
3163: jmp move_10_bytes
3164: ALIGN
3165: move_result_cop:
3166: mov $offset_cop+2,%edi
3167: jmp move_result
3168: ALIGN
3169: move_result_dop:
3170: mov $offset_dop+2,%edi
3171: jmp move_result
3172: ALIGN
3173: move_result_frac2:
3174: mov $offset_operand2+2,%edi
3175: jmp move_result
3176: ALIGN
3177: move_result_frac1:
3178: mov $offset_operand1+2,%edi
3179: move_result:
3180: mov $offset_result+2,%esi
3181: move_10_bytes:
3182: add %ebp,%esi // add global record offset
3183: push %ds // save a?msr
3184: push %ss // load source segment register
3185: set_destination:
3186: pop %ds
3187: // push %ss // load destination segment register
3188: // pop %es // into es
3189: add %ebp,%edi // add global record offset
3190:
3191: /* FAST_MOVSW */
3192: movl 0(%esi),%ecx
3193: movl %ecx,%ss:0(%edi)
3194: movl 4(%esi),%ecx
3195: movl %ecx,%ss:4(%edi)
3196: movw 8(%esi),%ecx
3197: movw %ecx,%ss:8(%edi)
3198: // addl $10,%esi
3199: // addl $10,%edi
3200: // movl $0,%ecx
3201:
3202: pop %ds // reload a?msr
3203: ret
3204: ALIGN
3205: //
3206: // add, sub, mul, move_constant group
3207: //
3208: add_half1_frac2:
3209: mov $add_half_pattern_1,%esi
3210: call add_frac2
3211: mov $offset_result,%edi
3212: jmp addition_normalize
3213: ALIGN
3214: add_frac2:
3215: call move_constant_frac2
3216: jmp addx
3217: ALIGN
3218: sub_frac1:
3219: mov $offset_operand1+2,%edi
3220: sub_constant:
3221: call move_constant
3222: jmp subx
3223: ALIGN
3224: sub_frac2:
3225: mov $offset_operand2+2,%edi
3226: jmp sub_constant
3227: ALIGN
3228: mul_frac2:
3229: call move_constant_frac2
3230: jmp mulx
3231: ALIGN
3232: move_constant_frac2:
3233: mov $offset_operand2+2,%edi
3234: move_constant:
3235: push %ds // save a?msr
3236: push %cs // load code segment base into ds
3237: jmp set_destination // move five words
3238: ALIGN
3239: // .byte 'bernard verreau,san francisco,ca . 1983'
3240: //
3241: //a_med ends
3242: //
3243: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.