/joh'liks/ n.,adj. 386BSD

Porting Unix to the 386: A Practical Approach



William & Lynne Jolitz


We used GCC but not GNULIB, so we had to roll our own support code as needed.




GCC Support Calls to Replace GNULIB
In addition to the normal subroutine libraries found with BSD, two support subroutines are needed. GCC handles all ANSI C operations by generating the appropriate 386 instructions, with the exception of floating point conversion to signed and unsigned integers.

Listing 1: GCC double to signed integer support function
/* fixdfsi.s: Copyright (c) 1990 William Jolitz. All rights reserved.
 * Written by William Jolitz 1/90
 * Redistribution and use in source and binary forms are freely permitted
 * provided that the above copyright notice and attribution and date of work
 * and this paragraph are duplicated in all such forms.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * GCC compiler support function, truncates a double float into a signed long.
 */

    .globl ___fixdfsi
___fixdfsi:
    pushl   $0xe7f      /* truncate, long real, mask all */
    fnstcw  2(%esp)     /* save my old control word */
    fldcw   (%esp)      /* load truncating one */

    fldl    8(%esp)     /* load double */
    fistpl  8(%esp)     /* store back as an integer */
    fldcw   2(%esp)     /* load prior control word */
    popl    %eax
    movl    4(%esp),%eax
    ret
In Listing One, fixdfsi( ) manages to take a double precision floating point argument (a df) and turn it into a signed integer (an si, or small, within a machine word, integer).

Listing 2: GCC double to unsigned support function
/* fixunsdfsi.s: Copyright (c) 1990 William Jolitz. All rights reserved.
 * Written by William Jolitz 4/90
 * Redistribution and use in source and binary forms are freely permitted
 * provided that the above copyright notice and attribution and date of work
 * and this paragraph are duplicated in all such forms.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * GCC compiler support function, truncates a double float into unsigned long.
 */

    .globl ___fixunsdfsi
___fixunsdfsi:
    pushl   $0xe7f          /* truncate, long real, mask all */
    fnstcw  2(%esp)         /* save my old control word */
    fldcw   (%esp)          /* load truncating one */
    fldl    8(%esp)         /* argument double to accum stack */
    frndint                 /* create integer */
    fcoml   fbiggestsigned  /* bigger than biggest signed? */
    fstsw   %ax
    sahf
    jnb 1f

    fistpl  8(%esp)
    fldcw   2(%esp)         /* load prior control word */
    popl    %eax
    movl    4(%esp),%eax
    ret

1:  fsubl   fbiggestsigned      /* reduce for proper conversion */
    fistpl  8(%esp)         /* convert */
    fldcw   2(%esp)         /* load prior control word */
    popl    %eax
    movl    4(%esp),%eax
    addl    $2147483648,%eax    /* restore bias of 2^31 */
    ret

fbiggestsigned: .double 0r2147483648.0  /* 2^31 */
In Listing Two, fixunsdfsi( ) likewise takes a double-precision floating point argument and returns an unsigned (uns) integer. These functions use the 386 numeric processor integer truncation features to return the appropriate values. Because there is no direct method to convert a floating point number to unsigned format, we detect the condition (for example, above the most positive number possible), reduce the value prior to conversion (so it will fit into a signed value), then add back in what we subtracted after conversion, thus avoiding overflow.


<<BACK NEXT >>



Copyright 1990, 2006 TeleMuse Partners, William Jolitz and Lynne Jolitz