Annotation of coherent/b/kernel/i386/rts87.s, revision 1.1.1.1

1.1       root        1: //////////
                      2: / rts87.s
                      3: / cc386 80x87 runtime support.
                      4: / N.B. Converted 6/29/92 by steve from 8087 .a86 source, not tested!
                      5: / Conversion is incomplete!
                      6: / Operand lengths should be explicit for each opcode!
                      7: //////////
                      8: 
                      9:        .text
                     10: 
                     11:        .globl  _cfcc
                     12:        .globl  _tstcc
                     13:        .globl  _tstccp
                     14:        .globl  _dp87
                     15:        .globl  _fdcvt
                     16:        .globl  _vdcvt
                     17:        .globl  _ldcvt
                     18:        .globl  _udcvt
                     19:        .globl  _idcvt
                     20:        .globl  _dfcvt
                     21:        .globl  _dvcvt
                     22:        .globl  _dlcvt
                     23:        .globl  _ducvt
                     24:        .globl  _dicvt
                     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: iw87   .word   0x0fbf                  / chop control word
                     36: cwdown .word   0x07ff                  / round down control word
                     37: two    .word   2                       / constant 2
                     38: 
                     39: //////////
                     40: / _tstcc()     Test and copy floating condition codes.
                     41: / _tstccp()    Test and pop and copy floating condition codes.
                     42: / _cfcc()      Copy floating condition codes.+
                     43: /
                     44: / _tstcc() tests the 80x87 stacktop against 0 and then does a _cfcc().
                     45: / _tstccp() tests the 80x87 stacktop against 0, pops, and then does a _cfcc.
                     46: / _cfcc() copies the C0 and C3 status flags from the  80x87
                     47: / into the C and Z flags of the 80x86.
                     48: / This uses the otherwise useless opcode that copies the flags
                     49: / from %AH in 8080 format.
                     50: /
                     51: / Input:
                     52: /      80x87 status word.
                     53: / Output:
                     54: /      80x86 flags.
                     55: //////////
                     56: 
                     57: _tstcc:
                     58:        ftst                            / test st against 0.
                     59:        jmp     _cfcc                   / and set the condition codes.
                     60: _tstccp:
                     61:        ftst                            / test st against 0,
                     62:        fstp    %st                     / pop the 80x87 stack
                     63:                                        / and fall through...
                     64: _cfcc:
                     65: / N.B. fstsw unimplemented in as386 of 7/1/92, so use fwait+fnstsw instead
                     66: /      fstsw   %ax                     / store the 80x87 status word to AX
                     67:        fwait
                     68:        fnstsw  %ax                     / store the 80x87 status word to AX
                     69:        fwait                           / and wait for it to finish up.
                     70:        sahf                            / load cf and zf correctly.
                     71:        ret                             / and return to caller.
                     72: 
                     73: //////////
                     74: / _dp87()      Double push from 80x87 stack.
                     75: /
                     76: / Move a double from the top of the 80x87 stack to the top of the system stack.
                     77: / There is some magic to keep the return address in one piece.
                     78: /
                     79: / Input:
                     80: /      Double to push in %st.
                     81: / Outputs:
                     82: /      NDP stack popped.
                     83: /      Double on 80x86 stack.
                     84: //////////
                     85: 
                     86: _dp87:
                     87:        pop     %eax                    / capture return address.
                     88:        subl    %esp, $8                / claim a double on stack and
                     89:        fstpl   (%esp)                  / pop 80x87 to memory.
                     90:        fwait                           / make sure pop is completed.
                     91:        ijmp    %eax                    / return to the caller.
                     92: 
                     93: //////////
                     94: / _dicvt()     Convert integer to double.
                     95: / _ducvt()     Convert unsigned integer 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: / These routines are called directly from compiled code for all
                    101: / widen conversions to double.
                    102: / Some of the simple widens can be
                    103: / compiled inline, but the unsigned widens and the signed
                    104: / widens when the object lacks an lvalue cannot be.
                    105: /
                    106: / Each routine is passed the source operand as any C
                    107: / argument would be passed.
                    108: / Each returns the result on the top of the 80x87 stack.
                    109: //////////
                    110: 
                    111: _dicvt:
                    112: _ficvt:
                    113:        fildl   4(%esp)                 / load up the integer.
                    114:        ret                             / return.
                    115: 
                    116: _ducvt:
                    117: _fucvt:
                    118:        push    %ebp                    / save
                    119:        movl    %ebp, %esp              / sequence
                    120:        push    %eax                    / claim a long int.
                    121: 
                    122:        mov     %eax, 4(%ebp)           / fetch the unsigned int and
                    123:        mov     -4(%ebp), %eax          / put in ls half.
                    124:        mov     -2(%ebp), $0            / zero extend.
                    125:        fild    -4(%ebp)                / load and convert to double.
                    126: 
                    127:        mov     %esp, %ebp              / back up stack.
                    128:        pop     %ebp                    / standard
                    129:        ret                             / return sequence.
                    130: 
                    131: _dlcvt:
                    132: _flcvt:
                    133:        fild    4(%esp)                 / load and convert the long.
                    134:        ret                             / sequence.
                    135: 
                    136: _dvcvt;
                    137: _fvcvt:
                    138:        push    %ebp                    / save
                    139:        mov     %ebp, %esp              / sequence
                    140:        sub     %esp, $8                / claim a 64 bit integer.
                    141: 
                    142:        mov     %eax, 4(%ebp)           / low half of long
                    143:        mov     -8(%ebp), %eax          / put in 64 bit integer.
                    144:        mov     %eax, 6(%ebp)           / high half of long.
                    145:        mov     -6(%ebp), %eax          / put in 64 bit integer.
                    146:        mov     -4(%ebp), $0            / zeros on the
                    147:        mov     -2(%ebp), $0            / end.
                    148:        fild    -8(%ebp)                / load and convert to double.
                    149: 
                    150:        mov     %esp, %ebp              / standard
                    151:        pop     %ebp                    / c
                    152:        ret                             / sequence.
                    153: 
                    154: _dfcvt:
                    155:        push    %ebp                    / save
                    156:        mov     %ebp, %esp              / sequence.
                    157:        push    %eax                    / claim a float.
                    158: 
                    159:        fld     4(%ebp) / grab double and
                    160:        fstp    -4(%ebp)                / round to a single float.
                    161:        fld     -4(%ebp)                / load result.
                    162: 
                    163:        mov     %esp, %ebp              / full.
                    164:        pop     %ebp                    / standard
                    165:        ret                             / sequence.
                    166: 
                    167: //////////
                    168: / _idcvt()     convert double to integer
                    169: / _udcvt()     convert double to unsigned integer
                    170: / _ldcvt()     convert double to long integer
                    171: / _vdcvt()     convert double to unsigned long integer
                    172: / _fdcvt()     convert double to float
                    173: /
                    174: / this set of routines handle all shrinks from double. the task
                    175: / is a little harder than would be expected. the 80x87 is always
                    176: / shifted into chop mode, so that conversions work the way that
                    177: / you expect them to work.
                    178: /
                    179: / all of these routines take a double argument in the  standard
                    180: / way, and return the result in the standard return location of
                    181: / objects of that type (%eax, dx%eax, tos).
                    182: //////////
                    183: 
                    184: _idcvt:
                    185:        push    %ebp                    / save
                    186:        mov     %ebp, %esp              / sequence.
                    187:        push    %eax                    / claim 2 words.
                    188: 
                    189: /      fstcw   -2(%ebp)                / save old control word
                    190:        fwait
                    191:        fnstcw  -2(%ebp)                / save old control word
                    192:        fldcw   iw87                    / load chopping control word
                    193:        fld     4(%ebp)                 / load up double and
                    194:        fistp   -4(%ebp)                / convert to integer and
                    195:        fldcw   -2(%ebp)                / put control word back.
                    196:        mov     %eax, -4(%ebp)          / ax=result.
                    197: 
                    198:        mov     %esp, %ebp              / standard
                    199:        pop     %ebp                    / c
                    200:        ret                             / sequence.
                    201: 
                    202: _udcvt:
                    203:        push    %ebp                    / save
                    204:        mov     %ebp, %esp              / sequence.
                    205:        sub     %esp, $6                / claim 3 words.
                    206: 
                    207: /      fstcw   -2(%ebp)                / save old control word
                    208:        fwait
                    209:        fnstcw  -2(%ebp)                / save old control word
                    210:        fldcw   iw87                    / load chopping control word
                    211:        fld     4(%ebp)                 / load up double and
                    212:        fistp   -6(%ebp)                / convert to 32 bit integer and
                    213:        fldcw   -2(%ebp)                / put control word back.
                    214:        mov     %eax, -6(%ebp)          / ax=ls half of result.
                    215: 
                    216:        mov     %esp, %ebp              / standard
                    217:        pop     %ebp                    / c
                    218:        ret                             / sequence.
                    219: 
                    220: _ldcvt:
                    221:        push    %ebp                    / save
                    222:        mov     %ebp, %esp              / sequence.
                    223:        sub     %esp, $6                / claim 3 words.
                    224: 
                    225: /      fstcw   -2(%ebp)                / save old control word
                    226:        fwait
                    227:        fnstcw  -2(%ebp)                / save old control word
                    228:        fldcw   iw87                    / load chopping control word
                    229:        fld     4(%ebp)                 / load up double and
                    230:        fistp   -6(%ebp)                / convert to long and
                    231:        fldcw   -2(%ebp)                / put control word back.
                    232:        mov     %eax, -6(%ebp)          / dxax=the 32 bit
                    233:        mov     %edx, -4(%ebp)          / result.
                    234: 
                    235:        mov     %esp, %ebp              / standard
                    236:        pop     %ebp                    / c
                    237:        ret                             / sequence.
                    238: 
                    239: _vdcvt:
                    240:        push    %ebp                    / save
                    241:        mov     %ebp, %esp              / sequence.
                    242:        sub     %esp, $10               / claim 5 words.
                    243: 
                    244: /      fstcw   -2(%ebp)                / save old control word
                    245:        fwait
                    246:        fnstcw  -2(%ebp)                / save old control word
                    247:        fldcw   iw87                    / load chopping control word
                    248:        fldcw   iw87                    / load chopping control word
                    249:        fld     4(%ebp)                 / load up double and
                    250:        fistp   -10(%ebp)               / convert to integer and
                    251:        fldcw   -2(%ebp)                / put control word back.
                    252:        mov     %eax, -10(%ebp)         / dxax=unsigned long
                    253:        mov     %edx, -8(%ebp)          / result.
                    254: 
                    255:        mov     %esp, %ebp              / standard
                    256:        pop     %ebp                    / c
                    257:        ret                             / sequence.
                    258: 
                    259: _fdcvt:
                    260:        push    %ebp                    / save
                    261:        mov     %ebp, %esp              / sequence.
                    262:        push    %eax                    / claim 2 words.
                    263: 
                    264:        fld     4(%ebp)                 / load the double and
                    265:        fstp    -4(%ebp)                / convert it to a float.
                    266:        fld     -4(%ebp)                / load the float up.
                    267: 
                    268:        mov     %esp, %ebp              / standard
                    269:        pop     %ebp                    / c
                    270:        ret                             / sequence.
                    271: 
                    272: //////////
                    273: / ldexp()      make a double.
                    274: /
                    275: / this routine assembles a double precision floating point number
                    276: / given a fraction and an integer exponent.
                    277: /
                    278: / calling sequence:
                    279: / double
                    280: / ldexp(fraction, exponent);
                    281: / double       fraction;
                    282: / int          exponent;
                    283: //////////
                    284: 
                    285: ldexp:
                    286:        push    %ebp                    / save
                    287:        mov     %ebp, %esp              / sequence.
                    288: 
                    289:        fild    12(%ebp)                / exponent
                    290:        fld     4(%ebp)                 / fraction
                    291:        fscale                          / put it all together
                    292:        fstp    %st(1)                  / and pop stack
                    293: 
                    294:        pop     %ebp                    / standard
                    295:        ret                             / return.
                    296: 
                    297: //////////
                    298: / frexp()      split a double.
                    299: /
                    300: / this routine splits a double float into its fraction and its
                    301: / exponent. the "fxtract" instruction almost does the job. the
                    302: / ieee standard says that the significand is not from 0.5 to 1
                    303: / but from 1 to 2. the extracted significand and exponent must
                    304: / be adjusted (if non zero).
                    305: /
                    306: / calling sequence:
                    307: / double
                    308: / frexp(value, expp);
                    309: / double       value;
                    310: / int          *expp;
                    311: //////////
                    312: 
                    313: frexp:
                    314:        push    %ebp                    / save
                    315:        mov     %ebp, %esp              / sequence
                    316: 
                    317:        fld     4(%ebp)                 / load up the value
                    318:        fxtract                         / split it
                    319:        call    _tstcc                  / check if the significand is zero.
                    320:        je      frexp0                  / jump if it is.
                    321:        fild    two                     / divide the significand
                    322:        fdivp   %st(1), %st             / by two and
                    323:        fld1                            / add 1 to the
                    324:        faddp   %st(2), %st             / exponent.
                    325: 
                    326: frexp0:        fxch                            / move exponent to %st
                    327:        mov     %ebx, 12(%ebp)          / save the exponent
                    328:        fistp   (%ebx)                  / through the supplied pointer.
                    329:        fwait                           / make sure it is good.
                    330: 
                    331:        pop     %ebp                    / standard
                    332:        ret                             / return.
                    333: 
                    334: //////////
                    335: / modf()       split a double (another way!)
                    336: /
                    337: / calling sequence:
                    338: / double
                    339: / modf(value, intpart);
                    340: / double       value;
                    341: / double       *intpart;
                    342: //////////
                    343: 
                    344: modf:
                    345:        push    %ebp                    / function
                    346:        mov     %ebp, %esp              / sequence.
                    347:        push    %eax                    / claim one word.
                    348: 
                    349: /      fstcw   -2(%ebp)                / save the old control word and
                    350:        fwait
                    351:        fnstcw  -2(%ebp)                / save the old control word and
                    352:        fldcw   cwdown                  / load a new one that rounds down.
                    353:        fld     4(%ebp)                 / pick up argument.
                    354:        fld     %st                     / %st=arg, %st(1)=arg.
                    355:        frndint                         / %st=intpart, %st(1)=arg.
                    356:        fsub    %st(1), %st             / %st=intpart, %st(1)=fracpart.
                    357:        mov     %ebx, 12(%ebp)          / load integer pointer.
                    358:        fstp    (%ebx)                  / store intpart through it and pop.
                    359:        fldcw   -2(%ebp)                / put old control word back.
                    360: 
                    361:        mov     %esp, %ebp              / standard
                    362:        pop     %ebp                    / c
                    363:        ret                             / code
                    364: 
                    365: / end of rts87.s

unix.superglobalmegacorp.com

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