asmfixup.c

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

C
549
字号
/*
  this routine marks the correct target offset and data record address for
  FIXUPP record;
*/
{
    struct asmfixup     *fixup;

    fixup = InsFixups[index];
    if( fixup != NULL ) {
        fixup->fixup_loc = AsmCodeAddress;
#if defined( _STANDALONE_ )
        // fixup->offset = Code->data[index];
        // Code->data[index] = 0; // fixme
        if( fixup->fixup_type != FIX_SEG ) {
            Code->data[index] += fixup->offset;
        }
        /*
        20-Aug-92: put the offset in the location instead of attaching it
        to the fixup
        */
#else
        fixup->offset = Code->data[index];
        Code->data[index] = 0;
#endif

        switch( determinant ) {
        case OP_I16:
        case OP_J32:
            switch( fixup->fixup_type ) {
            case FIX_OFF32:
                fixup->fixup_type = FIX_OFF16;
                break;
            case FIX_PTR32:
                fixup->fixup_type = FIX_PTR16;
                break;
            }
            break;
        case OP_I32:
        case OP_J48:
            switch( fixup->fixup_type ) {
            case FIX_OFF16:
                fixup->fixup_type = FIX_OFF32;
                break;
            case FIX_PTR16:
                fixup->fixup_type = FIX_PTR32;
                break;
            }
            break;
        }
    }
}

#if defined( _STANDALONE_ )

