madman.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,275 行 · 第 1/5 页

C
2,275
字号
#endif
            amount %= BITS_PER_BYTE;
        }
        if( amount != 0 ) {
            tmp1 = 0;
            for( i = bytes-byte_shift-1; i >= 0; --i ) {
                tmp2 = b[i];
                b[i] = (b[i] >> amount) | (tmp1 << (BITS_PER_BYTE - amount));
                tmp1 = tmp2;
            }
        }
    }
}

static void ExtractBits( unsigned pos, unsigned len, const void *src, void *dst, int dst_size )
{
    unsigned_64         tmp;
    unsigned            bytes;
    unsigned_8          *d = dst;

    src = (unsigned_8 *)src + (pos / BITS_PER_BYTE);
    pos %= BITS_PER_BYTE;
    bytes = (pos + len + (BITS_PER_BYTE-1)) / BITS_PER_BYTE;
    memset( &tmp, 0, sizeof( tmp ) );
    memcpy( &tmp, src, bytes );
    ShiftBits( pos + len, -pos, &tmp );
    bytes = len / BITS_PER_BYTE;
    tmp.u._8[bytes] &= BitMask[ len % BITS_PER_BYTE ];
#if defined( __BIG_ENDIAN__ )
    d += dst_size - (len + (BITS_PER_BYTE-1)) / BITS_PER_BYTE;
#endif
    memcpy( d, &tmp, (len + (BITS_PER_BYTE-1)) / BITS_PER_BYTE );
}

static void InsertBits( unsigned pos, unsigned len, const void *src, void *dst )
{
    unsigned_64         tmp;
    unsigned            bytes;
    unsigned            i;

    dst = (unsigned_8 *)dst + (pos / BITS_PER_BYTE);
    pos %= BITS_PER_BYTE;
    bytes = (len + (BITS_PER_BYTE-1)) / BITS_PER_BYTE;
    memset( &tmp, 0, sizeof( tmp ) );
    memcpy( &tmp, src, bytes );
    len += pos;
    bytes = (len + (BITS_PER_BYTE-1)) / BITS_PER_BYTE;
    ShiftBits( len, pos, &tmp );
    src = &tmp;
    for( i = 0; i < bytes; ++i ) {
        ((unsigned_8 *)dst)[i] |= ((unsigned_8 *)src)[i];
    }
}

//NYI: non radix 2, sign-magnitude floats
static mad_status DecomposeFloat( const mad_type_info *mti, const void *d,
                                    decomposed_item *v )
{
    unsigned    bytes;
    unsigned    mant_bits;
    unsigned    shifts;
    unsigned    i;
    unsigned_8  *dst = &v->f.mantissa.u._8[0];

    memset( v, 0, sizeof( *v ) );
    bytes = mti->b.bits / BITS_PER_BYTE;
    if( memcmp( &v->f.mantissa, d, bytes ) == 0 ) {
        v->f.type = F_ZERO;
        /* number is zero */
        return( MS_OK );
    }

#if defined( __BIG_ENDIAN__ )
    dst += DF_SIZE - bytes;     /* low bytes are higher in memory */
#endif
    if( mti->i.endian == ME_HOST ) {
        memcpy( dst, d, bytes );
    } else {
        for( i = 0; i < bytes; i++ ) {
            dst[i] = ((unsigned_8 *)d)[EndMap[ME_BIG][DF_SIZE - bytes + i]];
        }
    }

    ExtractBits( mti->f.exp.pos, mti->f.exp.data.b.bits,
                &v->f.mantissa, &v->f.exp, sizeof( v->f.exp ) );
    /* Assuming IEEE here */
    if( v->f.exp == 0 ) {
        v->f.type = F_DENORMAL;
    } else if( v->f.exp == BitMask[ mti->f.exp.data.b.bits ] ) {
        v->f.type = F_SPECIAL;
    }
    v->f.exp -= mti->f.exp.bias;
    ExtractBits( mti->f.mantissa.sign_pos, 1, &v->f.mantissa,
                &v->f.sign, sizeof( v->f.sign ) );
    mant_bits = mti->b.bits - mti->f.exp.data.b.bits - 1;
    if( mti->f.exp.hidden && (v->f.type != F_DENORMAL) ) mant_bits += 1;
    ShiftBits( sizeof( v->f.mantissa )*BITS_PER_BYTE,
        sizeof( v->f.mantissa )*BITS_PER_BYTE - mant_bits, &v->f.mantissa );
    if( v->f.type == F_DENORMAL ) {
        shifts = 0;
        for( ;; ) {
            if( v->f.mantissa.u._8[sizeof(v->f.mantissa)-1] & 0x80 ) break;
            ShiftBits( sizeof( v->f.mantissa )*BITS_PER_BYTE, 1, &v->f.mantissa );
            if( ++shifts > sizeof( v->f.mantissa )*BITS_PER_BYTE ) {
                /* mantissa is all zero bits - we must have gotten a -0.0 */
                v->f.type = F_ZERO;
                v->f.exp = 0;
                return( MS_OK );
            }
            v->f.exp--;
        }
        v->f.type = F_NORMAL;
    }
    if( mti->f.exp.hidden && (v->f.type != F_DENORMAL) ) {
        v->f.mantissa.u._8[sizeof(v->f.mantissa)-1] |= 0x80;
    }
    return( MS_OK );
}

