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

unix.superglobalmegacorp.com

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