Annotation of coherent/b/lib/libc/crt/i387/rts87.s, revision 1.1.1.1

1.1       root        1: //////////
                      2: / rts87.s
                      3: / cc386 80x87 runtime support.
                      4: //////////
                      5: 
                      6:        .text
                      7: 
                      8:        .globl  _fwait
                      9:        .globl  _cfcc
                     10:        .globl  _tstcc
                     11:        .globl  _tstccp
                     12:        .globl  _dp87
                     13:        .globl  _fdcvt
                     14:        .globl  _vdcvt
                     15:        .globl  _ldcvt
                     16:        .globl  _pdcvt
                     17:        .globl  _udcvt
                     18:        .globl  _idcvt
                     19:        .globl  _dfcvt
                     20:        .globl  _dvcvt
                     21:        .globl  _dlcvt
                     22:        .globl  _ducvt
                     23:        .globl  _dicvt
                     24:        .globl  _dpcvt
                     25:        .globl  ldexp
                     26:        .globl  frexp
                     27:        .globl  modf
                     28: 
                     29: / The following should be unnecessary but...
                     30:        .globl  _fvcvt
                     31:        .globl  _flcvt
                     32:        .globl  _fucvt
                     33:        .globl  _ficvt
                     34: 
                     35: cwchop .word   0x0F3F                  / chop control word
                     36: two    .word   2                       / constant 2
                     37: 
                     38: RASIZE =       4                       / size of a return address
                     39: EBPSIZE        =       4                       / size of saved %ebp
                     40: 
                     41: //////////
                     42: / _fwait       Force NDP synchronization.
                     43: /
                     44: / This is here in case the user wants to explicitly force an fwait.
                     45: //////////
                     46: 
                     47: _fwait:
                     48:        fwait
                     49:        ret
                     50: 
                     51: //////////
                     52: / _tstcc()     Test %st and copy NDP condition codes.
                     53: / _tstccp()    Test %st and pop and copy NDP condition codes.
                     54: / _cfcc()      Copy NDP condition codes.
                     55: /
                     56: / _tstcc() tests %st against 0 and then does a _cfcc().
                     57: / _tstccp() tests %st against 0, pops it, and then does a _cfcc.
                     58: / _cfcc() copies the C0 and C3 status flags from the NDP
                     59: / into the Cf and Zf flags of the 80x86.
                     60: / This uses the otherwise useless opcode that copies the flags
                     61: / from %ah in 8080 format.
                     62: /
                     63: / Input:
                     64: /      %st for _tstcc() and _tstccp(), NDP status word for _cfcc().
                     65: / Output:
                     66: /      80x86 flags Cf and Zf.
                     67: /      NDP stack popped for _tstccp().
                     68: //////////
                     69: 
                     70: _tstcc:
                     71:        ftst                            / Test %st against 0
                     72:        jmp     _cfcc                   / and set the condition codes.
                     73: _tstccp:
                     74:        ftst                            / Test st against 0,
                     75:        fstp    %st                     / pop the 80x87 stack,
                     76:                                        / and fall through...
                     77: _cfcc:
                     78:        fstsw   %ax                     / Store the 80x87 status word to %eax
                     79:        fwait                           / and wait for it to finish up.
                     80:        sahf                            / Load Cf and Zf correctly.
                     81:        ret
                     82: 
                     83: //////////
                     84: / _dp87()      Double push from NDP stacktop to 80x86 stack.
                     85: /
                     86: / Push a double from the NDP stacktop %st to the system stack.
                     87: / There is some magic to keep the return address in one piece.
                     88: /
                     89: / Input:
                     90: /      Double in %st.
                     91: / Outputs:
                     92: /      NDP stack popped.
                     93: /      Double on 80x86 stack.
                     94: //////////
                     95: 
                     96: _dp87:
                     97:        pop     %eax                    / Return address to %eax.
                     98:        subl    %esp, $8                / Claim a double on stack and
                     99:        fstpl   (%esp)                  / pop 80x87 to memory.
                    100:        fwait                           / Make sure pop is completed.
                    101:        ijmp    %eax                    / Return to the caller.
                    102: 
                    103: //////////
                    104: / _dicvt()     Convert integer to double.
                    105: / _ducvt()     Convert unsigned integer to double.
                    106: / _dpcvt()     Convert pointer to double.
                    107: / _dlcvt()     Convert long integer to double.
                    108: / _dvcvt()     Convert unsigned long integer to double.
                    109: / _dfcvt()     Convert float to double.
                    110: /
                    111: / Widen to double.
                    112: / Some simple widens can be compiled inline,
                    113: / but the unsigned widens and the signed
                    114: / widens when the object lacks an lvalue cannot be.
                    115: /
                    116: / Input:
                    117: /      Operand passed in standard C fashion on 80x86 stack.
                    118: / Output:
                    119: /      Result in %st.
                    120: //////////
                    121: 
                    122: IARG   =       RASIZE
                    123: 
                    124: _dicvt:
                    125: _ficvt:
                    126: _dlcvt:
                    127: _flcvt:
                    128:        fildl   IARG(%esp)              / Load and convert the integer.
                    129:        ret
                    130: 
                    131: UARG   =       RASIZE+EBPSIZE
                    132: INT64  =       -8                      / Auto int64 offset.
                    133: 
                    134: _ducvt:
                    135: _dpcvt:
                    136: _fucvt:
                    137: _dvcvt:
                    138: _fvcvt:
                    139:        push    %ebp
                    140:        movl    %ebp, %esp
                    141:        subl    %esp, $8                / Claim a 64 bit integer.
                    142: 
                    143:        movl    %eax, UARG(%ebp)        / Grab unsigned integer
                    144:        movl    INT64(%ebp), %eax       / and store in 64 bit integer low half.
                    145:        movl    INT64+4(%ebp), $0       / Zero-extend to high half.
                    146:        fildll  INT64(%ebp)             / Load and convert to double.
                    147: 
                    148:        movl    %esp, %ebp
                    149:        pop     %ebp
                    150:        ret
                    151: 
                    152: DARG   =       RASIZE+EBPSIZE
                    153: FLOAT  =       -4                      / Auto float offset.
                    154: 
                    155: _dfcvt:
                    156:        push    %ebp
                    157:        movl    %ebp, %esp
                    158:        push    %eax                    / Claim a float.
                    159: 
                    160:        fldl    DARG(%ebp)              / Grab double and
                    161:        fstps   FLOAT(%ebp)             / round to a float.
                    162:        flds    FLOAT(%ebp)             / Load result.
                    163: 
                    164:        movl    %esp, %ebp
                    165:        pop     %ebp
                    166:        ret
                    167: 
                    168: //////////
                    169: / _idcvt()     Convert double to integer.
                    170: / _udcvt()     Convert double to unsigned integer.
                    171: / _pdcvt()     Convert double to pointer.
                    172: / _ldcvt()     Convert double to long integer.
                    173: / _vdcvt()     Convert double to unsigned long integer.
                    174: / _fdcvt()     Convert double to float.
                    175: /
                    176: / Shrinks from double.
                    177: / The task is a little harder than would be expected.
                    178: / Shift the 80x87 into chop mode for integer conversions
                    179: / so that conversions work the right way.
                    180: /
                    181: / Input:
                    182: /      Double argument on the 80x86 stack.
                    183: / Output:
                    184: /      Result in %eax for [iulv]dcvt(), %st for _fdcvt().
                    185: //////////
                    186: 
                    187: SAVECW =       -6                      / Auto saved control word offset.
                    188: INT    =       -4                      / Auto int32 offset.
                    189: 
                    190: _idcvt:
                    191: _ldcvt:
                    192:        push    %ebp
                    193:        movl    %ebp, %esp
                    194:        subl    %esp, $6                / Claim a word and a dword.
                    195: 
                    196:        fstcw   SAVECW(%ebp)            / Save old control word.
                    197:        fldcw   cwchop                  / Load chopping control word.
                    198:        fldl    DARG(%ebp)              / Load up double and
                    199:        fistpl  INT(%ebp)               / convert to integer and
                    200:        fldcw   SAVECW(%ebp)            / put control word back.
                    201:        movl    %eax, INT(%ebp)         / Result to %eax.
                    202: 
                    203:        movl    %esp, %ebp
                    204:        pop     %ebp
                    205:        ret
                    206: 
                    207: SAVECW =       -10                     / Auto saved control word offset.
                    208: INT64  =       -8                      / Auto int64 offset.
                    209: 
                    210: _pdcvt:
                    211: _udcvt:
                    212: _vdcvt:
                    213:        push    %ebp
                    214:        movl    %ebp, %esp
                    215:        subl    %esp, $10               / Claim a word and a 64-bit int.
                    216: 
                    217:        fstcw   SAVECW(%ebp)            / Save old control word.
                    218:        fldcw   cwchop                  / Load chopping control word.
                    219:        fldl    DARG(%ebp)              / Load up double and
                    220:        fistpll INT64(%ebp)             / convert to integer and
                    221:        fldcw   SAVECW(%ebp)            / put control word back.
                    222:        movl    %eax, INT64(%ebp)       / Unsigned long result to %eax.
                    223:        cmpl    INT64+4(%ebp), $0       / If hi result dword is zero,
                    224:        je      ?0                      / return lo result dword.
                    225:        movl    %eax, $-1               / Overflow, return UINTMAX.
                    226: 
                    227: ?0:
                    228:        movl    %esp, %ebp
                    229:        pop     %ebp
                    230:        ret
                    231: 
                    232: FLOAT  =       -4                      / Auto float offset.
                    233: 
                    234: _fdcvt:
                    235:        push    %ebp
                    236:        movl    %ebp, %esp
                    237:        push    %eax                    / Claim a float.
                    238: 
                    239:        fldl    DARG(%ebp)              / Load the double and
                    240:        fstps   FLOAT(%ebp)             / convert it to a float.
                    241:        flds    FLOAT(%ebp)             / Load the float.
                    242: 
                    243:        movl    %esp, %ebp
                    244:        pop     %ebp
                    245:        ret
                    246: 
                    247: //////////
                    248: / double
                    249: / ldexp(fraction, exponent) double fraction; int exponent;
                    250: /
                    251: / Assemble a double precision floating point number
                    252: / from the given fraction and integer exponent.
                    253: //////////
                    254: 
                    255: FRAC   =       RASIZE+EBPSIZE
                    256: EXP    =       FRAC+8
                    257: 
                    258: ldexp:
                    259:        push    %ebp
                    260:        movl    %ebp, %esp
                    261: 
                    262:        fildl   EXP(%ebp)               / Grab exponent
                    263:        fldl    FRAC(%ebp)              / and fraction.
                    264:        fscale                          / Put it all together
                    265:        fstp    %st(1)                  / and pop stack.
                    266: 
                    267:        pop     %ebp
                    268:        ret
                    269: 
                    270: //////////
                    271: / double
                    272: / frexp(value, expp) double value; int *expp;
                    273: /
                    274: / Split a double float into its fraction and its exponent.
                    275: / The "fxtract" instruction almost does the job.
                    276: / The IEEE standard says that the significand is not from 0.5 to 1
                    277: / but from 1 to 2.
                    278: / The extracted significand and exponent must be adjusted if nonzero.
                    279: //////////
                    280: 
                    281: VALUE  =       RASIZE+EBPSIZE
                    282: EXPP   =       VALUE+8
                    283: 
                    284: frexp:
                    285:        push    %ebp
                    286:        movl    %ebp, %esp
                    287: 
                    288:        fldl    VALUE(%ebp)             / Load the value.
                    289:        fxtract                         / Significand to %st, unbiased exp to %st1.
                    290:        call    _tstcc                  / Check if the significand is zero.
                    291:        je      frexp0                  / Jump if it is.
                    292:        filds   two                     / %st=2.0, %st1=sig, %st2=exp.
                    293:        fdivrp  %st(1), %st             / %st=sig/2.0, %st1=exp.
                    294:        fld1                            / %st=1.0, %st1=sig/2.0, %st2=exp.
                    295:        faddp   %st(2), %st             / %st=sig/2.0, %st1=exp+1.0.
                    296: 
                    297: frexp0:                                        / Significand in %st, exponent in %st1.
                    298:        fxch                            / Exponent to %st, significand to %st1.
                    299:        movl    %eax, EXPP(%ebp)        / Save the exponent
                    300:        fistpl  (%eax)                  / through the supplied pointer and pop.
                    301:        fwait                           / Make sure it is good.
                    302: 
                    303:        pop     %ebp
                    304:        ret
                    305: 
                    306: //////////
                    307: / double
                    308: / modf(value, intpart) double value; double *intpart;
                    309: /
                    310: / Split a double (another way!).
                    311: //////////
                    312: 
                    313: VALUE  =       RASIZE+EBPSIZE
                    314: INTPART        =       VALUE+8
                    315: SAVECW =       -2                      / Auto saved control word offset.
                    316: 
                    317: modf:
                    318:        push    %ebp
                    319:        movl    %ebp, %esp
                    320:        push    %eax                    / Claim one dword (only 2 bytes used).
                    321: 
                    322:        fstcw   SAVECW(%ebp)            / Save the old control word and
                    323:        fldcw   cwchop                  / load chopping control word.
                    324:        fldl    VALUE(%ebp)             / Pick up argument.
                    325:        fld     %st                     / %st=arg, %st1=arg.
                    326:        frndint                         / %st=intpart, %st1=arg.
                    327:        fsubr   %st(1), %st             / %st=intpart, %st1=fracpart.
                    328:        movl    %eax, INTPART(%ebp)     / Load integer pointer.
                    329:        fstpl   (%eax)                  / Store intpart through it and pop.
                    330:        fldcw   SAVECW(%ebp)            / Put old control word back.
                    331: 
                    332:        movl    %esp, %ebp
                    333:        pop     %ebp
                    334:        ret
                    335: 
                    336: / end of rts87.s
                    337: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.