/* Convert native integer to specified representation */
static mad_status ComposeInt( decomposed_item *v,
                                const mad_type_info *mti, void *d )
{
    unsigned    bytes;
    unsigned    i;
    unsigned_8  *src = &v->i.u._8[0];

    bytes = mti->b.bits / BITS_PER_BYTE;
#if defined( __BIG_ENDIAN__ )
    src += DI_SIZE - bytes;     /* low bytes are higher in memory */
#endif
    if( mti->i.endian == ME_HOST ) {
        memcpy( d, src, bytes );
    } else {
        for( i = 0; i < bytes; i++ ) {
            ((unsigned_8 *)d)[EndMap[ME_BIG][DI_SIZE - bytes + i]] = src[i];
        }
    }
    return( MS_OK );
}

static mad_status ComposeAddr( decomposed_item *v,
                                const mad_type_info *mti, void *d )
{
    unsigned    bytes;

    if( mti->a.seg.pos == 0 ) {
        bytes = mti->a.seg.bits / BITS_PER_BYTE;
        memcpy( d, &v->a.segment, bytes );
        d = (unsigned_8 *)d + bytes;
        bytes = (mti->b.bits - mti->a.seg.bits) / BITS_PER_BYTE;
        memcpy( d, &v->a.offset, bytes );
    } else {
        bytes = (mti->b.bits - mti->a.seg.bits) / BITS_PER_BYTE;
        memcpy( d, &v->a.offset, bytes );
        d = (unsigned_8 *)d + bytes;
        bytes = mti->a.seg.bits / BITS_PER_BYTE;
        memcpy( d, &v->a.segment, bytes );
    }
    return( MS_OK );
}

static mad_status ComposeFloat( decomposed_item *v,
                                const mad_type_info *mti, void *d )
{
    unsigned    bytes;
    unsigned    mant_bits;
    unsigned    i;

    bytes = mti->b.bits / BITS_PER_BYTE;
    memset( d, 0, bytes );
    if( v->f.type == F_ZERO ) {
        /* number is zero */
        if( v->f.sign != 0 ) {
            InsertBits( mti->f.mantissa.sign_pos, 1, &v->f.sign, d );
        }
        return( MS_OK );
    }
    mant_bits = mti->b.bits - mti->f.exp.data.b.bits - 1;
    if( mti->f.exp.hidden ) {
        v->f.mantissa.u._8[sizeof(v->f.mantissa)-1] &= ~0x80;
        mant_bits += 1;
    }
    if( v->f.type == F_SPECIAL ) {
        v->f.exp = BitMask[ mti->f.exp.data.b.bits ];
    } else {
        v->f.exp += mti->f.exp.bias;
        if( v->f.exp <= 0 ) {
            /* denormal */
            if( mti->f.exp.hidden ) {
                v->f.mantissa.u._8[sizeof(v->f.mantissa)-1] |= 0x80;
            }
            while( v->f.exp < 0 ) {
                ShiftBits( sizeof( v->f.mantissa )*BITS_PER_BYTE, -1, &v->f.mantissa );
                v->f.exp++;
            }
        } else if( v->f.exp >= BitMask[ mti->f.exp.data.b.bits ] ) {
            /* infinity */
            memset( &v->f.mantissa, 0, sizeof( v->f.mantissa ) );
            v->f.exp = BitMask[ mti->f.exp.data.b.bits ];
        }
    }
    ShiftBits( sizeof( v->f.mantissa )*BITS_PER_BYTE,
        mant_bits - sizeof( v->f.mantissa )*BITS_PER_BYTE, &v->f.mantissa );
    memcpy( d, &v->f.mantissa, bytes );
    InsertBits( mti->f.exp.pos, mti->f.exp.data.b.bits, &v->f.exp, d );
    if( v->f.sign != 0 ) {
        InsertBits( mti->f.mantissa.sign_pos, 1, &v->f.sign, d );
    }
    if( mti->i.endian != ME_HOST ) {
        for( i = 0; i < bytes / 2; i++ ) {
            unsigned_8  tmp;

            tmp = ((unsigned_8 *)d)[bytes - i - 1];
            ((unsigned_8 *)d)[bytes - i - 1] = ((unsigned_8 *)d)[i];
            ((unsigned_8 *)d)[i] = tmp;
        }
    }
    return( MS_OK );
}

