|
|
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 "reg.s"
26:
27: .ident "@(#)kern-fp:reg.s 1.1"
28:
29: // ****************************************************************************
30: //
31: // r e g . 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 nor disclosed except in accordance with
39: // the terms of that agreement.
40: // ===============================================================
41: //
42: // function:
43: // operation cluster for the 80387 register stack.
44: //
45: // public procedures:
46: // put_result stack_full? float_int16
47: // save_regs restore_regs set_up_indefinite
48: // getx fetch_an_op exchange exam
49: // fxtrac abs_value chsign put_op1_result
50: // put_si_result do_exchange
51: //
52: // internal procedures:
53: // extend_single extend_double get_bcd fetch_an_op
54: // float16 float32 float64
55: //
56: // *****************************************************************************
57: //
58: //...March 3, 1987...
59: //
60: //$nolist
61: #include "fp_e80387.h"
62: //$list
63: //...declare status register segment...
64: //
65: .data //a_msr segment rw public
66: // extrn %gs:sr_masks,%gs:sr_errors,%gs:sr_flags,%gs:sr_regstack
67: //a_msr ends
68: //
69: // assume %ds:a_msr
70: //
71: .text //a_med segment er public
72: //
73: // extrn store_reg_tag,decr_top,left_shift
74: // extrn subtraction_normalize,clear_6w,test_3w
75: // extrn move_op_to_result,save_status,set_z_bit
76: // extrn restore_status,init,test_4w,test_6w
77: // extrn left_shift_frac2_cl,left_shift_frac1_1
78: // extrn left_shift_result_cl,get_top,set_i_error
79: // extrn get_reg_tag,set_s_bit,set_d_error
80: // extrn i_masked_,clear_c_bit,clear_cond_bits
81: // extrn set_c_bit,set_a_bit,set_i_masked_
82: // extrn move_op_to_op,set_stk_u_error,set_stk_o_error
83: // extrn norm_denorm,correct_tag_word
84: // --------to be added for unix
85: //.. extrn fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far
86: //
87: .globl getx
88: .globl fetch_an_op
89: .globl put_result
90: .globl stack_full_
91: .globl fxtrac
92: .globl float_int16
93: .globl save
94: .globl save_regs
95: .globl restore_regs
96: .globl restore
97: .globl set_up_indefinite
98: .globl exchange
99: .globl exam
100: .globl decompose
101: .globl load
102: .globl abs_value
103: .globl chsign
104: .globl put_op1_result
105: .globl do_exchange
106: .globl put_si_result
107: .globl do_exchange_leave_a_bit
108: //
109: // *****************************************************************************
110: // extend_single:
111: // **************
112: // function:
113: // retrieves a single real operand from memory,
114: // extends its parts, and puts them in the operand
115: //
116: // inputs:
117: // assumes mem_operand_pointer set up
118: // edi points to operand1 or operand2
119: //
120: // outputs:
121: // extended operand in operand
122: //
123: // data accessed:
124: // - mem_operand_pointer
125: //
126: // data changed:
127: // - operands
128: //
129: // procedures called:
130: // set_d_error
131: //
132: // ***************************************************************************
133: ALIGN
134: extend_single: //proc
135: les mem_operand_pointer(%ebp),%ebx
136: xor %eax,%eax
137: mov %eax,frac64(%ebp,%edi) //clear low 5 bytes of
138: movb %al,frac32(%ebp,%edi) //fraction to 0
139: // ---- replace following line for unix
140: mov %es:(%ebx),%eax // move 3 fraction
141:
142: //..
143: //.. pushad
144: //.. push es
145: //.. push ebx
146: //.. call fpfulong
147: //.. add esp,8
148: //.. popad
149: //.. cld
150: //..
151: mov %eax,frac32+1(%ebp,%edi) // bytes from memory
152: sar $23,%eax // get short real exponent in al
153: movb %ah,sign(%ebp,%edi) // transfer sign to operand
154: and $0x000000ff,%eax // strip sign bits (here, b8-b31)
155: movl $0,before_error_signals(%ebp) // initialize all to false
156: jnz single_invalid_
157: movb frac64+7(%ebp,%edi),%al // zero or denormalized?
158: orw frac64+5(%ebp,%edi),%ax
159: jnz single_denormalized
160: zero_return:
161: movb special,tag(%ebp,%edi) // set tag to special,
162: mov %eax,expon(%ebp,%edi) // expon to 0
163: ret
164: ALIGN
165: single_denormalized:
166: movb denormd,tag(%ebp,%edi) // set tag to denormd
167: movb true,signal_d_error_
168: testb denorm_mask,%gs:sr_masks // short cut for unmasked d-error
169: jnz sngl_d_error_masked
170: ret
171: ALIGN
172: sngl_d_error_masked:
173: movl single_exp_offset+1,expon(%ebp,%edi)
174: bsrl frac32(%ebp,%edi),%ecx
175: sub $31,%ecx
176: neg %ecx
177: shll %cl,frac32(%ebp,%edi)
178: sub %ecx,expon(%ebp,%edi) // adjust exponent
179: ret
180: ALIGN
181: single_invalid_:
182: cmpb true,%al
183: jne single_operand_is_valid
184: movl $0x7fff,expon(%ebp,%edi) //operand is inv/inf
185: testl $0x7fffffff,frac32(%ebp,%edi)
186: movb infinty,tag(%ebp,%edi)
187: jz sngl_exit
188: movb inv,tag(%ebp,%edi) //invalid operand
189: testb $0x40,msb(%ebp,%edi)
190: jnz sngl_qnan
191: movb true,signal_i_error_
192: sngl_qnan:
193: sngl_exit:
194: ret //set tag to invalid
195: ALIGN
196: single_operand_is_valid:
197: movb valid,tag(%ebp,%edi) //set tag to valid
198: add single_exp_offset,%eax //single_exp_offset,
199: mov %eax,expon(%ebp,%edi) //implicit bit to 1
200: orb $0x80,frac64+7(%ebp,%edi)
201: ret
202: ALIGN
203: //extend_single endp
204: //
205: // ***********************************************************************
206: // extend_double:
207: // **************
208: // function:
209: // retrieves a double real operand from memory,
210: // extends its parts, and puts them in the operand
211: //
212: // inputs:
213: // assumes mem_operand_pointer is set up
214: // edi points to operand1 or operand2
215: //
216: // outputs:
217: // expanded operand in operand
218: //
219: // data accessed:
220: // - mem_operand_pointer
221: //
222: // data changed:
223: // - operand
224: //
225: // procedures called:
226: //
227: //
228: // *********************************************************************
229: ALIGN
230: extend_double: //proc
231: // push %ds // save a?msr
232: les mem_operand_pointer(%ebp),%ebx
233: movb $0,frac64(%ebp,%edi) //clear low byte of
234: mov %es:(%ebx),%eax //fraction to 0
235:
236: //..
237: //.. pushad
238: //.. push ds
239: //.. push ebx
240: //.. call fpfulong
241: //.. pop ebx
242: //..
243: mov %eax,frac64+1(%ebp,%edi) //move 7 fraction bytes
244: mov %es:4(%ebx),%eax // from memory
245: //..
246: //.. push ebx+4
247: //.. call fpfulong
248: //.. add esp, 8
249: //.. popad
250: //.. cld
251:
252: // pop %ds // reload a?msr
253: mov %eax,frac32+1(%ebp,%edi)
254: sar $20,%eax
255: cwtd
256: movb %dl,sign(%ebp,%edi) // transfer sign to operand
257: and $0x000007ff,%eax // strip sign bits (here,
258: // b11 - b31)
259: movl $0,before_error_signals(%ebp) // initialize both to false
260: jnz double_invalid_
261: mov frac64(%ebp,%edi),%eax // exp=0 : is fraction 0?
262: or frac32(%ebp,%edi),%eax
263: jnz double_denormalized
264: jmp zero_return
265: ALIGN
266: double_denormalized:
267: movb denormd,tag(%ebp,%edi) // set tag to denormd
268: movb true,signal_d_error_
269: testb denorm_mask,%gs:sr_masks // short cut for unmasked d-error
270: jnz dubl_d_error_masked
271: ret
272: ALIGN
273: dubl_d_error_masked:
274: movl double_exp_offset+1+3,expon(%ebp,%edi)
275: bsrl frac32(%ebp,%edi),%ecx
276: jz top_28_zero
277: mov frac64(%ebp,%edi),%eax
278: sub $31,%ecx
279: neg %ecx
280: shldl %cl,%eax,frac32(%ebp,%edi)
281: shll %cl,frac64(%ebp,%edi)
282: dubl_denorm_expon:
283: sub %ecx,expon(%ebp,%edi) // adjust exponent
284: ret
285: ALIGN
286: top_28_zero:
287: mov frac64(%ebp,%edi),%eax
288: bsrl %eax,%ecx
289: sub $31,%ecx
290: neg %ecx
291: shll %cl,%eax
292: mov %eax,frac32(%ebp,%edi)
293: movl $0,frac64(%ebp,%edi)
294: add $32,%ecx
295: jmp dubl_denorm_expon
296: ALIGN
297: double_invalid_:
298: cmpw $0x07ff,%ax
299: jne double_operand_is_valid
300: movl $0x7fff,expon(%ebp,%edi) // operand is nan or
301: andl $0x0fffffff,frac32(%ebp,%edi) // inf. set exponent.
302: mov frac32(%ebp,%edi),%eax // mask expon bits
303: or frac64(%ebp,%edi),%eax
304: movb infinty,tag(%ebp,%edi)
305: jz dubl_msb_set
306: movb inv,tag(%ebp,%edi) // invalid operand
307: testb $0x08,msb(%ebp,%edi)
308: jnz dubl_qnan
309: movb true,signal_i_error_
310: testb invalid_mask,%gs:sr_masks
311: jz dubl_exit
312: dubl_qnan:
313: jmp norm_dubl_sgnfcnd
314: ALIGN
315: double_operand_is_valid:
316: add double_exp_offset,%eax // double_exp_offset
317: mov %eax,expon(%ebp,%edi)
318: movb valid,tag(%ebp,%edi) // set operand tag
319: norm_dubl_sgnfcnd:
320: mov frac64(%ebp,%edi),%eax
321: .byte 0x0f,0xa4,0x44,0x3d,0x08,0x03 //implements following inst.
322: // shldl $3,%eax,frac32(%ebp,%edi)
323: shll $3,frac64(%ebp,%edi)
324: dubl_msb_set:
325: orb $0x80,frac64+7(%ebp,%edi) //set leading bit
326: dubl_exit:
327: ret
328: //extend_double endp
329: //
330: // ****************************************************************************
331: // getx:
332: // *****
333: // function:
334: // fetches extended-format fp number from memory, unpacks it,
335: // and sets its tag
336: //
337: // inputs:
338: // assumes mem_operand_pointer is set up
339: // edi points to operand1 or operand2
340: //
341: // outputs:
342: // if number is valid, then exponent and msb set to all ones
343: //
344: // data accessed:
345: // - mem_operand_pointer extra_word_reg
346: //
347: // data changed:
348: // - operand extra_word_reg
349: //
350: // procedures called:
351: // test_4w test_3w
352: // set_d_error
353: //
354: // ****************************************************************************
355: ALIGN
356: getx: //proc
357: // push %ds // save a?msr
358: les mem_operand_pointer(%ebp),%esi // ds:esi ==> memop
359: //
360: getx_stackreg:
361: // push %ss
362: // pop %es // es:edi ==> operand
363:
364: add $frac64,%edi // bump di to frac64
365: push %edi // save operand offset
366: lea (%ebp,%edi),%edi
367: // mov $0x0002,%ecx // move first four words
368: /* FAST_MOVSL */
369:
370: movl %es:0(%esi),%ecx
371: movl %ecx,%ss:0(%edi)
372: movl %es:4(%esi),%ecx
373: movl %ecx,%ss:4(%edi)
374: // addl $8,%esi
375: // movl $0,%ecx
376:
377: movw %es:8(%esi),%ax // get sign/expon word
378: //.. pushad
379: //.. push ds
380: //..rep_loop:
381: //.. push esi
382: //.. call fpfulong
383: //.. pop esi
384: //.. stosd
385: //.. add esi,4
386: //.. loop rep_loop
387: //.. push esi
388: //.. call fpfushort
389: //.. add esp,8
390: //.. popad
391: //.. cld
392: //..
393: pop %edi // reload operand offset
394: // pop %ds // reload a?msr
395: cwtd // transmit sign to dx
396: movb %dl,sign-frac64(%ebp,%edi)// and to operand
397: and $0x7fff,%eax // strip off sign bit
398: mov %eax,expon-frac64(%ebp,%edi) // store to operand
399: movl $0,before_error_signals(%ebp) // initialize both to false
400: jz expon_zero // branch if exponent 0
401: testb $0x80,msb-frac64(%ebp,%edi)
402: jnz max_expon_
403: movb unsupp,%dl // we have an
404: jmp getx_set_tag // unsupported format
405: ALIGN
406: max_expon_:
407: cmpw $0x7fff,%ax // check for invalid
408: je not_validx // or infinity
409: movb valid,%dl // operand is valid
410: getx_set_tag:
411: movb %dl,tag-frac64(%ebp,%edi) // set operand tag
412: xor %eax,%eax // (for stackreg return)
413: ret
414: ALIGN
415: not_validx:
416: movb infinty,%dl
417: mov frac32-frac64(%ebp,%edi),%eax
418: and $0x07fffffff,%eax
419: or (%ebp,%edi),%eax
420: jz getx_set_tag
421: movb inv,%dl // set tag to invalid
422: jmp getx_set_tag
423: ALIGN
424: expon_zero:
425: mov frac32-frac64(%ebp,%edi),%eax
426: or (%ebp,%edi),%eax
427: movb special,%dl // set tag to special
428: jz getx_set_tag // if number is +/- 0
429: movb denormd,%dl // set tag to denormd
430: jmp getx_set_tag
431: ALIGN
432: //getx endp
433: //
434: // ****************************************************************************
435: // fetch_an_op:
436: // ***********
437: // function:
438: // fetches one operand(op1 or op2) and puts its parts
439: // in operand1 or operand2
440: //
441: // inputs:
442: // location of op info in esi
443: // location of the operand in edi
444: //
445: // outputs:
446: // operand parts in operand1 or operand2
447: //
448: // procedures called:
449: // mem_fetch_routine set_up_indefinite
450: // get_top
451: // getx_stackreg
452: //
453: // ***************************************************************************
454: fetch_location:
455: .long from_memory,from_stack_top,from_stack_minus_1
456: .long from_stack_plus_1,from_reg
457: mem_fetch_routine:
458: .long extend_single,extend_double,float16,float32
459: .long float64,getx,float16,float16,get_bcd
460: ALIGN
461: fetch_an_op: //proc
462: cmpb $null,format(%ebp,%esi)// if format = null,
463: je no_stack_error_on_fetch // then no operand to get
464: xor %ebx,%ebx
465: mov %ebx,(%ebp,%edi) // set low order dword of
466: movb location(%ebp,%esi),%bl // fraction to zero
467: shl $2,%ebx // handle each operand
468: jmp *%cs:fetch_location(%ebx) // location case separate
469: ALIGN
470: from_memory:
471: movb format(%ebp,%esi),%bl // form table offset
472: shl $2,%ebx
473: call *%cs:mem_fetch_routine(%ebx) // call routine to fetch
474: no_stack_error_on_fetch:
475: xor %eax,%eax // eax = 00000000h
476: ret
477: ALIGN
478: from_stack_top:
479: call get_top // get reg num in al
480: unpack_reg:
481: call reg_full_ // zf=1 (empty) cx=top
482: jz from_stack_plus_1 // error if reg empty
483: mov %ebx,%esi // reg_full returns ebx as pointer
484: // to stackoffset =
485: // (10*regnum) + offset regstack
486: // thus, ds:esi ==> regstack
487: //
488: // push %ds // stack a copy of a?msr
489: push %gs // set ds to address register stack
490: pop %es
491: jmp getx_stackreg // unpack register
492: ALIGN
493: from_stack_minus_1:
494: call get_top
495: incw %ax
496: jmp unpack_reg
497: ALIGN
498: from_reg:
499: call get_top
500: addb reg_num(%ebp),%al
501: jmp unpack_reg
502: ALIGN
503: from_stack_plus_1:
504: call set_up_indefinite // store indefinite opr
505: incw %ax // indicate stack error on return
506: ret
507:
508: //fetch_an_op endp
509: //
510: // *************************************************************************
511: // get_bcd:
512: // ********
513: // function:
514: // fetches a bcd number and converts it to an unpacked
515: // tempreal in operand1.
516: // inputs:
517: // assumes mem_operand_pointer is set up.
518: // ignores di and uses operand2 and result fields.
519: //
520: // outputs:
521: // unpacked operand in operand1
522: //
523: // data accessed:
524: // - mem_operand_pointer expon1
525: // - offset_operand1 sign1
526: // - tag1 word_frac1
527: // - offset_operand1 word_frac2
528: // - lsb__frac2 offset_operand2
529: // - result_word_frac offset_result
530: //
531: // data changed:
532: // - sign1 tag1
533: // - expon1 word_frac1
534: // - word_frac2 result_word_frac
535: //
536: // procedures called:
537: // left_shift move_op_to_result
538: // subtraction_normalize test_6w
539: //
540: // ******************************************************************************
541: ALIGN
542: get_bcd: //proc
543: // push %ds // save a?msr
544: les mem_operand_pointer(%ebp),%esi
545: // push %ss // set up destination pointer
546: // pop %es
547: lea word_frac2,%edi // es:di ==> word_frac2
548: // mov $0x0005,%ecx
549:
550: /* FAST_MOVSW */
551: movl %es:0(%esi),%ecx
552: movl %ecx,%ss:0(%edi)
553: movl %es:4(%esi),%ecx
554: movl %ecx,%ss:4(%edi)
555: movw %es:8(%esi),%cx
556: movw %cx,%ss:8(%edi)
557: // addl $10,%esi
558: // movl $0,%ecx
559:
560: //..
561: //.. pushad
562: //.. push ds
563: //..getbcd_loop:
564: //.. push esi
565: //.. call fpfushort
566: //.. pop esi
567: //.. stosw
568: //.. add esi,2
569: //.. loop getbcd_loop
570: //.. pop ds
571: //.. popad
572: //.. cld
573: //..
574: // pop %ds // reload a?msr
575: cmpw $0x0ffff,dword_frac1+10(%ebp)
576: jne accept_bcd
577: mov $offset_operand1,%edi
578: call set_up_indefinite
579: ret
580: ALIGN
581: accept_bcd:
582: movb msb_frac2,%al // get most significant byte
583: cbtw // and transmit sign to ah
584: movb %ah,sign1(%ebp) // store sign into operand
585: mov $offset_operand1,%edi // set frac1 to 0
586: call clear_6w
587: movb $18,%cl //set loop count to 18 digits
588: FALLSTHRU
589: convert_loop:
590: push %ecx
591: movb $4,%cl //shift frac2 left 4 bits to
592: call left_shift_frac2_cl // the next digit
593: and $0x0f,msb_frac2 //clear previous digit
594: call left_shift_frac1_1 // frac1 <= 10*frac1 + frac2(9):
595: mov $offset_operand1,%esi // 1) frac1 <= frac1 * 2
596: call move_op_to_result // 2) result_frac <= frac1 * 4
597: movb $2,%cl
598: call left_shift_result_cl
599: // mov ax,(ebp).result_word_frac ; 3) frac1 <-- frac1 +
600: // add word_frac1,ax ; result_frac
601: // mov ax,(ebp).result_word_frac + 2
602: // adc (ebp).word_frac1 + 2,ax
603: // mov ax,(ebp).result_word_frac + 4
604: // adc (ebp).word_frac1 + 4,ax
605: // mov ax,(ebp).result_word_frac + 6
606: // adc (ebp).word_frac1 + 6,ax
607: // mov ax,(ebp).result_word_frac + 8
608: // adc (ebp).word_frac1 + 8,ax
609: //
610: mov result_dword_frac(%ebp),%eax // 3) frac1 <-- frac1 +
611: xorw %ax,%ax
612: add %eax,dword_frac1(%ebp) // result_frac
613: mov result_dword_frac+4(%ebp),%eax
614: adc %eax,dword_frac1+4(%ebp)
615: mov result_dword_frac+8(%ebp),%eax
616: adc %eax,dword_frac1+8(%ebp)
617: xor %eax,%eax // 4) frac1 <-- frac1 + frac(9)
618: movb msb_frac2,%al
619: addw %ax,word_frac1
620: movb $0,%al
621: adc %eax,dword_frac1+4(%ebp)
622: adc %eax,dword_frac1+8(%ebp)
623: pop %ecx //and loop
624: LOOP(convert_loop)
625: mov $dword_frac1,%edi
626: call test_6w //frac1 = 0?
627: jnz make_floating_point
628: mov %eax,dword_expon1 //set expon and tag for zero
629: movb special,tag1(%ebp)
630: ret
631: ALIGN
632: make_floating_point:
633: movl $0x404e,dword_expon1 //set expon1 and normalize
634: mov $offset_operand1,%edi
635: call subtraction_normalize
636: movb valid,tag1(%ebp) //set tag to valid
637: ret
638: //get_bcd endp
639: //
640: // ******************************************************************************
641: // put_result:
642: //
643: // function:
644: // puts result on 80387 stack or in 80387 register.
645: // implements 80387 load instruction.
646: //
647: // inputs:
648: // address of data parts (in edi register)
649: // address of result info (in esi).
650: // (ebp).before_error_signals
651: // outputs:
652: // stack error indication (in al register).
653: //
654: // data accessed:
655: //
656: // data changed:
657: //
658: // procedures called:
659: // decr_top stack_full?
660: // set_up_indefinite store_reg_tag
661: // get_top
662: //
663: // ***************************************************************************
664: location_case:
665: .long push_onto_stack
666: .long put_in_stack_top
667: .long put_in_stack_top_minus_1
668: .long push_onto_stack
669: .long put_in_reg
670: //
671: ALIGN
672: load: //proc
673: jz put_zf_in_ah // if zf set, no stack error
674: call set_stk_u_error
675: testb invalid_mask,%gs:sr_masks // else, stack underflow error
676: jnz put_zf_in_ah // if i_error masked, continue
677: ret // else, return
678: ALIGN
679: put_zf_in_ah: // if zf is set here, no stack
680: lahf // underflow occurred. however,
681: // if zf is clear, stack underflow
682: // occurred and invalid is masked.
683: jnz put_op1_result
684: common_clear_a_bit:
685: andb $~a_mask,%gs:sr_flags
686: put_op1_result:
687: mov $offset_operand1,%edi // edi points to result record
688: put_si_result:
689: mov offset_result_rec,%esi // merge with put_result
690: put_result:
691: movzbl location(%ebp,%esi),%ebx //handle cases separately
692: shl $2,%ebx
693: jmp *%cs:location_case(%ebx)
694: ALIGN
695: put_in_stack_top_minus_1:
696: call get_top // put reg num of top-1 in al
697: incw %ax
698: jmp mask_top
699: ALIGN
700: push_onto_stack:
701: sahf // zf clear iff stack underflow occurred with
702: jnz push_value // invalid exception masked
703: call stack_full_ // is top - 1 full?
704: jz other_before_error_ // no, so detect other before errors.
705: call set_stk_o_error // set invalid error, stack bit, and
706: // c1 (a) bit
707: testb invalid_mask,%gs:sr_masks
708: jz exit_load // unmasked, so done with load
709: call set_up_indefinite // push indefinite as the result
710: jmp push_value
711: ALIGN
712: other_before_error_:
713: mov before_error_signals(%ebp),%eax
714: or %eax,%eax
715: jz push_value
716: orb %al,%al
717: jz check_z_error
718: orb invalid_mask,%gs:sr_errors
719: testb invalid_mask,%gs:sr_masks
720: jz exit_load // unmasked, so done with load
721: orb $0x40,msb(%ebp,%edi)
722: jmp push_value
723: ALIGN
724: check_z_error:
725: orb %ah,%ah
726: jz signal_d_error
727: orb zero_divide_mask,%gs:sr_errors
728: testb zero_divide_mask,%gs:sr_masks
729: jz exit_load // unmasked, so done with load
730: jmp push_value
731: ALIGN
732: signal_d_error:
733: orb denorm_mask,%gs:sr_errors
734: testb denorm_mask,%gs:sr_masks
735: jz exit_load // unmasked, so done with load
736: // the following seven instructions were added to cope with a load from
737: // memory to (new) 87 stack top of a short_real or long_real operand.
738: // otherwise, such loads of a denormal source operand while the denormal
739: // exception is masked would incorrectly tag the loaded, normalized
740: // temporary_real operand as invalid, instead of valid. the first four
741: // of these seven instructions have been commented out, because the
742: // executive procedure e80387 in the module *dcode* always initializes
743: // the op1_format field, even when its contents are deducible from the
744: // operation_type and op1_location fields, so it is enough to check
745: // whether the format field is single_real or double_real.
746: // cmp (ebp).operation_type, load_op
747: // jne push value
748: // cmp (ebp).op1_location, memory_opnd
749: // jne push_value
750: cmpb $double_real,op1_format(%ebp)
751: ja push_value
752: movb valid,tag(%ebp,%edi)
753: push_value:
754: call decr_top // decrement top for push
755: put_in_stack_top:
756: call get_top // put reg num of stack top in al
757: jmp mask_top
758: ALIGN
759: put_in_reg:
760: call get_top // put reg num specified in
761: addb reg_num(%ebp),%al // instruction in al
762: mask_top:
763: and $0x0007,%eax
764: mov %eax,%ecx // save reg num word in cx
765: movb tag(%ebp,%edi),%al // put new tag in al
766: call store_reg_tag
767: lea frac64(%ebp,%edi),%esi// ds:esi ==> operand frac64
768: mov $sr_regstack,%edi // form offset within %gs:sr_regstack
769: add %ecx,%edi // for result (10 * reg num)
770: shl $2,%ecx
771: add %ecx,%edi // es:edi ==> treal st(reg num)
772: // mov $0x02,%ecx // count = 2 dwords
773: // push %gs // set segment registers
774: // pop %es
775: // push %ds
776: // push %ss
777: // pop %ds
778:
779: /* FAST_MOVSL */
780: movl %ss:0(%esi),%ecx
781: movl %ecx,%gs:0(%edi)
782: movl %ss:4(%esi),%ecx
783: movl %ecx,%gs:4(%edi)
784: // addl $8,%esi
785: // addl $8,%edi
786: // movl $0,%ecx
787:
788: movb %ss:8(%esi),%ah // ah = sign of operand
789: andw $0x8000,%ax // form tempreal exponent
790: orw %ss:12(%esi),%ax
791: // pop %ds // reload a?msr into ds
792: movw %ax,%gs:8(%edi) // exponent => %gs:sr_regstack
793: exit_load:
794: ret
795: //load endp
796: //
797: // *****************************************************************************
798: // stack_full?:
799: //
800: // function:
801: // checks stack to see if an attempted push will
802: // generate a stack error.
803: //
804: // inputs:
805: // tag for register on top of stack
806: //
807: // outputs:
808: // zf = true if stack is empty; zf = false if stack is full.
809: //
810: // procedures called:
811: // get_top get_reg_tag
812: //
813: // *****************************************************************************
814: ALIGN
815: stack_full_: //proc
816: call get_top // determine reg no. of (top-1)
817: decw %ax
818: reg_full_:
819: andb $0x07,%al
820: call get_reg_tag
821: cmpb $empty,%al // if (top-1) is not empty,
822: return:
823: ret // then stack is full
824: //stack_full_ endp
825: //
826: // ************************************************************************
827: // decompose:
828: //
829: // function:
830: // decomposes op1 into two parts
831: //
832: // inputs:
833: // assumes op1 is set up, with tag1 /= unsupp and tag1 /= inv
834: //
835: // outputs:
836: // puts the exponent, floated in op1; the fraction in op2
837: //
838: // data accessed:
839: // - offset_operand sign1
840: // - tag1 expon1
841: // - offset_operand2 sign2
842: // - tag2 expon2
843: //
844: // data changed:
845: // - sign2 expon2
846: //
847: // procedures called:
848: // float_int32 move_op_to_op
849: //
850: // ****************************************************************************
851: ALIGN
852: decompose: //proc
853: lea dword_frac1(%ebp),%esi // move op1 to op2
854: lea dword_frac2(%ebp),%edi
855: call move_op_to_op
856: cmpb valid,tag1(%ebp)
857: jne is_op1_denorm_
858: put_sig_in_op2:
859: movl $exponent_bias,dword_expon2 // set op2 exponent=bias
860: put_exp_in_op1:
861: mov dword_expon1,%eax // float exp into op1
862: unbias_expon:
863: sub $exponent_bias,%eax // first unbias it
864: mov $offset_operand1,%edi
865: jmp float_int32
866: ALIGN
867: is_op1_denorm_:
868: cmpb denormd,tag1(%ebp)
869: jne op1_zero_or_inf
870: movb true,signal_d_error_
871: testb denorm_mask,%gs:sr_masks // short cut if unmasked d-error
872: jz interim_exit
873: mov $offset_operand2,%edi
874: call norm_denorm
875: mov dword_expon2,%eax
876: movl $exponent_bias,dword_expon2 // set op2 exponent=bias
877: jmp unbias_expon
878: ALIGN
879: op1_zero_or_inf:
880: cmpb special,tag1(%ebp)
881: je op1_zero // op1 and op2 are infinite
882: movb positive,sign1(%ebp)
883: interim_exit:
884: ret
885: ALIGN
886: op1_zero:
887: movb true,signal_z_error_ // if number=0, signal z-error
888: testb zero_divide_mask,%gs:sr_masks // if z_error is unmasked
889: jz interim_exit // then just return
890: make_op1_negative_inf:
891: movl $0x07fff,dword_expon1 // else, make op1 -infinity
892: movb $0x80,msb_frac1
893: movl infinty*0x10000+NEGATIVE,sign1(%ebp)
894: ret
895: //decompose endp
896: //
897: // **************************************************************************
898: // float16:
899: //
900: // function:
901: // retrieves a 16-bit, 2s complement integer from memory,
902: // and fills in the operand
903: //
904: // inputs:
905: // assumes mem_operand_pointer is set up
906: // edi points to operand1 or operand2
907: //
908: // outputs:
909: // operand
910: //
911: // data accessed:
912: // - mem_operand_pointer
913: //
914: // data changed:
915: // - operand
916: //
917: // procedures called:
918: // float_int32
919: //
920: // ***************************************************************************
921: ALIGN
922: float16: //proc
923: les mem_operand_pointer(%ebp),%ebx // fetch the
924: // 16-bit integer
925: movw %es:(%ebx),%ax
926: //..
927: //.. pushad
928: //.. push es
929: //.. push ebx
930: //.. call fpfushort
931: //.. add esp,8
932: //.. popad
933: //.. cld
934: //..
935: float_int16:
936: movswl %ax,%eax
937: jmp float_int32
938: ALIGN
939: //
940: //
941: //
942: // *****************************************************************************
943: // float32:
944: //
945: // function:
946: // retrieves a 32-bit, 2s complement integer from memory
947: // and fills in the operand
948: //
949: // inputs:
950: // assumes mem_operand_pointer is set up
951: // edi points to operand1 or operand2
952: //
953: // outputs:
954: // operand
955: //
956: // data accessed:
957: // - mem_operand_pointer
958: //
959: // data changed:
960: // - operand
961: //
962: // procedures called:
963: //
964: //
965: // *****************************************************************************
966: float32:
967: les mem_operand_pointer(%ebp),%ebx
968:
969: mov %es:(%ebx),%eax // move from memory to eax
970:
971: //..
972: //.. pushad
973: //.. push es
974: //.. push ebx
975: //.. call fpfulong
976: //.. add esp,8
977: //.. popad
978: //.. cld
979:
980: float_int32:
981: mov %eax,%edx // save integer in edx
982: xor %eax,%eax // clear low 8 bytes
983: mov %eax,(%ebp,%edi)
984: mov %eax,frac64(%ebp,%edi)
985: or %edx,%eax // if integer is zero,
986: jnz get_sign_and_mag_32 // then load +0
987: mov %eax,frac32(%ebp,%edi)
988: movb %al,sign(%ebp,%edi)
989: movb special,tag(%ebp,%edi)
990: mov %eax,expon(%ebp,%edi)
991: ret
992: ALIGN
993: get_sign_and_mag_32:
994: cltd // transmit sign to edx
995: movb %dl,sign(%ebp,%edi) // and store to operand
996: jns positive_int // branch if positive
997: neg %eax // negate if negative
998: positive_int:
999: bsrl %eax,%ecx
1000: sub $31,%ecx
1001: neg %ecx
1002: shl %cl,%eax
1003: mov %eax,frac32(%ebp,%edi) // store normalized{abs(int)}
1004: mov $0x401e,%eax // load valid exponent
1005: sub %ecx,%eax
1006: mov %eax,expon(%ebp,%edi)
1007: movb valid,tag(%ebp,%edi)
1008: ret
1009: ALIGN
1010: //float16 endp
1011: //
1012: // ******************************************************************************
1013: // float64:
1014: //
1015: // function:
1016: // retrieves a 64-bit, 2s complement integer from memory
1017: // and fills in the operand
1018: //
1019: // inputs:
1020: // assumes mem_operand_pointer is set up
1021: // edi points to operand1 or operand2
1022: //
1023: // outputs:
1024: // operand
1025: //
1026: // data accessed:
1027: // - mem_operand_pointer
1028: //
1029: // data changed:
1030: // - operand
1031: //
1032: // procedures called:
1033: //
1034: //
1035: // ****************************************************************************
1036: ALIGN
1037: float64: //proc
1038: // push %ds // save a?msr
1039: les mem_operand_pointer(%ebp),%esi
1040: // push %ss
1041: // pop %es // es:edi ==> operand
1042: push %edi // save op? offset
1043: lea frac64(%ebp,%edi),%edi // set operand offset
1044: // mov $0x0002,%ecx // move fraction from
1045:
1046: /* FAST_MOVSL */
1047: movl %es:0(%esi),%ecx
1048: movl %ecx,%ss:0(%edi)
1049: movl %es:4(%esi),%ecx
1050: movl %ecx,%ss:4(%edi)
1051: // addl $8,%esi
1052: // addl $8,%edi
1053: // movl $0,%ecx
1054:
1055: //..
1056: //.. pushad
1057: //.. push ds
1058: //..float64_loop:
1059: //.. push esi
1060: //.. call fpfulong
1061: //.. pop esi
1062: //.. add esi,4
1063: //.. stosd
1064: //.. loop float64_loop
1065: //.. pop ds
1066: //.. popad
1067: //.. cld
1068: //..
1069: pop %edi // reload operand offset
1070: // pop %ds // reload a?msr
1071: mov frac32(%ebp,%edi),%eax // get long integer sign
1072: cltd // transmit sign to edx
1073: movb %dl,sign(%ebp,%edi) // and store to operand
1074: inc %edx // test for '-' fract
1075: jnz detect_zero_64
1076: notl frac64(%ebp,%edi) // '-', so form 2s
1077: add $1,frac64(%ebp,%edi) // complement
1078: notl frac32(%ebp,%edi)
1079: adc $0,frac32(%ebp,%edi)
1080: jmp set_expon_64
1081: ALIGN
1082: detect_zero_64:
1083: or frac64(%ebp,%edi),%eax
1084: jnz set_expon_64
1085: mov %eax,expon(%ebp,%edi) // set expon = zero
1086: movb special,tag(%ebp,%edi)
1087: ret
1088: ALIGN
1089: set_expon_64:
1090: movl $0x403e,expon(%ebp,%edi) //set expon = 63
1091: bsrl frac32(%ebp,%edi),%ecx
1092: jz top_32_zero
1093: mov frac64(%ebp,%edi),%eax
1094: sub $31,%ecx
1095: neg %ecx
1096: shldl %cl,%eax,frac32(%ebp,%edi)
1097: shl %cl,frac64(%ebp,%edi)
1098: adjust_norm_expon:
1099: sub %ecx,expon(%ebp,%edi) // adjust exponent
1100: ret
1101: ALIGN
1102: top_32_zero:
1103: mov frac64(%ebp,%edi),%eax
1104: bsrl %eax,%ecx
1105: sub $31,%ecx
1106: neg %ecx
1107: shl %cl,%eax
1108: mov %eax,frac32(%ebp,%edi)
1109: movl $0,frac64(%ebp,%edi)
1110: add $32,%ecx
1111: jmp adjust_norm_expon
1112: ALIGN
1113: //float64 endp
1114: //
1115: // ***************************************************************************
1116: // save:
1117: //
1118: // function:
1119: // implements 80387 save instruction
1120: //
1121: // inputs:
1122: //
1123: // outputs:
1124: //
1125: // data accessed:
1126: // - mem_operand_pointer result_rec_offset
1127: //
1128: // data changed:
1129: //
1130: // procedures called:
1131: // save_status save_regs init
1132: //
1133: // **************************************************************************
1134: ALIGN
1135: save: //proc
1136: call save_status
1137: call save_regs
1138: jmp init // initialize environment
1139: //save endp
1140: //
1141: // *************************************************************************
1142: // save_regs:
1143: //
1144: // function:
1145: // saves all registers in contiguous memory locations.
1146: //
1147: // inputs:
1148: // memory operand pointer (in es:(di))
1149: //
1150: // outputs:
1151: //
1152: // data accessed:
1153: //
1154: // data changed:
1155: //
1156: // procedures called:
1157: // get_top
1158: //
1159: // ***************************************************************************
1160: ALIGN
1161: save_regs: //proc
1162: movb $5,%cl // 5 words per register
1163: call get_top // ax = top * 5
1164: push %ds // set source seg register
1165: push %gs
1166: pop %ds
1167: mulb %cl
1168: movw $40,%cx // number words to move
1169: subw %ax,%cx // from top of stack =
1170: mov $sr_regstack,%esi // 40 - top*5
1171: push %esi // starting address =
1172: cwtl
1173: add %eax,%esi // %gs:sr_regstack + top*5
1174: add %eax,%esi // *2 bytes/word
1175: movzwl %cx,%ecx
1176: FAST_MOVSW
1177: movw %ax,%cx // move (top * 5) words
1178: pop %esi // load starting address
1179: FAST_MOVSW
1180: pop %ds // restore %ds
1181: ret
1182: //save_regs endp
1183: //
1184: // *****************************************************************************
1185: // restore_regs:
1186: //
1187: // function:
1188: // loads all registers from contiguous memory locations
1189: // implements 80387 restore instruction
1190: //
1191: // inputs:
1192: // mem_operand_pointer
1193: //
1194: // outputs:
1195: // loads the %gs:sr_regstack area of a?msr from memory
1196: //
1197: // data accessed:
1198: //
1199: // data changed:
1200: // - operand
1201: //
1202: // procedures called:
1203: // restore_status get_top
1204: //
1205: // *************************************************************************
1206: ALIGN
1207: restore: //proc
1208: call restore_status // this call defines es
1209: restore_regs:
1210: movb $5,%cl // 5 words per register
1211: call get_top
1212: push %ds // save a?msr
1213: // pop %es
1214: // push %ds
1215: mulb %cl // ax = top*5
1216: mov $40,%ecx // number words to move
1217: subw %ax,%cx // from top of stack =
1218: mov $sr_regstack,%edi // 40 - top*5
1219: push %edi // starting address =
1220: cwtl
1221: add %eax,%edi // %gs:sr_regstack + top*5
1222: add %eax,%edi // *2 bytes/word
1223: lds mem_operand_pointer(%ebp),%esi // source is in memory
1224: add $14,%esi
1225: cmpb $1,oprnd_siz32(%ebp) //is it a 32 bit operand
1226: jne status16 //no restore 16 bit status
1227: add $14,%esi // skip the environment
1228: // --------replace following line for unix
1229: status16:
1230: FAST_MOVSW
1231:
1232: //..
1233: //.. pushad
1234: //.. push ds
1235: //..restor_loop:
1236: //.. push esi
1237: //.. call fpfushort
1238: //.. pop esi
1239: //.. stosw
1240: //.. add esi,2
1241: //.. loop restor_loop
1242: //.. pop ds
1243: //.. popad
1244: //.. cld
1245: //..
1246: movw %ax,%cx
1247: pop %edi // load starting address
1248: FAST_MOVSW
1249: pop %ds // reload a?msr
1250: jmp correct_tag_word
1251:
1252: // ret
1253: //restore endp
1254: //
1255: // *****************************************************************************
1256: // set_up_indefinite:
1257: //
1258: // function:
1259: // puts indefinite in the operand pointed to by edi
1260: //
1261: // input:
1262: // edi points to operand
1263: //
1264: // output:
1265: // indefinite in operand, eax = 0, zf set (zf = 1)
1266: //
1267: // data accessed:
1268: // - operand
1269: //
1270: // data changed:
1271: // - operand
1272: //
1273: // ****************************************************************************
1274: ALIGN
1275: set_up_indefinite: //proc
1276: xor %eax,%eax
1277: mov %eax,frac64(%ebp,%edi) //set up indef fraction
1278: movl $0x0c0000000,frac32(%ebp,%edi)
1279: movb negative,sign(%ebp,%edi) //set sign negative
1280: movl $0x7fff,expon(%ebp,%edi) //set exponent to 7fffh
1281: movb inv,tag(%ebp,%edi) //set tag to invalid
1282: common_return:
1283: ret
1284: ALIGN
1285: //set_up_indefinite endp
1286: //
1287: // ***********************************************************************
1288: // exchange
1289: //
1290: //
1291: // function:
1292: // implements 80387 exchange instruction
1293: //
1294: // inputs:
1295: // operand(s) in operands
1296: //
1297: // outputs:
1298: // result(s) on stack
1299: //
1300: // data accessed:
1301: // - result_rec_offset offset_operand1
1302: //
1303: // data changed:
1304: //
1305: // procedures called:
1306: // put_result set_stk_u_error
1307: //
1308: // *************************************************************************
1309: ALIGN
1310: exchange: //proc
1311: jz do_exchange // if zf clear, then stack error
1312: call set_stk_u_error
1313: testb invalid_mask,%gs:sr_masks
1314: jz common_return // if unmasked error, do nothing
1315: do_exchange:
1316: // call common_clear_a_bit / put op1(top) in result(reg)
1317: and $~a_mask,%gs:sr_flags
1318: do_exchange_leave_a_bit:
1319: call put_op1_result
1320: set_zf_put_second_result:
1321: xor %eax,%eax // set 86 zf
1322: lahf // save set zf in ah
1323: put_second_result:
1324: mov $offset_operand2,%edi // put op2(reg) in res2(top)
1325: mov offset_result2_rec,%esi
1326: jmp put_result
1327: //exchange endp
1328: //
1329: // ***********************************************************************
1330: // exam:
1331: //
1332: // function:
1333: // implements 80387 fxam instruction
1334: //
1335: // inputs:
1336: // operand1
1337: //
1338: // outputs:
1339: // operand type indicators set
1340: //
1341: // data accessed:
1342: // - tag1 sign1
1343: // - msb_frac1
1344: //
1345: // data changed:
1346: //
1347: // procedures called:
1348: //
1349: // ***********************************************************************
1350: ALIGN
1351: exam: //proc
1352: jz something_on_stack // branch on no stack error
1353: orb $(zero_mask+sign_mask),%gs:sr_flags // set s and z bits
1354: andb $~(a_mask+c_mask),%gs:sr_flags // clear a and c bits
1355: jmp check_a_bit
1356: ALIGN
1357: something_on_stack:
1358: andb $~(zero_mask+c_mask+a_mask+sign_mask),%gs:sr_flags
1359: // clear condition code bits
1360: movb tag1(%ebp),%al
1361: cmpb unsupp,%al
1362: je check_a_bit
1363: cmpb inv,%al // remove special cases
1364: je check_z_s_a_bits
1365: cmpb infinty,%al
1366: je set_c_to_one
1367: cmpb denormd,%al
1368: jne valid_or_zero
1369: orb $(zero_mask+c_mask),%gs:sr_flags // set s, z, c to 0, 1, 1
1370: // for denormalized op
1371: jmp check_a_bit
1372: ALIGN
1373: valid_or_zero:
1374: testb $0x80,msb_frac1 // for valid or zero,
1375: jz check_z_s_a_bits // set c to msb of frac
1376: set_c_to_one:
1377: orb $c_mask,%gs:sr_flags
1378: check_z_s_a_bits:
1379: rorb $1,%al // set z-bit to lsb of tag1
1380: jnc check_s_a_bits
1381: orb $zero_mask,%gs:sr_flags
1382: check_s_a_bits:
1383: rorb $1,%al // set s-bit to lsb-1 of tag1
1384: jnc check_a_bit
1385: orb $sign_mask,%gs:sr_flags
1386: check_a_bit:
1387: testb $0x01,sign1(%ebp) // set a-bit to sign bit
1388: jz exchange_return
1389: orb $a_mask,%gs:sr_flags // set_a_bit
1390: exchange_return:
1391: ret
1392: //exam endp
1393: //
1394: // ***********************************************************************
1395: // fxtrac:
1396: //
1397: // function:
1398: // implements the 80387 fxtrac instruction
1399: //
1400: // inputs:
1401: //
1402: // outputs:
1403: // decomposed results in results
1404: //
1405: // data accessed:
1406: // - result_rec_offset result2_rec_offset
1407: // - offset_operand1 tag1
1408: // - offset_operand2
1409: //
1410: // data changed:
1411: //
1412: // procedures called:
1413: // set_up_indefinite decompose
1414: // do_exchange
1415: //
1416: // ***********************************************************************
1417: ALIGN
1418: fxtrac: //proc
1419: jz detect_i_error // branch if no stack error
1420: call set_stk_u_error // set invalid error and stack bit, but
1421: // clear c1 (a) bit
1422: testb invalid_mask,%gs:sr_masks
1423: jz quick_out // branch if error unmasked
1424: mov $offset_operand2,%edi // for masked invalid error,
1425: call set_up_indefinite // set op2 to indefinite
1426: orb true,%al // clear zf to indicate that
1427: lahf // stack underflow occurred.
1428: jmp put_second_result
1429: ALIGN
1430: detect_i_error:
1431: call stack_full_
1432: jz other_i_error_
1433: jmp set_zf_put_second_result
1434: ALIGN
1435: other_i_error_:
1436: andb $~a_mask,%gs:sr_flags // clear a-bit
1437: movl $0,before_error_signals(%ebp) // initialize all to zero
1438: movb tag1(%ebp),%al // load operand tag
1439: cmpb unsupp,%al
1440: jne is_op1_nan_
1441: testb invalid_mask,%gs:sr_masks // short cut if unmasked i-error
1442: jnz put_indef_in_op1
1443: unmasked_i_error:
1444: orb invalid_mask, %gs:sr_errors
1445: quick_out:
1446: ret // return if unmasked error
1447: ALIGN
1448: put_indef_in_op1:
1449: mov $offset_operand1, %edi
1450: call set_up_indefinite
1451: jmp masked_i_error
1452: ALIGN
1453: is_op1_nan_:
1454: cmpb inv,%al
1455: jne do_decompose
1456: testb $0x40,msb_frac1 // is op1 a signaling nan?
1457: jnz op1_is_qnan
1458: testb invalid_mask,%gs:sr_masks
1459: jz unmasked_i_error
1460: orb $0x40,msb_frac1 // make op1 a quiet nan
1461: masked_i_error:
1462: movb true, signal_i_error_
1463: op1_is_qnan:
1464: lea dword_frac1(%ebp),%esi // move op1 to op2
1465: lea dword_frac2(%ebp),%edi
1466: call move_op_to_op
1467: call put_op1_result // no push occurs here
1468: jmp set_zf_put_second_result // put both results
1469: ALIGN
1470: do_decompose:
1471: call decompose
1472: jmp do_exchange // put both results
1473: ALIGN
1474: //fxtrac endp
1475: //
1476: // ***********************************************************************
1477: // abs_value:
1478: //
1479: // function:
1480: // implements the 80387 absolute value instruction
1481: //
1482: // inputs:
1483: // assumes operand is set up
1484: //
1485: // outputs:
1486: // absolute value of operand in result
1487: //
1488: // procedures called:
1489: // set_stk_u_error
1490: //
1491: // ***************************************************************************
1492: ALIGN
1493: abs_value: //proc
1494: jz do_abs_value // branch if no stack error
1495: call set_stk_u_error // set invalid error and stack bit,
1496: // but clear c1 (a) bit
1497: testb invalid_mask,%gs:sr_masks
1498: jnz abs_value_result // masked error, so give indef already
1499: common_exit: // set up in operand1 by fetch_an_op.
1500: ret // unmasked error
1501: ALIGN
1502: do_abs_value:
1503: movb positive,sign1(%ebp)// set sign to positive
1504: abs_value_result:
1505: jmp common_clear_a_bit // put result on stack
1506: //abs_value endp
1507: //
1508: // ***********************************************************************
1509: // chsign:
1510: //
1511: // function:
1512: // implement the 80387 chsign instruction
1513: //
1514: // inputs:
1515: // operand1
1516: //
1517: // outputs:
1518: // result <== -(operand1)
1519: //
1520: // procedures called:
1521: // set_stk_u_error
1522: //
1523: // ************************************************************************
1524: ALIGN
1525: chsign: //proc
1526: jz do_chsign // branch if no stack error
1527: call set_stk_u_error // set invalid error and stack bit, but
1528: // clear c1 (a) bit
1529: testb invalid_mask,%gs:sr_masks
1530: jnz chsign_result // put op1, set up as qnan indefinite
1531: ret // by fetch_an_op, into result
1532: ALIGN
1533: do_chsign:
1534: notb sign1(%ebp) // complement sign
1535: chsign_result:
1536: jmp common_clear_a_bit // put op1 into result
1537: ALIGN
1538: //chsign endp
1539: //
1540: //a_med ends
1541: //
1542: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.