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 + -
显示快捷键?