static mad_status DoConversion( const mad_type_info *in_t, const void *in_d, const mad_type_info *out_t, void *out_d, addr_seg seg )
{
    mad_status          ms;
    decomposed_item     value;

    if( in_t->b.kind != out_t->b.kind ) return( MS_UNSUPPORTED );
    switch( in_t->b.kind ) {
    case MTK_INTEGER:
        ms = DecomposeInt( in_t, in_d, &value );
        if( ms != MS_OK ) return( ms );
        return( ComposeInt( &value, out_t, out_d ) );
    case MTK_ADDRESS:
        ms = DecomposeAddr( in_t, in_d, seg, &value );
        if( ms != MS_OK ) return( ms );
        return( ComposeAddr( &value, out_t, out_d ) );
    case MTK_FLOAT:
        ms = DecomposeFloat( in_t, in_d, &value );
        if( ms != MS_OK ) return( ms );
        return( ComposeFloat( &value, out_t, out_d ) );
    }
    return( MS_UNSUPPORTED );
}

mad_status      MADTypeConvert( const mad_type_info *in_t, const void *in_d, const mad_type_info *out_t, void *out_d, addr_seg seg )
{
    mad_status  ms;

    if( in_t->b.handler_code  == MAD_DEFAULT_HANDLING
     && out_t->b.handler_code == MAD_DEFAULT_HANDLING ) {
        ms = DoConversion( in_t, in_d, out_t, out_d, seg );
        if( ms == MS_OK ) return( MS_OK );
    }
    return( Active->rtns->MITypeConvert( in_t, in_d, out_t, out_d, seg ) );
}

static mad_status DIGREGISTER DummyTypeToString( unsigned base, const mad_type_info *mti, const void *d, unsigned *max, char *buff )
{
    base = base;
    mti = mti;
    d = d;
    max = max;
    buff = buff;
    return( MS_UNSUPPORTED );
}