struct fixup *CreateFixupRec( int index )
/***************************************/
/* Create a fixup record for WOMP;
   Note that if Modend is TRUE, it means the fixup is the starting address
   for the module.
*/
{
    struct asmfixup     *fixup;         // fixup structure from WASM
    struct fixup        *fixnode;       // fixup structure from WOMP
    struct asm_sym      *sym;

    fixup = InsFixups[index];

    if( fixup == NULL )
        return( NULL );

    fixnode = FixNew();
    fixnode->next = NULL;
    fixnode->self_relative = FALSE;
    fixnode->lr.target_offset = 0;
    if( !Modend ) {
        fixnode->lr.is_secondary = TRUE;
    } else {
        fixnode->lr.is_secondary = FALSE;
        fixnode->lr.target_offset = fixup->offset;
    }

    if( !Modend ) {
        switch( fixup->fixup_type ) {
        case FIX_LOBYTE:
            fixnode->loc_method = FIX_LO_BYTE;
            break;
        case FIX_RELOFF8:
            fixnode->self_relative = TRUE;
            fixnode->loc_method = FIX_LO_BYTE;
            break;
        case FIX_RELOFF16:
            fixnode->self_relative = TRUE;
        case FIX_OFF16:
            fixnode->loc_method = FIX_OFFSET;
            break;
        case FIX_RELOFF32:
            fixnode->self_relative = TRUE;
        case FIX_OFF32:
            fixnode->loc_method = FIX_OFFSET386;
            break;
        case FIX_SEG:
            fixnode->loc_method = FIX_BASE;
            break;
        case FIX_PTR16:
            fixnode->loc_method = FIX_POINTER;
            break;
        case FIX_PTR32:
            fixnode->loc_method = FIX_POINTER386;
            break;
        }
    }

    sym = fixup->sym;
    if( sym == NULL )
        return( NULL );

    fixnode->loader_resolved = FALSE;

    fixnode->loc_offset = AsmCodeAddress - GetCurrSegStart();

    /*------------------------------------*/
    /* Determine the Target and the Frame */
    /*------------------------------------*/

    if( sym->state == SYM_UNDEFINED ) {
        AsmErr( SYMBOL_NOT_DEFINED, sym->name );
        return( NULL );
    } else if( sym->state == SYM_GRP ) {

        if( Modend ) {
            AsmError( INVALID_START_ADDRESS );
            return( NULL );
        }

        fixnode->lr.target = TARGET_GRP;
        fixnode->lr.target_datum = GetGrpIdx( sym );
        if( fixup->frame != EMPTY ) {
            fixnode->lr.frame = fixup->frame;
            fixnode->lr.frame_datum = fixup->frame_datum;
        } else {
            fixnode->lr.frame = FRAME_GRP;
            fixnode->lr.frame_datum = fixnode->lr.target_datum;
        }

    } else if( sym->state == SYM_SEG ) {

        if( Modend ) {
            AsmError( INVALID_START_ADDRESS );
            return( NULL );
        }

        fixnode->lr.target = TARGET_SEG;
        fixnode->lr.target_datum = GetSegIdx( sym );
        if( fixup->frame != EMPTY ) {
            fixnode->lr.frame = fixup->frame;
            fixnode->lr.frame_datum = fixup->frame_datum;
        } else {
            fixnode->lr.frame = FRAME_SEG;
            fixnode->lr.frame_datum = fixnode->lr.target_datum;
        }

    } else {

        /* symbol is a label */

        if( sym->state == SYM_EXTERNAL ) {
            if( Modend ) {
                if( sym->mem_type == MT_BYTE ||
                    sym->mem_type == MT_SBYTE ||
                    sym->mem_type == MT_WORD ||
                    sym->mem_type == MT_SWORD ||
                    sym->mem_type == MT_DWORD ||
                    sym->mem_type == MT_SDWORD ||
                    sym->mem_type == MT_FWORD ||
                    sym->mem_type == MT_QWORD ||
                    sym->mem_type == MT_TBYTE ||
                    sym->mem_type == MT_OWORD ||
                    sym->mem_type == MT_ABS ) {

                    AsmError( MUST_BE_ASSOCIATED_WITH_CODE );
                    return( NULL );
                }
                fixnode->lr.target = TARGET_EXT & TARGET_WITH_DISPL;
            } else {
                fixnode->lr.target = TARGET_EXT;
            }
            fixnode->lr.target_datum = GetExtIdx( sym );

            if( fixup->frame == FRAME_GRP && fixup->frame_datum == 0 ) {
                /* set the frame to the frame of the corresponding segment */
                fixup->frame_datum = GetGrpIdx( sym );
            }
        } else {
            /**/myassert( sym->segment != NULL );
            if( Modend ) {
                fixnode->lr.target = TARGET_SEG & TARGET_WITH_DISPL;
                fixup->frame = FRAME_TARG;
            } else {
                fixnode->lr.target = TARGET_SEG;
            }
            fixnode->lr.target_datum = GetSegIdx( sym->segment );
        }

        /* HMMM .... what if fixup->frame is say -2 .... ie empty?
        * what should really be going on here?
        */
        // fixnode->lr.frame = (uint_8)fixup->frame;
        // fixnode->lr.frame_datum = fixup->frame_datum;

        if( fixup->frame != EMPTY ) {
            fixnode->lr.frame = (uint_8)fixup->frame;
        } else {
            fixnode->lr.frame = FRAME_TARG;
        }
        fixnode->lr.frame_datum = fixup->frame_datum;

        if( Modend )
            return( fixnode );
    }

    /*--------------------*/
    /* Optimize the fixup */
    /*--------------------*/

    if( fixnode->lr.frame == ( fixnode->lr.target - TARGET_SEG ) ) {
        fixnode->lr.frame = FRAME_TARG;
    }

    return( fixnode );
}

int store_fixup( int index )
/**************************/
/* Store the fixup information in a WOMP fixup record */
{
    struct fixup        *fixnode;

    if( Parse_Pass == PASS_1 )
        return( NOT_ERROR );
    if( InsFixups[index] == NULL )
        return( NOT_ERROR );
    fixnode = CreateFixupRec( index );
    if( fixnode == NULL )
        return( ERROR );

    if( FixupListHead == NULL ) {
        FixupListTail = FixupListHead = fixnode;
    } else {
        FixupListTail->next = fixnode;
        FixupListTail = fixnode;
    }
    return( NOT_ERROR );
}

int MakeFpFixup( struct asm_sym *sym )
/*************************************/
{
    int old_count;
    int_8 old_frame;

    old_count = Opnd_Count;
    old_frame = Frame;
    Opnd_Count = 2;
    Frame = FRAME_LOC;
    AddFixup( sym, FIX_OFF16, OPTJ_NONE );
    Frame = old_frame;
    Opnd_Count = old_count;
    if( store_fixup( 2 ) == ERROR )
        return( ERROR ); // extra entry in insfixups
    return( NOT_ERROR );
}

#endif

⌨️ 快捷键说明

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