static float_handle BFCnvU64F( unsigned_64 val ) { float_handle t0, t1, t2; t0 = TwoTo32(); t1 = BFCnvUF( val.u._32[ I64HI32 ] ); t2 = BFMul( t0, t1 ); BFFree( t0 ); BFFree( t1 ); t0 = BFCnvUF( val.u._32[ I64LO32 ] ); t1 = BFAdd( t0, t2 ); BFFree( t0 ); BFFree( t2 ); return t1; }
static float_handle BFCnvI64F( signed_64 val ) { float_handle t0, t1, t2; t0 = TwoTo32(); t1 = BFCnvIF( val.u._32[ I64HI32 ] ); t2 = BFMul( t0, t1 ); BFFree( t0 ); BFFree( t1 ); if( val.u.sign.v ) { t0 = BFCnvUF( ( val.u._32[ I64LO32 ] ^ ULONG_MAX ) + 1 ); BFNegate( t0 ); } else { t0 = BFCnvUF( val.u._32[ I64LO32 ] ); } t1 = BFAdd( t0, t2 ); BFFree( t0 ); BFFree( t2 ); return t1; }
static signed_64 BFCnvF64( float_handle flt ) { signed_64 result; float_handle absol, t0, t1, t2, t3; bool positive; int sign = BFSign( flt ); if( 0 == sign ) { result.u._32[0] = 0; result.u._32[1] = 0; return result; } positive = true; absol = flt; if( sign < 0 ) { positive = false; absol = BFCopy( flt ); BFNegate( absol ); } t0 = TwoTo32(); t1 = BFDiv( flt, t0 ); t3 = BFTrunc( t1 ); BFFree( t1 ); result.u._32[ I64HI32 ] = BFCnvF32( t3 ); BFFree( t3 ); t1 = BFCnvUF( result.u._32[ I64HI32 ] ); t2 = BFMul( t0, t1 ); BFFree( t0 ); BFFree( t1 ); t0 = BFSub( flt, t2 ); BFFree( t2 ); t3 = BFTrunc( t0 ); BFFree( t0 ); result.u._32[ I64LO32 ] = BFCnvF32( t3 ); BFFree( t3 ); if( ! positive ) { signed_64 neg; BFFree( absol ); neg = result; U64Neg( &neg, &result ); } return result; }
static PTREE foldInt64( CGOP op, PTREE left, signed_64 v2 ) { signed_64 test; signed_64 v1; float_handle t0, t1, t2; v1 = left->u.int64_constant; switch( op ) { case CO_PLUS: U64Add( &v1, &v2, &left->u.int64_constant ); break; case CO_MINUS: U64Sub( &v1, &v2, &left->u.int64_constant ); break; case CO_TIMES: t0 = BFCnvI64F( v1 ); t1 = BFCnvI64F( v2 ); t2 = BFMul( t0, t1 ); test = BFCnvF64( t2 ); BFFree( t0 ); BFFree( t1 ); BFFree( t2 ); U64Mul( &v1, &v2, &left->u.int64_constant ); if( 0 != I64Cmp( &test, &left->u.int64_constant ) ) { CErr1( ANSI_ARITHMETIC_OVERFLOW ); } break; case CO_DIVIDE: { signed_64 rem; idiv64( &v1, &v2, &left->u.int64_constant, &rem ); } break; case CO_PERCENT: { signed_64 div; idiv64( &v1, &v2, &div, &left->u.int64_constant ); } break; case CO_AND: left->u.int64_constant.u._32[0] = v1.u._32[0] & v2.u._32[0]; left->u.int64_constant.u._32[1] = v1.u._32[1] & v2.u._32[1]; break; case CO_OR: left->u.int64_constant.u._32[0] = v1.u._32[0] | v2.u._32[0]; left->u.int64_constant.u._32[1] = v1.u._32[1] | v2.u._32[1]; break; case CO_XOR: left->u.int64_constant.u._32[0] = v1.u._32[0] ^ v2.u._32[0]; left->u.int64_constant.u._32[1] = v1.u._32[1] ^ v2.u._32[1]; break; case CO_RSHIFT: I64ShiftR( &v1, v2.u._32[ I64LO32 ], &left->u.int64_constant ); break; case CO_LSHIFT: U64ShiftL( &v1, v2.u._32[ I64LO32 ], &left->u.int64_constant ); break; case CO_EQ: left = makeBooleanConst( left, 0 == I64Cmp( &v1, &v2 ) ); return( left ); case CO_NE: left = makeBooleanConst( left, 0 != I64Cmp( &v1, &v2 ) ); return( left ); case CO_GT: left = makeBooleanConst( left, 0 < I64Cmp( &v1, &v2 )) ; return( left ); case CO_LE: left = makeBooleanConst( left, 0 >= I64Cmp( &v1, &v2 ) ); return( left ); case CO_LT: left = makeBooleanConst( left, 0 > I64Cmp( &v1, &v2 )) ; return( left ); case CO_GE: left = makeBooleanConst( left, 0 <= I64Cmp( &v1, &v2 ) ); return( left ); case CO_AND_AND: left = makeBooleanConst( left, !Zero64( &v1 ) && !Zero64( &v2 ) ); return( left ); case CO_OR_OR: left = makeBooleanConst( left, !Zero64( &v1) || !Zero64( &v2 ) ); return( left ); case CO_COMMA: left->u.int64_constant = v2; break; default: return( NULL ); } left->op = PT_INT_CONSTANT; return( left ); }
static PTREE foldFloating( CGOP op, PTREE left, float_handle v2 ) { float_handle v1; float_handle tmp; v1 = left->u.floating_constant; switch( op ) { case CO_PLUS: tmp = BFAdd( v1, v2 ); BFFree( v1 ); v1 = tmp; break; case CO_MINUS: tmp = BFSub( v1, v2 ); BFFree( v1 ); v1 = tmp; break; case CO_TIMES: tmp = BFMul( v1, v2 ); BFFree( v1 ); v1 = tmp; break; case CO_DIVIDE: if( BFSign( v2 ) == 0 ) { CErr1( ERR_DIVISION_BY_ZERO ); } tmp = BFDiv( v1, v2 ); BFFree( v1 ); v1 = tmp; break; case CO_EQ: left = makeBooleanConst( left, BFCmp( v1, v2 ) == 0 ); BFFree( v1 ); return( left ); case CO_NE: left = makeBooleanConst( left, BFCmp( v1, v2 ) != 0 ); BFFree( v1 ); return( left ); case CO_GT: left = makeBooleanConst( left, BFCmp( v1, v2 ) > 0 ); BFFree( v1 ); return( left ); case CO_LE: left = makeBooleanConst( left, BFCmp( v1, v2 ) <= 0 ); BFFree( v1 ); return( left ); case CO_LT: left = makeBooleanConst( left, BFCmp( v1, v2 ) < 0 ); BFFree( v1 ); return( left ); case CO_GE: left = makeBooleanConst( left, BFCmp( v1, v2 ) >= 0 ); BFFree( v1 ); return( left ); case CO_COMMA: BFFree( v1 ); v1 = BFCopy( v2 ); break; default: return( NULL ); } left->u.floating_constant = v1; left->op = PT_FLOATING_CONSTANT; return( left ); }
static void DoDataInit( PTYPE var_type ) { //========================================== // Do data initialization. int const_size; int var_size; int size; byte *const_ptr; segment_id seg; seg_offset offset; byte const_buff[sizeof(ftn_type)]; if( ( DtConstType == PT_CHAR ) || ( DtConstType == PT_NOTYPE ) ) { const_size = DtConst->u.lt.length; const_ptr = &DtConst->u.lt.value; } else { const_size = DtConst->u.cn.size; const_ptr = (byte *)(&DtConst->u.cn.value); } var_size = DtItemSize; seg = GetDataSegId( InitVar ); offset = GetDataOffset( InitVar ); DtInit( seg, offset ); if( DtConstType == PT_CHAR ) { if( const_size >= var_size ) { DtBytes( const_ptr, var_size ); } else { DtBytes( const_ptr, const_size ); DtIBytes( ' ', var_size - const_size ); } } else if( ( var_type == PT_CHAR ) && IntType( DtConstType ) ) { DtBytes( const_ptr, sizeof( char ) ); if( var_size > sizeof( char ) ) { DtIBytes( ' ', var_size - sizeof( char ) ); } } else if( DtConstType == PT_NOTYPE ) { if( var_type != PT_CHAR ) { size = var_size; while( size > const_size ) { size--; const_buff[ size ] = 0; } while( size > 0 ) { size--; const_buff[ size ] = *const_ptr; const_ptr++; } const_ptr = const_buff; const_size = var_size; } if( const_size < var_size ) { DtIBytes( 0, var_size - const_size ); var_size = const_size; } else { const_ptr += const_size - var_size; } DtBytes( const_ptr, var_size ); } else if( DtConstType <= PT_LOG_4 ) { DtBytes( const_ptr, var_size ); } else { // numeric to numeric if( DtConstType != var_type ) { DataCnvTab[ ( var_type - PT_INT_1 ) * CONST_TYPES + ( DtConstType - PT_INT_1 ) ]( (ftn_type *)const_ptr, (ftn_type *)&const_buff ); const_ptr = const_buff; } // Temporary fix for identical precision between front end and code generator. { char fmt_buff[CONVERSION_BUFFER+1]; float_handle cf; if( (var_type == PT_REAL_4) || (var_type == PT_CPLX_8) ) { CnvS2S( (single *)const_ptr, fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff, BETypeLength( TY_SINGLE ) ); BFFree( cf ); } else if( (var_type == PT_REAL_8) || (var_type == PT_CPLX_16) ) { CnvD2S( (double *)const_ptr, fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff, BETypeLength( TY_DOUBLE ) ); BFFree( cf ); } else if( (var_type == PT_REAL_16) || (var_type == PT_CPLX_32) ) { CnvX2S( (extended *)const_ptr, fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff, BETypeLength( TY_LONGDOUBLE ) ); BFFree( cf ); } if( var_type == PT_CPLX_8 ) { CnvS2S( (single *)(const_ptr + sizeof( single )), fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff + sizeof( single ), BETypeLength( TY_SINGLE ) ); BFFree( cf ); } else if( var_type == PT_CPLX_16 ) { CnvD2S( (double *)(const_ptr + sizeof( double )), fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff + sizeof( double ), BETypeLength( TY_DOUBLE ) ); BFFree( cf ); } else if( var_type == PT_CPLX_32 ) { CnvX2S( (extended *)(const_ptr + sizeof( extended )), fmt_buff ); cf = BFCnvSF( fmt_buff ); BFCnvTarget( cf, const_buff + sizeof( extended ), BETypeLength( TY_LONGDOUBLE ) ); BFFree( cf ); } if( (var_type >= PT_REAL_4) && (var_type <= PT_CPLX_32) ) { const_ptr = const_buff; } } // End of temporary fix. DtBytes( const_ptr, var_size ); } DtItemSize = 0; }