|
|
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 "arith.s"
26:
27: .ident "@(#)kern-fp:arith.s 1.1"
28: //$tt(*80387 emulator + + + arithmetic + + +*)
29: // ************************************************************************
30: //
31: // a r i t h . m o d
32: // =================
33: //
34: // ===============================================================
35: // intel corporation proprietary information
36: // this software is supplied under the terms of a license
37: // agreement or non-disclosure agreement with intel corporation
38: // and may not be copied or disclosed except in accordance with
39: // the terms of that agreement.
40: // ===============================================================
41: //
42: // function:
43: // implements add, subtract, multiply, and divide.
44: //
45: // public procedures:
46: // move_op_to_result overflow_response
47: // underflow_response put_max_nan
48: // put_indefinite arith
49: //
50: // *************************************************************************
51: //
52: //...March 3, 1987...
53: //
54: // .file *a_mar*
55: #include "fp_e80387.h"
56: //$eject
57: //...declare status register segment...
58: //
59: .data //a_msr segment rw public
60: // extrn sr_masks
61: //a_msr ends
62: //
63: .text //a_med segment er public
64: // assume %ds:a_med
65: // extrn addition_normalize,round
66: // extrn gradual_underflow,put_result
67: // extrn pop_free,subadd,mult
68: // extrn divid,set_up_indefinite,test_4w
69: // extrn special_round_test,directed_round_test
70: // extrn get_precision,u_masked_,set_i_masked_
71: // extrn d_masked_,affine_infinity_,i_masked_
72: // extrn o_masked_,set_p_error,set_u_error
73: // extrn set_o_error,set_z_masked_,set_d_masked_
74: // extrn set_stk_u_error,d_error_,get_rnd_control
75: //
76: .globl put_indefinite
77: .globl move_op_to_result
78: .globl put_max_nan
79: .globl overflow_response
80: .globl underflow_response
81: .globl arith
82: .globl norm_denorm
83: .globl put_arith_result
84: .globl set_up_nan_return
85: //$eject
86: //
87: //...define some floating point constants...
88: //
89: indefinite_pattern:
90: .value 0,0,0,0x0c000,0x0ffff
91: infinity_pattern:
92: .value 0,0,0,0x8000,0x7fff
93: zero_pattern:
94: .value 0,0,0,0,0
95: max_valid_pattern:
96: .value 0x0ffff,0x0ffff,0x0ffff,0x0ffff,0x7ffe
97: arith_table:
98: .long subadd,subadd,mult,divid
99: //
100: //...the following jump tables refer to the following op1/op2 cases
101: //
102: // (where v=valid, z=zero, f=infinity, and d=denormal):
103: // 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,
104: // in that order ..
105: //add_table
106: special_table:
107: .long handle_non_special_cases,handle_non_special_cases
108: .long second_operand,only_op2_denormd
109: .long handle_non_special_cases,handle_non_special_cases
110: .long second_operand,only_op2_denormd
111: .long first_operand,first_operand
112: .long add_sub_infinities,derror_with_first_operand
113: .long only_op1_denormd,only_op1_denormd
114: .long derror_with_second_operand,both_ops_denormd
115: //sub_table
116: .long handle_non_special_cases,handle_non_special_cases
117: .long neg_second_operand,only_op2_denormd
118: .long handle_non_special_cases,handle_non_special_cases
119: .long neg_second_operand,only_op2_denormd
120: .long first_operand,first_operand
121: .long add_sub_infinities,derror_with_first_operand
122: .long only_op1_denormd,only_op1_denormd
123: .long derror_with_neg_second_operand,both_ops_denormd
124: //mul_table
125: .long handle_non_special_cases,exor_signed_zero
126: .long exor_signed_infinity,only_op2_denormd
127: .long exor_signed_zero,exor_signed_zero
128: .long invalid_error_detected,denormd_exor_signed_zero
129: .long exor_signed_infinity,invalid_error_detected
130: .long exor_signed_infinity,denormd_exor_signed_infinity
131: .long only_op1_denormd,denormd_exor_signed_zero
132: .long denormd_exor_signed_infinity,both_ops_denormd
133: //div_table
134: .long handle_non_special_cases,divide_by_zero
135: .long exor_signed_zero,only_op2_denormd
136: .long exor_signed_zero,invalid_error_detected
137: .long exor_signed_zero,denormd_exor_signed_zero
138: .long exor_signed_infinity,exor_signed_infinity
139: .long invalid_error_detected,denormd_exor_signed_infinity
140: .long only_op1_denormd,divide_by_zero
141: .long denormd_exor_signed_zero,both_ops_denormd
142: //
143: //$eject
144: // put_indefinite:
145: //
146: // function:
147: // sets unpacked result to indefinite.
148: //
149: // inputs:
150: //
151: // outputs:
152: // result set to indefinite; tag set to invalid.
153: //
154: // data accessed:
155: // - result_sign result_tag
156: //
157: // data changed:
158: // - result
159: //
160: ALIGN
161: put_indefinite: //proc
162: mov $indefinite_pattern,%esi
163: movb negative,result_sign(%ebp)
164: // note that entry points below do not affect result_sign.
165: put_inv_tag:
166: movb inv,result_tag(%ebp) // fall into set_constant_result
167: set_constant_result:
168: lea offset_result+4(%ebp),%edi
169: // push %ds // save a?msr
170: // push %cs
171: // pop %ds
172: // push %ss
173: // pop %es
174:
175: /* FAST_MOVSL */
176: movl %cs:0(%esi),%ecx
177: movl %ecx,%ss:0(%edi)
178: movl %cs:4(%esi),%ecx
179: movl %ecx,%ss:4(%edi)
180: // addl $8,%esi
181:
182: mov %ecx,result_dword_frac(%ebp) // clear ls dword
183: mov %cs:8(%esi),%eax // move exponent
184: movw %ax,result_expon(%ebp) // to result
185: // pop %ds // reload a?msr
186: ret
187: //put_indefinite endp
188: //$eject
189: // move_op_to_result:
190: //
191: // function:
192: // moves operand to result.
193: //
194: // inputs:
195: // assumes ss:(ebp).esi points to op1 or op2
196: //
197: // outputs:
198: // result in result
199: //
200: // data accessed:
201: // - expon1 offset_result
202: // - result_expon
203: //
204: // data changed:
205: // - result
206: //
207: ALIGN
208: move_op_to_result: //proc
209: // push %ds // save a?msr
210: add %ebp,%esi
211: // push %ss
212: // pop %ds
213: // push %ss
214: // pop %es
215: lea offset_result(%ebp),%edi
216: mov $((offset_operand2-offset_operand1)>>2),%ecx
217:
218: /* FAST_MOVSL */
219: 1:
220: movl %ss:0(%esi),%eax
221: movl %eax,%ss:0(%edi)
222: addl $4,%esi
223: addl $4,%edi
224: decl %ecx
225: testl %ecx,%ecx
226: jg 1b
227:
228: // pop %ds // reload a?msr
229: ret
230: //move_op_to_result endp
231: //$eject
232: // overflow_response:
233: //
234: // function:
235: // responds to detected overflow.
236: //
237: // inputs:
238: //
239: // outputs:
240: // overflow error indication(s) set when appropriate
241: // correct masked or unmasked result
242: //
243: // data accessed:
244: // - result_sign result_tag
245: // - result_expon msb_result
246: //
247: // data changed:
248: // - result
249: //
250: // procedures called:
251: // special_round_test set_o_error
252: // o_masked? set_p_error
253: //
254: //
255: ALIGN
256: overflow_response: //proc
257: orb overflow_mask, %gs:sr_errors //set overflow error
258: testb overflow_mask, %gs:sr_masks
259: jnz masked_overflow // branch if ovflw masked
260: // note that p_error may have been set by the first rounding of the result,
261: // and that rounded result will now have its exponents bias adjusted:
262: reduce_exponent:
263: subl wrap_around_constant,dword_result_expon // subtract
264: cmpl $0x7fff, dword_result_expon //wrap around constant
265: jge masked_overflow // bad! should give qnan indefinite
266: unmasked_ov_un_rounds:
267: cmpb true, rnd1_inexact //detect inexact result
268: jne give_valid_o_result // if exact, branch to replace source
269: orb $inexact_mask, %gs:sr_errors // else, set p_error
270: cmpb true, added_one //was rounding done by adding one
271: jne give_valid_o_result // if not branch to replace source
272: orb $a_mask, %gs:sr_flags // else set A_bit
273: jmp give_valid_o_result
274: ALIGN
275: masked_overflow:
276: orb $inexact_mask, %gs:sr_errors //set p_error
277: call get_rnd_control
278: cmpb rnd_to_zero,%al
279: je put_max_valid
280: movb result_sign(%ebp),%al // check for special
281: call special_round_test // rounding case
282: jnz put_max_valid
283: orb $a_mask, %gs:sr_flags //set a_bit
284: put_infinity:
285: mov $infinity_pattern,%esi
286: jmp put_inv_tag
287: ALIGN
288: put_max_valid:
289: // mov (ebp).result_tag, valid
290: movl $0x00007ffe,dword_result_expon
291: movl $0,result_dword_frac(%ebp)
292: movl $0x0ffffffff,result_dword_frac+frac64(%ebp)
293: movl $0x0ffffffff,result_dword_frac+frac32(%ebp)
294: cmpb $add_op,operation_type(%ebp)
295: jl give_valid_o_result
296: cmpb $div_op,operation_type(%ebp)
297: jg give_valid_o_result
298: movb $precision_mask,%dl // load precision field mask
299: andb %gs:sr_controls,%dl // mask in precision control
300: cmpb prec53,%dl
301: jg give_valid_o_result
302: je purge_11_bits
303: movl $0,result_dword_frac+frac64(%ebp)
304: movl $0x0ffffff00,result_dword_frac+frac32(%ebp)
305: jmp give_valid_o_result
306: ALIGN
307: purge_11_bits:
308: andl $0x0fffff800,result_dword_frac+frac64(%ebp)
309:
310: // mov esi, offset max_valid_pattern ; set result to max
311: // jmp set_constant_result ; valid number
312:
313: give_valid_o_result:
314: movb valid,result_tag(%ebp)
315: ret
316: //overflow_response endp
317: //$eject
318: // underflow_response:
319: //
320: // function:
321: // responds to a detected underflow
322: //
323: // inputs:
324: //
325: // outputs:
326: // sets underflow error indication(s) if appropiate
327: // correct masked or unmasked results in result
328: //
329: // data accessed:
330: // - offset_result result_sign
331: // - result_tag result_expon
332: // - result_word_frac
333: //
334: // data changed:
335: // - result
336: //
337: // procedures called:
338: // directed_round_test gradual_underflow
339: // round test_4w
340: // set_u_error u_masked?
341: // get_precision
342: //
343: ALIGN
344: underflow_response: //proc
345: testb underflow_mask, %gs:sr_masks //is underflow masked
346: jnz do_grad_underflow // yes, dont set flag
347: orb underflow_mask, %gs:sr_errors //no, set error flag
348: increase_exponent:
349: addl wrap_around_constant,dword_result_expon // add wrap-around
350: cmp $0, dword_result_expon //wrap_around constant
351: jg unmasked_ov_un_rounds // bad! shuld give qnan indef
352: subl wrap_around_constant, dword_result_expon // subtract
353: do_grad_underflow:
354: mov $offset_result,%edi // do gradual underflow
355: mov $0x0001,%eax // minimum expon is 0001
356: call gradual_underflow
357: call get_precision
358: movb true,%al
359: mov $offset_result,%edi // do second round
360: call round
361: cmpw $0, rnd_history
362: je prepare_zero_expon
363: orb underflow_mask + inexact_mask, %gs:sr_errors //set both errors
364: cmpb true, added_one // was rounding done by adding one
365: jne prepare_zero_expon //if not, branch for zero expon
366: orb $a_mask, %gs:sr_flags //else, set a_bit & if incrementing
367: testb $0x80, msb_result //The significand caused the most
368: jz prepare_zero_expon //significant bit of result_frac to
369: movb valid, result_tag(%ebp) // be set, tag result *valid* & return
370: ret
371: ALIGN
372: prepare_zero_expon:
373: xor %eax, %eax
374: clear_expon:
375: mov %eax,dword_result_expon // set exponent to zero
376: mov $result_dword_frac+4,%edi
377: call test_4w // if fraction nonzero,
378: movb denormd,result_tag(%ebp)
379: jnz accept_tag // tag as denormal
380: movb special,result_tag(%ebp) // else, tag as zero
381: accept_tag:
382: ret
383: //underflow_response endp
384: //$eject
385: // norm_denorm:
386: //
387: // function:
388: // normalizes an unpacked operand presumed to have been tagged
389: // *denormd*. includes case in which operand is so tagged because
390: // it was a single or double format denormal, which has already
391: // been normalized in the course of extending it to unpacked format.
392: // also includes case in which operand is a pseudo-denormal.
393: //
394: // inputs: edi points to the offset of the record to be normalized.
395: //
396: // outputs:
397: // 8 bytes beginning at (ebp + edi + frac64) are left shifted until
398: // the bit in position b63 is set.
399: // the 32 bit exponent field is 1 - shift_count
400: //
401: // data accessed:
402: // - dword ptr (ebp + edi + expon)
403: // - byte ptr (ebp + edi + msb)
404: // - dword ptr (ebp + edi + frac32), dword ptr (ebp + edi + frac64)
405: //
406: // data changed:
407: // - dword ptr (ebp + edi + expon)
408: // - byte ptr (ebp + edi + msb)
409: // - dword ptr (ebp + edi + frac32), dword ptr (ebp + edi + frac64)
410: //
411: // procedures called:
412: //
413: //
414: ALIGN
415: norm_denorm: //proc
416: cmp $0,expon(%ebp,%edi)
417: jne norm_denorm_done
418: movl $1,expon(%ebp,%edi)
419: testb $0x80,msb(%ebp,%edi)
420: jnz norm_denorm_done
421: norm_64_bits:
422: bsrl frac32(%ebp,%edi),%ecx
423: jz top_32_zero
424: mov frac64(%ebp,%edi),%eax
425: sub $31,%ecx
426: neg %ecx
427: shldl %cl,%eax,frac32(%ebp,%edi)
428: shll %cl,frac64(%ebp,%edi)
429: adjust_dword_expon:
430: sub %ecx,expon(%ebp,%edi) // adjust exponent
431: norm_denorm_done:
432: ret
433: ALIGN
434: top_32_zero:
435: mov frac64(%ebp,%edi),%eax
436: bsrl %eax,%ecx
437: sub $31,%ecx
438: neg %ecx
439: shll %cl,%eax
440: mov %eax,frac32(%ebp,%edi)
441: movl $0,frac64(%ebp,%edi)
442: add $32,%ecx
443: jmp adjust_dword_expon
444: //norm_denorm endp
445: //$eject
446: //
447: // arith:
448: //
449: // function:
450: // main procedure for implementation of 80387 add, subtract,
451: // multiply, and divide instructions
452: //
453: // inputs:
454: // assumes operation type, operand(s), and unpacked
455: // status variables are set up
456: //
457: // outputs
458: // result of operation in result
459: //
460: // data accessed:
461: // - operation_type offset_operand1
462: // - sign1 tag1
463: // - expon1 offset_operand2
464: // - sign2 tag2
465: // - expon2 offset_result
466: // - result_sign result_tag
467: // - result_expon result_word_frac
468: //
469: // data changed:
470: // - result
471: //
472: // procedures called:
473: // put_indefinite affine_infinity?
474: // put_max_valid move_op_to_result
475: // overflow_response underflow_response
476: // put_max_nan divid
477: // set_up_indefinite round
478: // addition_normalized put_result
479: // pop_free subadd
480: // mult test_4w
481: // i_masked? d_error?
482: // d_masked? i_error?
483: // get_precision set_i_masked?
484: // set_z_masked? set_d_masked?
485: //
486: //
487: ALIGN
488: arith: //proc
489: // assume %ds:a_msr
490: jz weed_out_special_cases // branch if no stack error
491: call set_stk_u_error // stack underflow occurred
492: testb invalid_mask,%gs:sr_masks
493: jz go_home // if unmasked, return
494: call put_indefinite // otherwise, result = indefinite
495: jmp finish_up
496: ALIGN
497: weed_out_special_cases:
498: andb $~a_mask, %gs:sr_flags //clear a_bit initially
499: movb tag1(%ebp),%al // both operands valid?
500: orb tag2(%ebp),%al
501: jnz special_cases // no, special case
502: handle_non_special_cases:
503: movzbl operation_type(%ebp),%ebx// call sub/add/mul/div
504: subb $add_op,%bl // to do the operation
505: shlw $2,%bx
506: call *%cs:arith_table(%ebx)
507: // the following three instructions are residue of warning mode arithmetic:
508: // call i_error? ; invalid if attempted
509: // jz no_invalid_error; division by denormal
510: // jmp invalid_error_detected
511: no_invalid_error:
512: mov $offset_result,%edi // round result
513: call get_precision // (indicate first, not
514: movb false,%al // second, round)
515: call round
516: mov $offset_result,%edi // re-normalize
517: // movb $4,%ah / (num words in frac=4)
518: call addition_normalize // (al contains overflow
519: mov dword_result_expon,%eax // indication from round)
520: cmp $0x7ffe,%eax // overflow iff
521: jg overflow_happened // expon > 7ffeh
522: cmp $0,%eax // check underflow if
523: jl underflow_happened // expon < 0
524: call give_valid_o_result // set tag to valid
525: and %eax,%eax // check underflow if
526: jnz report_rounds // expon = 0 and frac <> 0
527: mov $result_dword_frac+4,%edi //expon=0
528: call test_4w
529: jnz underflow_happened
530: movb special,result_tag(%ebp) // result is truly zero
531: report_rounds:
532: cmpb true, rnd1_inexact //detect inexact result
533: jne finish_up //if exact, branch
534: orb $inexact_mask, %gs:sr_errors //else, set p_error
535: cmpb true, added_one //was rounding done by adding one
536: jne finish_up //if not, branch
537: orb $a_mask, %gs:sr_flags // else, set a_bit
538: finish_up:
539: mov $offset_result,%edi
540: mov offset_result_rec,%esi
541: jmp put_arith_result
542: ALIGN
543: //
544: both_ops_denormd:
545: orb denorm_mask, %gs:sr_errors
546: testb denorm_mask, %gs:sr_masks
547: jz go_home
548: mov $offset_operand1,%edi
549: call norm_denorm
550: op2_denormd:
551: mov $offset_operand2,%edi
552: call norm_denorm
553: jmp handle_non_special_cases
554: ALIGN
555: only_op1_denormd:
556: orb denorm_mask, %gs:sr_errors
557: testb denorm_mask, %gs:sr_masks
558: jz go_home
559: mov $offset_operand1,%edi
560: call norm_denorm
561: jmp handle_non_special_cases
562: ALIGN
563: only_op2_denormd:
564: orb denorm_mask, %gs:sr_errors
565: testb denorm_mask, %gs:sr_masks
566: jz go_home
567: jmp op2_denormd
568: ALIGN
569: //
570: overflow_happened:
571: call overflow_response // here, overflow is certain.
572: jmp finish_up
573: ALIGN
574: go_home:
575: ret
576: underflow_happened:
577: call underflow_response
578: jmp finish_up
579: ALIGN
580: special_cases:
581: testb $0x10,%al // al contains (ebp).tag1 or (ebp).tag2
582: jz op1_nan_
583: orb invalid_mask, %gs:sr_errors
584: testb invalid_mask, %gs:sr_masks
585: jz go_home
586: mov $offset_operand1,%edi
587: call set_up_indefinite
588: mov offset_result_rec,%esi
589: jmp put_arith_result
590: ALIGN
591: op1_nan_: // here, neither op is unsupported.
592: cmpb inv,tag1(%ebp)
593: je op1_snan_
594: cmpb inv,tag2(%ebp)
595: jne non_nan_supp_ops
596: jmp signal_invalid_
597: ALIGN
598: op1_snan_:
599: testb $0x40,msb_frac1
600: jz invalid_operand
601: op2_also_nan_:
602: cmpb inv,tag2(%ebp)
603: jne set_up_nan_return
604: signal_invalid_:
605: testb $0x40,msb_frac2
606: jnz set_up_nan_return
607: invalid_operand:
608: orb invalid_mask, %gs:sr_errors
609: testb invalid_mask, %gs:sr_masks
610: jz go_home // i-error, if unmasked
611: set_up_nan_return:
612: mov offset_result_rec,%esi // result=max(nan1,nan2)
613: cmpb inv, tag1(%ebp)
614: je check_tag2
615: mov $offset_operand2, %edi
616: jmp install_hi_bits
617: ALIGN
618: check_tag2:
619: cmpb inv, tag2(%ebp)
620: je put_max_nan
621: mov $offset_operand1, %edi
622: jmp install_hi_bits
623: ALIGN
624: put_max_nan:
625: movb sign1(%ebp),%al // set result to larger
626: movb sign2(%ebp),%ah // magnitude result
627: push %eax // save signs
628: andb $0x7f,msb_frac1
629: andb $0x7f,msb_frac2
630: subtract_fracs:
631: movb positive,sign1(%ebp) // subtract the absolute
632: movb positive,sign2(%ebp) // values of the two ops
633: movb $sub_op,operation_type(%ebp)
634: push %esi
635: call subadd
636: pop %esi
637: pop %eax
638: movb %al,sign1(%ebp) // restore sign1 and give
639: mov $offset_operand1,%edi // operand1 as answer
640: cmpb positive,result_sign(%ebp) // if difference is +
641: je install_hi_bits
642: movb %ah,sign2(%ebp) // restore sign2 and give
643: mov $offset_operand2,%edi // operand2 as answer
644: install_hi_bits:
645: orb $0x0c0,msb(%ebp,%edi)
646: put_arith_result:
647: call put_result
648: jmp pop_free
649: ALIGN
650: non_nan_supp_ops:
651: movb tag2(%ebp),%bl
652: movb tag1(%ebp),%bh
653: testb $0x04,%bh
654: jz op2_denorm_
655: movb $3,%bh // indicate op1 is denorm
656: op2_denorm_:
657: testb $0x04,%bl
658: jz get_index
659: movb $3,%bl // indicate op2 is denorm
660: get_index:
661: and $0x0303,%ebx // form index to special operation table
662: // bx=4*(4*masked_tag1 + masked_tag2),
663: // where masked_tag = 0 for valid,
664: shlb $2,%bh // 1 for zero,
665: //2 for infinity
666: addb %bh,%bl // 3 for denormd
667: xorb %bh,%bh
668: shl $2,%ebx
669: mov $0x40fb,%eax // 64 byte/table -add_op
670: addb operation_type(%ebp),%al // al = normalized type
671: mulb %ah // (e)ax = operation offset
672: add %eax,%ebx // (e)bx = case offset
673: jmp *%cs:special_table(%ebx) // jump to special case
674: ALIGN
675: exit_arith:
676: ret
677: derror_with_first_operand:
678: orb denorm_mask, %gs:sr_errors
679: testb denorm_mask, %gs:sr_masks
680: jz exit_arith // if unmasked, return
681: first_operand:
682: mov $offset_operand1,%esi // give first operand as
683: jmp set_result_to_operand // result
684: ALIGN
685: derror_with_neg_second_operand:
686: orb denorm_mask, %gs:sr_errors
687: testb denorm_mask, %gs:sr_masks
688: jz exit_arith // if unmasked, return
689: neg_second_operand:
690: notb sign2(%ebp) // negate second operand
691: jmp second_operand // result
692: ALIGN
693: derror_with_second_operand:
694: orb denorm_mask, %gs:sr_errors
695: testb denorm_mask, %gs:sr_masks
696: jz exit_arith // if unmasked, return
697: second_operand:
698: mov $offset_operand2,%esi //give second operand
699: set_result_to_operand:
700: call move_op_to_result
701: jmp go_to_finish_up
702: ALIGN
703: //divide_into_zero: ; this section, for pseudo-zeroes, was
704: // xor ax,ax ; commented out when they became unsupp.
705: // mov edi,offset word_frac2 + 2 ; if frac2 = 0, invalid
706: // call test_4w ; else, zero and xor
707: // jz invalid_error_detected ; signs as the result
708: denormd_exor_signed_zero:
709: orb denorm_mask, %gs:sr_errors
710: testb denorm_mask, %gs:sr_masks
711: jz exit_arith // if unmasked, return
712: exor_signed_zero:
713: mov $zero_pattern,%esi
714: call set_constant_result
715: movb special,result_tag(%ebp)
716: jmp set_exor_sign
717: ALIGN
718: denormd_exor_signed_infinity:
719: orb denorm_mask, %gs:sr_errors
720: testb denorm_mask, %gs:sr_masks
721: jz exit_arith // if unmasked, return
722: jmp exor_signed_infinity
723: ALIGN
724: divide_by_zero:
725: orb zero_divide_mask, %gs:sr_errors
726: testb zero_divide_mask, %gs:sr_masks
727: jz exit_arith // if unmasked, return
728: exor_signed_infinity:
729: call put_infinity // else, give infinity
730: set_exor_sign:
731: movb positive,result_sign(%ebp) // set sign to exclusive
732: movb sign1(%ebp),%ah // or of operand signs
733: cmpb sign2(%ebp),%ah
734: je go_to_finish_up
735: notb result_sign(%ebp)
736: go_to_finish_up:
737: jmp finish_up
738: ALIGN
739: add_sub_infinities:
740: movb sign2(%ebp),%ah // add or sub magnitude?
741: cmpb $sub_op,operation_type(%ebp) // add mag if add_op and
742: jne add_or_sub_mag_ // signs same, else sub
743: notb %ah // comp sign2 if sub
744: add_or_sub_mag_:
745: cmpb sign1(%ebp),%ah
746: je first_operand // first op res if add_mag
747: invalid_error_detected:
748: orb invalid_mask, %gs:sr_errors
749: testb invalid_mask, %gs:sr_masks
750: jz exit_arith
751: call put_indefinite // if masked, indefinite
752: jmp finish_up // otherwise, just return
753: ALIGN
754: //
755: //arith endp
756: //
757: //a_med ends
758: //
759: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.