|
|
Darwin 0.1 Mach+BSD kernel
/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.1 (the "License"). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ .file "store.s" .ident "@(#)kern-fp:store.s 1.1" //$tt(*80387 emulator+++s t o r e+++*) // *************************************************************************** // // s t o r e . m o d // ================== // // ============================================================= // intel corporation proprietary information // this software is supplied under the terms of a license // agreement or non-disclosure agreement with intel corporation // and may not be copied nor disclosed except in accordance with // the terms of that agreement. // =============================================================== // // function: // implements 80387 store, fix, and storex instructions. // // public procedures: // store fix16 fix32 fix64 move_op_to_op // // internal procedures: // extended_store bcd_store // single_real_store double_real_store // store_valid int64_store // int16_store int32_store // // ************************************************************************ // //...december 12, 1986.. // //$nolist #include "fp_e80387.h" //$list .data //a_msr segment rw public // extrn %gs:sr_masks,%gs:sr_flags,%gs:sr_errors,%gs:sr_controls //a_msr ends // // assume %ds:a_msr // .text //a_med segment er public // // extrn pop_free,clear_6w,test_3w,subadd // extrn gradual_underflow,right_shift_frac2_cl // extrn special_round_test,directed_round_test // extrn right_shift_result_cl,set_up_indefinite // extrn right_shift_frac1_cl,sticky_right_shift // extrn left_shift_frac1_cl,left_shift_result_cl // extrn put_op1_result,divid,addition_normalize // extrn round,get_precision,get_rnd_control // extrn store_precision,set_i_error,i_masked_ // extrn set_o_error,o_masked_,set_p_error // extrn set_u_error,test_4w,subtraction_normalize // extrn p_error_,clear_p_error,add_to_frac // extrn move_constant,set_stk_u_error,norm_denorm // extrn %gs:sr_mem_offset // --------to be added for unix //.. extrn fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far // .globl store .globl fix16 .globl fix32 .globl fix64 .globl move_op_to_op // store_routine: .long single_real_store,double_real_store,int16_store .long int32_store,int64_store,extended_store .long int16_store,int16_store,bcd_store // // ************************************************************************* // store: // ****** // function: // implements all store instructions . // // inputs: // operand1; format of result. // // outputs: // operand in *result_format* stored in memory // destination pointed to by es:di. // // data accessed: // - result_rec_offset result_format // - offset_operand1 // // data changed: // - result record // // procedures called: // set_up_indefinite store routine (result format) // i_masked? // // **************************************************************************** ALIGN store: //proc jz no_unmasked_stack_error // branch if no stack error call set_stk_u_error // stack underflow occurred testb invalid_mask,%gs:sr_masks // if unmasked, just exit jz return // else, store indef set up no_unmasked_stack_error: // in operand1 by fetch_an_op andb $~a_mask,%gs:sr_flags // clear a-bit get_result_loc: cmpb $reg,result_location(%ebp) jne store_to_memory // branch if memop call put_op1_result // give opnd1 as result jmp pop_free ALIGN store_to_memory: movzbl result_format(%ebp),%ebx// call a different rtn shll $2,%ebx // for each of the cmp $8,%ebx jge go_to_storer // do store of temporary real cmpb unsupp,tag1(%ebp) // detect unsupported pattern jne go_to_storer orb invalid_mask,%gs:sr_errors // set i_error testb invalid_mask,%gs:sr_masks // if unmasked, just exit jz return // else, set up indef in mov $offset_operand1,%edi // operand1. call set_up_indefinite go_to_storer: jmp *%cs:store_routine(%ebx) // output formats //store endp // // **************************************************************************** // move_op_to_op: // // function: // moves operand record (op1,op2,result_op,result2_op) to // another op. // // inputs: // ss:esi points to the source, and // ss:edi points to the destination // outputs: // operand record in destination // // data accessed: // operand or result variables // // data changed: // operand or result variables // // ***************************************************************************** ALIGN move_op_to_op: //proc // push %ds // save a?msr // push %ss // pop %ds push %ss pop %es mov $((sign2-sign1)>> 2),%ecx / set record length /* FAST_MOVSL */ push %eax 1: movl %ss:0(%esi),%eax movl %eax,%es:0(%edi) addl $4,%esi addl $4,%edi decl %ecx testl %ecx,%ecx jg 1b pop %eax // pop %ds // reload a?msr return: ret //move_op_to_op endp // // *************************************************************************** // extended_store: // *************** // function: // stores into double extended format. // // inputs: // operand1 // // outputs: // double extended operand in memory. // stack popped if indicated // // data accessed: // - mem_operand_pointer sign1 // - expon1 word_frac1 // // data changed: // // procedures called: // pop_free // // ***************************************************************************** ALIGN extended_store: //proc les mem_operand_pointer(%ebp),%edi //move frac to memory // push %ds // save a?msr // push %ss // pop %ds // set up source pointer lea 2+word_frac1,%esi /* FAST_MOVSL */ movl %ss:0(%esi),%ecx movl %ecx,%es:0(%edi) movl %ss:4(%esi),%ecx movl %ecx,%es:4(%edi) // addl $8,%esi // addl $8,%edi // movl $0,%ecx // pop %ds // reload a?msr movb sign1(%ebp),%ah // merge sign & exponent andw $0x8000,%ax // and move to memory orw expon1(%ebp),%ax movw %ax,%es:8(%edi) //.. //.. pushad //.. push es //.. push edi //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld jmp pop_free // pop stack, if needed //extended_store endp // // **************************************************************************** // bcd_store: // ********** // function: // stores into bcd format // // inputs: // operand1 // // outputs: // bcd operand in memory; stack popped // // data accessed: // - mem_operand_pointer operation_type // - offset_operand1 sign1 // - tag1 word_frac1 // - msb_frac1 offset_operand1 // - offset_operand2 sign2 // - expon2 word_frac2 // - offset_operand2 offset_result // - result_expon result_word_frac // - msb_result offset_result // // data changed: // - operation_type word_frac1 // - msb_frac1 sign2 // - expon2 word_frac2 // - result_word_frac msb_result // // procedures called: // move_op_to_op right_shift_frac1_cl // right_shift_frac2_cl right_shift_result_cl // left_shift_frac1_cl left_shift_result_cl // divid clear_6w // pop_free test_4w // add_to_frac move_constant // // ************************************************************************** ten_18: .value 0x0000,0x0000,0x0000,0x7640,0x6b3a,0x0de0b// frac for 10**18 // ALIGN bcd_store: //proc push %gs:sr_masks // save current precision orb prec64,%gs:sr_controls // and set to 64-bit cmpb special,tag1(%ebp) // separate bcd cases jne finite_value_ jmp store_signed_bcd ALIGN finite_value_: cmpl $0x07fff,dword_expon1 // is it a finite number? jne check_bcd_denorm // yes, branch to valid invalid_bcd: orb invalid_mask,%gs:sr_errors // set i_error testb invalid_mask,%gs:sr_masks // is i_error unmasked? jnz store_bcd_indef jmp bcd_store_done // no, so exit at once ALIGN store_bcd_indef: // yes, store bcd_indef movl $0, dword_frac1+frac80(%ebp) // clear low frac movl $0x80000000, dword_frac1+6(%ebp)// set only ms bit of hi frac movw $0x0ffff, 8+word_frac1 //set msw to all ones, jmp store_bcd_result // and give as answer ALIGN check_bcd_denorm: cmpb denormd,tag1(%ebp) // separate bcd cases jne round_to_int movl $0x0001,dword_expon1 // if masked d-error, make valid movb valid,tag1(%ebp) round_to_int: mov $0x403e,%eax cmp %eax,dword_expon1 // if expon >= 63, then number jge invalid_bcd // is already too big for bcd mov $offset_operand1,%edi // gradual uflow until expon=63 push %edi call gradual_underflow pop %edi // round to precision 64 movb prec64,%dl movb false,%al call round detect_zero: xor %eax,%eax mov $dword_frac1+4,%edi // if fraction = 0, result = 0 call test_4w jnz below_10_to_18_ mov %eax,dword_expon1 // set result to true zero movb special,tag1(%ebp) jmp store_bcd_round_data ALIGN below_10_to_18_: mov 4(%ebp,%edi),%edx cmp $0x0de0b6b3,%edx ja invalid_bcd mov (%ebp,%edi),%eax jb divide_by_10_to_9 cmp $0x0a7640000,%eax jae invalid_bcd divide_by_10_to_9: movl $0,4(%ebp,%edi) // clear high dword of frac1 movl $0,(%ebp,%edi)// clear low dword of 8 byte frac1 sub $2,%edi // make edi point to 10 byte frac1 mov $0x3b9aca00,%ebx // ten to the 9th, as hex ordinal div %ebx push %eax // save quotient mov $4,%ecx mov $100,%ebx FALLSTHRU next_pair_nibbles: mov %edx,%eax xor %edx,%edx div %ebx xchgl %edx,%eax aam second_half_loop_start: shlb $4,%ah orb %ah,%al movb %al,(%ebp,%edi) inc %edi LOOP(next_pair_nibbles) do_second_half_: pop %eax or %eax,%eax // is eax 0? movb %dl,(%ebp,%edi) jz store_bcd_round_data push %edx xor %edx,%edx mov $10,%ecx div %ecx xchgl %edx,%eax pop %ecx movb %al, %ah movb %cl, %al push $0 mov $5, %ecx jmp second_half_loop_start ALIGN store_bcd_round_data: cmpb true,rnd1_inexact jne store_signed_bcd orb $inexact_mask,%gs:sr_errors cmpb true,added_one jne store_signed_bcd orb $a_mask,%gs:sr_flags store_signed_bcd: movb sign1(%ebp),%ah // set sign in bcd number andb $0x080,%ah movb %ah,msb_frac1 store_bcd_result: les %gs:sr_mem_offset,%edi //move frac1 to memory // push %ds // save a?msr // push %ss // pop %ds lea word_frac1,%esi /* FAST_MOVSL */ movl %ss:0(%esi),%ecx movl %ecx,%es:0(%edi) movl %ss:4(%esi),%ecx movl %ecx,%es:4(%edi) movw %ss:8(%esi),%cx movw %cx,%es:8(%edi) // addl $10,%esi // addl $10,%edi // movl $0,%ecx // pop %ds // reload a?msr call pop_free bcd_store_done: pop %gs:sr_masks // restore old setting ret //bcd_store endp // // ***************************************************************************** // single_real_store: // ****************** // function: // implements store to single-precision real format // // inputs: // operand1 // // outputs: // single_precision real in memory; // stack popped if indicated. // // data accessed: // - mem_operand_pointer offset_operand1 // - sign1 tag1 // - expon1 word_frac // - msb_frac1 // // data changed: // // procedures called: // round store_valid // addition_normalized special_round_test // directed_round_test gradual_underflow // pop_free test_3w // u_masked? set_o_error // o_masked? set_p_error // set_u_error set_i_masked? // store_denormd // // ************************************************************************ ALIGN single_real_store: //proc push $pop_free // return to pop_free les mem_operand_pointer(%ebp),%edi //set es:di to memop mov low_extended_expon_for_single,%esi movb prec24,%dl // 24-bit precision movb tag1(%ebp),%al // load op1 tag cmpb valid,%al je single_valid // detect valid, infinity, cmpb denormd,%al // denormd, invalid, and je single_denormd // special cases cmpb inv,%al // check whether op1 is nan jne single_special // branch unless op1 is nan testb $0x40,msb_frac1 // check whether nan is quiet jnz single_special // branch if nan is quiet orb invalid_mask,%gs:sr_errors // set i_error for snan testb invalid_mask,%gs:sr_masks // if unmasked, just exit jz special_return // else, change to qnan orb $0x40,msb_frac1 single_special: mov dword_frac1+frac32+1(%ebp),%ecx and $0x807fffff,%ecx movzbl expon1(%ebp),%eax shl $23,%eax or %ecx,%eax mov %eax,%es:(%edi) //.. //.. pushad //.. push es //.. push edi //.. push eax //.. call fpsulong //.. add esp, 12 //.. popad //.. cld //.. special_return: ret ALIGN single_denormd: mov $offset_operand1,%edi // op1 is denormal or pseudo-denormal call norm_denorm // dont set d_error; just normalize single_valid: mov high_extended_expon_for_single,%edi // load parameter call store_valid les mem_operand_pointer(%ebp),%edi // es:edi --> memop jz single_infinity // zf = 1 => store infinity js single_max // sf = 1 => store max jc single_qnan // cf = 1 => store qnan single_store: mov dword_frac1+frac32+1(%ebp),%eax and $0x80ffffff,%eax test $0x00ffffff,%eax jz single_store_it and $0x807fffff,%eax movzbl expon1(%ebp),%ecx addb $0x80,%cl shl $23,%ecx or %ecx,%eax single_store_it: mov %eax,%es:(%edi) //.. //.. pushad //.. push es //.. push edi //.. push eax //.. call fpsulong //.. add esp,12 //.. popad //.. cld //.. ret //do needed pop or free ALIGN single_max: mov $0x7fffff7f,%eax jmp single_sign_on ALIGN single_infinity: mov $0x8000007f,%eax single_sign_on: orb sign1(%ebp),%al ror $8,%eax jmp single_store_it ALIGN single_qnan: movl $0xffffffff,%es:(%edi) pop %eax // skip pop or free ret // since this happens on error ALIGN store_valid: push %edi // stack high_expon push %esi // stack low_expon push %edx // stack prec control movb false,%al // not second rounding mov $offset_operand1,%edi // round to prec (dl) // push edi ; round preserves edi call round // pop edi call addition_normalize // and renormalize pop %edx // unstack prec control pop %esi // unstack low_expon pop %edi // unstack high_expon cmp %esi,dword_expon1 // is underflow possible? jl store_underflow_ // < low_expon, so underflow possible je decrement_exponent // no, = low_expon? cmp %edi,dword_expon1 // no, > high_expon? jle do_store_valid // no, store number orb overflow_mask,%gs:sr_errors // set o_error testb overflow_mask,%gs:sr_masks // if unmasked, violate ieee standard jnz masked_overflow // and abort without rounding source unmasked_ov_underflow: // // the commentized instructions immediately following are appropriate for // unmasked over/underflow response in accord with the ieee standard. on the // 80387, unmasked over/underflows on conversion leave for the trap handler the // source operand, unmodified by rounding, exponent rebiasing, or anything else. // therefore, to report that preliminary rounding was inexact or achieved by // increasing the source seems inconsistent with the 80387s philosophy // of entering an over/underflow trap handler with the 80387s state changed // only insofar as the over/underflow flag has been set, so skip that report. // // cmp rnd1_inexact, true ; detect inexact result // jne move_op1_to_87_tos ; if exact, branch to replace source // or %gs:sr_errors, inexact_mask ; else, set i_error // cmp added_one, true ; was rounding done by adding one? // jne move_op1_to_87_tos ; if not, branch to replace source // or %gs:sr_flags, a_mask ; else, set a_bit //move_op1_to_87_tos: // mov (ebp).result_location, stack_top // pop %edi ; discard callers return address // pop %edi ; discard pop_free address // jmp put_op1_result // // Instead, we return a special error condition (sf=0 zf=0 cf=1) // to our caller, to cause a quiet NaN to be generated, as the 80387 does. movb $1, %ah sahf ret ALIGN masked_overflow: orb $inexact_mask,%gs:sr_errors // set inexact_error movb %gs:sr_controls,%al // load control byte andb $rnd_control_mask,%al // mask in rounding control movb rnd_up,%ah cmpb %al,%ah js store_valid_done // branch if zf = 0 & sf = 1 movb sign1(%ebp),%al // get sign of op1 call special_round_test // after round test, cf=0 pushf // (zf=0 sf=1)/(zf=1 sf=0) js pop_store_valid_done // sf = 1 => store max orb $a_mask,%gs:sr_flags // set a_bit pop_store_valid_done: popf // reload flags store_valid_done: ret // exit ALIGN store_underflow_: testb underflow_mask,%gs:sr_masks // if underflow masked, jnz check_masked_underflow // then branch to check for inexact orb underflow_mask,%gs:sr_errors// else, set u_error // // after the underflow exception has been set, the response to unmasked // underflow ought to be the same as that to unmasked overflow. jmp unmasked_ov_underflow ALIGN check_masked_underflow: mov $offset_operand1,%edi // load op1 offset mov %esi,%eax // load low exponent push %edi // save op1 offset push %edx // save prec control call gradual_underflow // do gradual underflow pop %edx // reload prec control pop %edi // reload op1 offset movb true,%al // perform second round call round cmpw $0,rnd_history // signal_u_error? je decrement_exponent orb underflow_mask+inexact_mask,%gs:sr_errors decrement_exponent: testb $0x80,msb_frac1 // test msb of fraction jnz do_store_valid // dont decrement if 800..0h decw expon1(%ebp) // else, decrement expon do_store_valid: cmpw $0,rnd_history // signal_p_error? je adjust_flags orb $inexact_mask,%gs:sr_errors // signal_p_error. cmpb true,added_one // was rounding done by adding one? jne adjust_flags // if not, branch to adjust flags orb $a_mask,%gs:sr_flags // else, set a_bit adjust_flags: xor %eax,%eax // cf = 0, sf = 0, zf = 0 for inc %eax // store valid exit ret //single_real_store endp // // ************************************************************************ // double_real_store: // ****************** // function: // implements store to double-precision real format // // inputs: // operand1 // // outputs: // double precision real in memory; // stack popped if indicated. // // data accessed: // - mem_operand_pointer offset_operand1 // - sign1 tag1 // - expon1 word_frac1 // - msb_frac1 offset_operand1 // // data changed: // - sign1 word_frac1 // // procedures called: // test_3w store_valid // right_shift_frac1_cl pop_free // double_zero double_fill // store_denormd double_frac_mem // // *************************************************************************** ALIGN double_real_store: //proc push $pop_free // return to pop_free mov low_extended_expon_for_double,%esi movb prec53,%dl // 53-bit precision movb tag1(%ebp),%al // separate special cases cmpb valid,%al je double_valid cmpb denormd,%al je double_denormd cmpb special,%al jne inv_or_inf movw $0x3c00,expon1(%ebp) jmp double_frac_mem ALIGN inv_or_inf: cmpb inv,%al jne double_special testb $0x40,msb_frac1 // check whether nan is quiet jnz double_special // branch if nan is quiet orb invalid_mask,%gs:sr_errors // set i_error for snan testb invalid_mask,%gs:sr_masks // if unmasked, just exit jnz make_dbl_qnan // else, change to qnan dbl_special_return: ret ALIGN make_dbl_qnan: orb $0x40,msb_frac1 double_special: movw $0x3c00+0x07ff,expon1(%ebp) jmp double_frac_mem // store frac to memory ALIGN double_denormd: mov $offset_operand1,%edi // op1 is denormal or pseudo-denormal call norm_denorm // dont set d_error; just normalize double_valid: mov high_extended_expon_for_double,%edi call store_valid jz double_infinity // zf = 1 ==> store infinity js double_max // sf = 1 ==> store max jc double_qnan // cf = 1 ==> store qnan double_store: movb 3+lsb_frac1,%al // else store double cbtw mov $dword_frac1+6,%edi call test_3w jz double_zero // store signed zero double_frac_mem: movb $3,%cl // start by shifting call right_shift_frac1_cl // fraction right 3 bits les mem_operand_pointer(%ebp),%edi // es:edi points to memop // push %ds // save a?msr // push %ss // pop %ds // set up source pointer lea 3+word_frac1,%esi // move frac to memory /* FAST_MOVSL */ movl %ss:0(%esi),%ecx movl %ecx,%es:0(%edi) movw %ss:4(%esi),%ecx movw %ecx,%es:4(%edi) // addl $6,%esi // addl $6,%edi // movl $0,%ecx // pop %ds // reload a?msr movw expon1(%ebp),%ax // fetch high-order word, subw $0x3c00,%ax // with expon, sign, and shlw $4,%ax // top 4 bits of fraction andb $0x0f,msb_frac1 orb msb_frac1,%al andb $0x80,sign1(%ebp) orb sign1(%ebp),%ah movw %ax,%es:6(%edi) // es:di points to expon //.. //.. pushad //.. push es //.. push edi //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld //.. ret // do pop or free ALIGN double_zero: xor %eax,%eax // store +/- 0 to memory double_fill: les mem_operand_pointer(%ebp),%edi // es:edi points to memop mov %eax,%es:(%edi) //.. //.. pushad //.. push es //.. push edi //.. push eax //.. call fpsulong //.. add esp,12 //.. movw %ax,%es:4(%edi) //.. //.. push es //.. push edi+4 //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld //.. movb sign1(%ebp),%ah andb $0x80,%ah double_expon: movw %ax,%es:6(%edi) // store the exponent //.. //.. pushad //.. push es //.. push edi+12 //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld //.. ret ALIGN double_max: mov $0x0ffffffff,%eax // set fraction to ff..f call double_fill movw $0x7fef,%ax // set exponent to 7feh orb sign1(%ebp),%ah // or sign bit jmp double_expon ALIGN double_infinity: call double_zero // first clear the memop orw $0x7ff0,%es:6(%edi) // es:di -> memop //.. //.. pushad //.. push es //.. push edi+6 //.. call fpfushort //.. or ax,7ff0h //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld //.. ret ALIGN double_qnan: mov $0xffffffff,%eax // set fraction to ff..f call double_fill movw $0xffff,%es:6(%edi) // es:di -> memop (set exp to ff..f) pop %eax // skip pop or free ret // since this happens on error //double_real_store endp // // *********************************************************************** // fix16: // // function: // fixes valid number to a 16-bit integer. // // inputs: // operand1 // // outputs: // 16-bit integer in word_frac1 + 8; // overflow indication in zf (zf:1 => no overflow) // // data accessed: // - offset_operand1 sign1 // - expon1 word_frac1 // - offset_operand1 // // data changed: // - word_frac1 extra_word_reg // // procedures called: // sticky_right_shift round // careful_round p_error? // // *************************************************************************** ALIGN fix16: //proc mov high_int16_exponent,%ecx // calc shift amount sub dword_expon1,%ecx // if expon1 > high expon js no_fix16_ovf // then overflow (zf=0) cmp max_int16_shift,%ecx // dont let shift amount jbe do_shift_16 // exceed max_int16_shift mov max_int16_shift,%ecx do_shift_16: mov $offset_operand1,%edi // shift frac1 by cl xorb %al,%al call sticky_right_shift mov $offset_operand1,%edi // round to 16-bit prec movb prec16,%dl movb false,%al call round cmpb false,%al // overflow if al=true jnz no_fix16_ovf // round cy out (zf=1) cmpw $0x8000,8+word_frac1 jb check_sign_16 // no overflow if < 8000h ja no_fix16_ovf // else, overflow (zf=0) cmpb negative,sign1(%ebp) // oflow if = 8000h and jnz no_fix16_ovf // sign1 = pos (zf=0) check_sign_16: movb positive,%al // al is overflow flag cmpb sign1(%ebp),%al // negate integer if jz no_fix16_ovf // sign is neg (zf=1) negw 8+word_frac1 xorb %al,%al // no overflow (zf=1) no_fix16_ovf: ret //fix16 endp // // *********************************************************************** // int16_store: // // function: // stores into 16-bit integer format // // inputs: // operand1 // // outputs: // 16-bit integer in memory operand location // // data accessed: // - mem_operand_pointer tag1 // - word_frac1 msb_frac1 // - offset_operand1 extra_word_reg // // data changed: // // procedures called: // fix16 pop_free // invalid_or_special get_rnd_control // set_i_error i_masked? // set_p_error clear_p_error // // ************************************************************************ ALIGN int16_store: //proc // cmpb valid,tag1(%ebp) je valid_16 cmpb denormd,tag1(%ebp) jne special_16 valid_16: call fix16 // make op1 a 16-bit int jnz special_16 // if zf=0, oflow on fix cmpw $0,rnd_history je store_16 orb $inexact_mask,%gs:sr_errors cmpb true,added_one jne store_16 orb $a_mask,%gs:sr_flags store_16: movw 8+word_frac1,%ax // move integer to memory pointer_16: les mem_operand_pointer(%ebp),%edi //set es:di to location finish_16: movw %ax,%es:(%edi) // store integer to mem //.. //.. pushad //.. push es //.. push edi //.. push ax //.. call fpsushort //.. add esp,12 //.. popad //.. cld //.. jmp pop_free // pop stack and go home ALIGN special_16: xorw %ax,%ax cmpb special,tag1(%ebp) // is operand tagged special? je pointer_16 // yes, load memop ptr and exit orb invalid_mask,%gs:sr_errors// no, set invalid error movw $0x8000,%ax // load inv constant into ax testb invalid_mask,%gs:sr_masks// is invalid error masked? jnz pointer_16 // yes, store invalid constant ret //int16_store endp // // *********************************************************************** // fix32: // // function: // fixes valid number to a 32-bit integer. // // inputs: // operand1 // // outputs: // 32-bit integer in word_frac1 + 6; // overflow indication in zf (zf:1 => no overflow) // // data accessed: // - offset_operand1 sign1 // - dword_expon1 word_frac1 // - offset_operand1 // // data changed: // - word_frac1 // // procedures called: // sticky_right_shift round // // *************************************************************************** ALIGN fix32: //proc mov high_int32_exponent,%ecx // calc shift amount sub dword_expon1,%ecx // if expon1 > high expon js no_fix32_ovf // then overflow (zf=0) cmp max_int32_shift,%ecx // dont let shift amount jbe do_shift_32 // exceed max_int32_shift mov max_int32_shift,%ecx do_shift_32: mov $offset_operand1,%edi // shift frac1 by cl xorb %al,%al call sticky_right_shift mov $offset_operand1,%edi // round to 16-bit prec movb prec32,%dl movb false,%al call round cmpb false,%al // overflow if al=true jnz no_fix32_ovf // round cy out (zf=1) cmpl $0x080000000,dword_frac1+frac32(%ebp) jb check_sign_32 // no overflow if < 80000000h ja no_fix32_ovf // else, overflow (zf=0) cmpb negative,sign1(%ebp) // oflow if = 80000000h and jnz no_fix32_ovf // sign1 = pos (zf=0) check_sign_32: movb positive,%al // al is overflow flag cmpb sign1(%ebp),%al // negate integer if jz no_fix32_ovf // sign is neg (zf=1) negl dword_frac1+frac32(%ebp) xorb %al,%al // no overflow (zf=1) no_fix32_ovf: ret //fix32 endp // // ************************************************************************** // int32_store: // // function: // stores into 32-bit integer format // // input: // operand1 // // output: // 32-bit integer in location pointed to by es:di. // // data accessed: // - mem_operand_pointer offset_operand1 // - sign1 tag1 // - expon1 word_frac1 // - msb_frac1 offset_operand1 // // data changed: // - word_frac1 // // procedures called: // pop_free // fix32 // // ************************************************************************** ALIGN int32_store: //proc cmpb valid,tag1(%ebp) je valid_32 cmpb denormd,tag1(%ebp) jne special_32 valid_32: call fix32 // make op1 a 32-bit int jnz special_32 // if zf=0, oflow on fix cmpw $0,rnd_history je store_32 orb $inexact_mask,%gs:sr_errors cmpb true,added_one jne store_32 orb $a_mask,%gs:sr_flags store_32: mov dword_frac1+frac32(%ebp),%eax // move integer to eax pointer_32: les mem_operand_pointer(%ebp),%edi //set es:di to location finish_32: mov %eax,%es:(%edi) // store integer to mem //.. //.. pushad //.. push es //.. push edi //.. push eax //.. call fpsulong //.. add esp,12 //.. popad //.. cld //.. jmp pop_free // pop stack and go home ALIGN special_32: xor %eax,%eax cmpb special,tag1(%ebp) // is operand tagged special? je pointer_32 // yes, load memop ptr and exit orb invalid_mask,%gs:sr_errors// no, set invalid error mov $0x080000000,%eax // load inv constant into ax testb invalid_mask,%gs:sr_masks// is invalid error masked? jnz pointer_32 // yes, store invalid constant ret //int32_store endp // // *********************************************************************** // fix64: // // function: // fixes valid number to a 64-bit integer. // // inputs: // operand1 // // outputs: // 64-bit integer in word_frac1 + 2; // overflow indication in zf (zf:1 => no overflow) // // data accessed: // - offset_operand1 sign1 // - dword_expon1 word_frac1 // - offset_operand1 // // data changed: // - word_frac1 // // procedures called: // sticky_right_shift round // // *************************************************************************** ALIGN fix64: //proc mov high_int64_exponent,%ecx // calc shift amount sub dword_expon1,%ecx // if expon1 > high expon js no_fix64_ovf // then overflow (zf=0) cmp max_int64_shift,%ecx // dont let shift amount jbe do_shift_64 // exceed max_int64_shift mov max_int64_shift,%ecx do_shift_64: mov $offset_operand1,%edi // shift frac1 by cl xorb %al,%al call sticky_right_shift mov $offset_operand1,%edi // round to 64-bit prec movb prec64,%dl movb false,%al call round cmpb false,%al // overflow if al=true jnz no_fix64_ovf // round cy out (zf=1) cmpl $0x080000000,dword_frac1+frac32(%ebp) jb check_sign_64 // no overflow if < 80000000h ja no_fix64_ovf // else, overflow (zf=0) cmp $0,dword_frac1+frac64(%ebp) jnz no_fix64_ovf cmpb negative,sign1(%ebp) // oflow if = 800..0h and jnz no_fix64_ovf // sign1 = pos (zf=0) check_sign_64: movb positive,%al // al is overflow flag cmpb sign1(%ebp),%al // negate integer if jz no_fix64_ovf // sign is neg (zf=1) xor %eax,%eax negl dword_frac1+frac64(%ebp) sbb dword_frac1+frac32(%ebp),%eax mov %eax,dword_frac1+frac32(%ebp) xorb %al,%al // no overflow (zf=1) no_fix64_ovf: ret //fix64 endp // // ***************************************************************************** // int64_store: // ************ // function: // stores into 64-bit integer format // // input: // operand1 // // output: // 64-bit integer in memory location pointed to by es:edi. // // data accessed: // - mem_operand_pointer offset_operand1 // - sign1 tag1 // - expon1 word_frac1 // - msb_frac1 offset_operand1 // // data changed: // - word_frac1 // // procedures called: // pop_free // // *************************************************************************** ALIGN int64_store: //proc cmpb valid,tag1(%ebp) je valid_64 cmpb denormd,tag1(%ebp) jne special_64 valid_64: call fix64 // make op1 a 64-bit int jnz special_64 // if zf=0, oflow on fix cmpw $0,rnd_history je store_64 orb $inexact_mask,%gs:sr_errors cmpb true,added_one jne store_64 orb $a_mask,%gs:sr_flags store_64: mov dword_frac1+frac64(%ebp),%eax // move integer to edx:eax mov dword_frac1+frac32(%ebp),%edx // move integer to edx:eax pointer_64: les mem_operand_pointer(%ebp),%edi //set es:edi to location finish_64: mov %eax,%es:(%edi) // store low integer to low mem //.. //.. pushad //.. push es //.. push edi //.. push eax //.. call fpsulong //.. add esp,12 //.. popad //.. cld //.. mov %edx,%es:4(%edi) // store high integer to high mem //.. //.. pushad //.. push es //.. push edi //.. push edx //.. call fpsulong //.. add esp,12 //.. popad //.. cld //.. jmp pop_free // pop stack and go home ALIGN special_64: xor %eax,%eax cltd cmpb special,tag1(%ebp) // is operand tagged special? je pointer_64 // yes, load memop ptr and exit orb invalid_mask,%gs:sr_errors// no, set invalid error mov $0x080000000,%edx // load inv constant into ax testb invalid_mask,%gs:sr_masks// is invalid error masked? jnz pointer_64 // yes, store invalid constant ret //int64_store endp // //a_med ends // // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.