static const char DigitTab[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

//NYI: big endian hosts & targets
static char *U64CvtNum( unsigned_64 val, unsigned radix, char *p, int bit_length )
{
    unsigned            len;
    char                save;
    int                 digits;
    unsigned_64         rem;
    unsigned_64         divisor;

    switch( radix ) {
    case 2:
        digits = bit_length;
        break;
    case 16:
        digits = bit_length / (BITS_PER_BYTE / 2);
        break;
    default:
        digits = 0;
        break;
    }
    U32ToU64( radix, &divisor );
    do {
        U64Div( &val, &divisor, &val, &rem );
        *--p = DigitTab[ rem.u._32[I64LO32] ];
        --digits;
    } while( val.u._32[I64LO32] != 0 || val.u._32[I64HI32] != 0 || digits > 0 );
    len = MADCliRadixPrefix( radix, 0, NULL );
    p -= len;
    save = p[len];
    MADCliRadixPrefix( radix, len + 1, p );
    p[len] = save; /* got overwritten with a '\0' */
    return( p );
}

static char *CvtNum( unsigned long val, unsigned radix, char *p, int bit_length )
{
    unsigned_64 tmp;

    U32ToU64( val, &tmp );
    return( U64CvtNum( tmp, radix, p, bit_length ) );
}

static mad_status IntTypeToString( unsigned radix, mad_type_info const *mti,
                        const void *d, unsigned *maxp, char *res )
{
    decomposed_item     val;
    int                 neg;
    char                buff[128];
    char                *p;
    unsigned            max;
    mad_status          ms;


    ms = DecomposeInt( mti, d, &val );
    if( ms != MS_OK ) return( ms );
    neg = 0;
    if( mti->i.nr != MNR_UNSIGNED && val.i.u.sign.v ) {
        neg = 1;
        U64Neg( &val.i, &val.i );
    }
    p = U64CvtNum( val.i, radix, &buff[ sizeof( buff ) ], mti->b.bits );
    if( neg ) *--p = '-';
    max = *maxp;
    *maxp = &buff[ sizeof( buff ) ] - p;
    if( max > 0 ) {
        --max;
        if( max > *maxp ) max = *maxp;
        memcpy( res, p, max );
        res[max] = '\0';
    }
    return( MS_OK );
}

static mad_status AddrTypeToString( unsigned radix, mad_type_info const *mti,
                        const void *d, unsigned *maxp, char *res )
{
    decomposed_item     val;
    char                *p;
    unsigned            max;
    char                buff[80];
    mad_status          ms;

    ms = DecomposeAddr( mti, d, 0, &val );
    if( ms != MS_OK ) return( ms );
    p = CvtNum( val.a.offset, radix, &buff[ sizeof( buff ) ], mti->b.bits - mti->a.seg.bits );
    if( mti->a.seg.bits != 0 ) {
        *--p = ':';
        p = CvtNum( val.a.segment, radix, p, mti->a.seg.bits );
    }
    max = *maxp;
    *maxp = &buff[ sizeof( buff ) ] - p;
    if( max > 0 ) {
        --max;
        if( max > *maxp ) max = *maxp;
        memcpy( res, p, max );
        res[max] = '\0';
    }
    return( MS_OK );
}

#if !defined(MAD_OMIT_FLOAT_CVT)

#define LOG10B2( v )    (((v) * 30103L ) / 100000L )
#define MAX_DIGITS      21

#ifdef __WATCOMC__
static char *fixup( char *p, int n )
{
    char    *start = p;

    if( n < MAX_DIGITS && isdigit( *p ) ) {
        while( *p ) {
            p++;
            n--;
        }
        while( n > 0 ) {
            *p++ = '0';
            n--;
        }
        *p = '\0';
    }
    return( start );
}

static char *__xcvt( long_double *value,
             int    ndigits,
             int    *dec,
             int    *sign,
             char   *buf )
{
    CVT_INFO    cvt;

    cvt.flags = G_FMT + F_CVT + NO_TRUNC + LONG_DOUBLE;
    cvt.scale = 1;
    cvt.ndigits = ndigits;
    cvt.expwidth = 0;
    cvt.expchar  = 0;
    __LDcvt( value, &cvt, buf );
    *dec = cvt.decimal_place;
    *sign = cvt.sign;
    fixup( buf, ndigits );
    return( buf );
}
#endif

static char *DoStrReal( long_double *value, char *p, mad_type_info const *mti )
{
    unsigned    mant_digs;
    unsigned    exp_digs;
    char        *mant;
    int         sign;
    int         exp;
    char        buff[80];

    exp_digs = LOG10B2( mti->f.exp.data.b.bits * (mti->f.exp.base / 2) );
    mant_digs = LOG10B2( mti->b.bits + mti->f.exp.hidden
                        - ( mti->f.exp.data.b.bits + 1 ) );
#ifdef __WATCOMC__
    mant = __xcvt( value, mant_digs, &exp, &sign, buff );
#else
    mant = ecvt( value->value, mant_digs, &exp, &sign );
#endif
    if( !isdigit( *mant ) ) {
        /* special magical thingy (nan, inf, ...) */
        strcpy( p, mant );
        return( p );
    }
    if( *mant != '0' )
        --exp;
    sprintf( p, "%c%c.%sE%+4.4d", 
        ( sign ) ? '-' : '+', *mant, mant + 1, exp );
    return( p );
}

static mad_status FloatTypeToString( unsigned radix, mad_type_info const *mti,
                        const void *d, unsigned *maxp, char *res )
{
    unsigned            max;
    mad_type_info       host;
    unsigned_8    const *p;
    unsigned            len;
    mad_status          ms;
#if defined( _LONG_DOUBLE_ )
    xreal               val;
#else
    lreal               val;
#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?