asiobj.c

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

C
569
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Inline assembler support for various front ends.
*
****************************************************************************/


#include "as.h"
#include "asinline.h"

#ifdef _STANDALONE_
#error For inline-assembler only!
#endif

#define ASMCODESTART    "0ASM"          // must be a non-usable string

unsigned char           *AsmCodeBuffer;
uint_32                 AsmCodeAddress;
uint_32                 AsmLastAddress;
asmreloc                *AsmRelocs;
uint_8                  CurrAlignment;

struct asm_label {
    sym_handle          sym;            // NULL if is_numeric
    struct asm_label    *next;
    uint_32             is_numeric : 1;
    uint_32             label_num : 31;
};

typedef struct asm_label *label_list;

static label_list       labelList = NULL;       // The list of pending labels
static asmreloc         *lastReloc;

static owl_offset tellOffset( void ) {
//************************************

    return( AsmCodeAddress );
}

static void doEmitData( char *buffer, int size ) {
//************************************************

    memcpy( &AsmCodeBuffer[AsmCodeAddress], buffer, size );
    AsmCodeAddress += size;
    if( AsmCodeAddress > AsmLastAddress ) {
        AsmLastAddress = AsmCodeAddress;
    }
}

static void doEmitLabel( label_list label ) {
//*******************************************

    sym_location    loc;

    labelList = label->next;
    //label->next = NULL;
    if( label->is_numeric ) {
        AsNumLabelEmit( label->label_num, NULL, AsmCodeAddress, 0 );
    } else {
        loc.offset = AsmCodeAddress;
        SymSetLocation( label->sym, loc );
    }
}

static owl_offset getSymOffset( sym_handle sym ) {
//************************************************

    sym_location    loc;

    assert( SymLocationKnown( sym ) );
    loc = SymGetLocation( sym );
    return( loc.offset );
}

static owl_offset relocTargetDisp( owl_offset from, owl_offset to ) {
//*******************************************************************

    owl_offset  ret;

#ifdef AS_ALPHA
    from += 4;  // Alpha uses updated PC
#endif // PPC & MIPS uses current PC
    assert( ( to % 4 ) == 0 );
    assert( ( from % 4 ) == 0 );
    ret = to - from;
#if defined( AS_PPC )
    return( ret );
#elif defined( AS_ALPHA )
    return( ret >> 2 );
#elif defined( AS_MIPS )
    // TODO
    return( ret >> 2 );
#else
    #error Unknown CPU type for assembler!
#endif
}

static unsigned relocMasks[] = {
#if defined( AS_PPC )
    0xffffffff,         /* OWL_RELOC_ABSOLUTE */
    0xffffffff,         /* OWL_RELOC_WORD */
    0x0000ffff,         /* OWL_RELOC_HALF_HI */
    0x0000ffff,         /* OWL_RELOC_HALF_HA */
    0x00000000,         /* OWL_RELOC_PAIR */
    0x0000ffff,         /* OWL_RELOC_HALF_LO */
    0x0000fffc,         /* OWL_RELOC_BRANCH_REL */
    0x0000fffc,         /* OWL_RELOC_BRANCH_ABS */
    0x03fffffc,         /* OWL_RELOC_JUMP_REL */
    0x03fffffc,         /* OWL_RELOC_JUMP_ABS */
    0x0000ffff,         /* OWL_RELOC_SECTION_INDEX */
    0xffffffff,         /* OWL_RELOC_SECTION_OFFSET */
#elif defined( AS_ALPHA )
    0xffffffff,         /* OWL_RELOC_ABSOLUTE */
    0xffffffff,         /* OWL_RELOC_WORD */
    0x0000ffff,         /* OWL_RELOC_HALF_HI */
    0x0000ffff,         /* OWL_RELOC_HALF_HA, unused */
    0x00000000,         /* OWL_RELOC_PAIR */
    0x0000ffff,         /* OWL_RELOC_HALF_LO */
    0x001fffff,         /* OWL_RELOC_BRANCH_REL */
    0x001fffff,         /* OWL_RELOC_BRANCH_ABS, unused */
    0x00003fff,         /* OWL_RELOC_JUMP_REL */
    0x00003fff,         /* OWL_RELOC_JUMP_ABS, unused */
    0x0000ffff,         /* OWL_RELOC_SECTION_INDEX */
    0xffffffff,         /* OWL_RELOC_SECTION_OFFSET */
#elif defined( AS_MIPS )
    // TODO
    0xffffffff,         /* OWL_RELOC_ABSOLUTE */
    0xffffffff,         /* OWL_RELOC_WORD */
    0x0000ffff,         /* OWL_RELOC_HALF_HI */
    0x0000ffff,         /* OWL_RELOC_HALF_HA, unused? */
    0x00000000,         /* OWL_RELOC_PAIR */
    0x0000ffff,         /* OWL_RELOC_HALF_LO */
    0x001fffff,         /* OWL_RELOC_BRANCH_REL */
    0x001fffff,         /* OWL_RELOC_BRANCH_ABS, unused */
    0x00003fff,         /* OWL_RELOC_JUMP_REL */
    0x00003fff,         /* OWL_RELOC_JUMP_ABS, unused */
    0x0000ffff,         /* OWL_RELOC_SECTION_INDEX */
    0xffffffff,         /* OWL_RELOC_SECTION_OFFSET */
#endif
};

static unsigned relocBitMask( asmreloc *reloc ) {
//***********************************************

    assert( reloc != NULL );
    return( relocMasks[ reloc->type ] );
}

static void doReloc( asmreloc *reloc ) {
//**************************************

    sym_handle  sym;
    uint_32     bit_mask;
    uint_32     *data;
    owl_offset  displacement;

    sym = SymLookup( reloc->name );
    displacement = relocTargetDisp( reloc->offset, getSymOffset( sym ) );
    bit_mask = relocBitMask( reloc );
    data = (uint_32 *)&AsmCodeBuffer[ reloc->offset ];
    *data = (*data&~bit_mask)|(((displacement&bit_mask)+(*data&bit_mask))&bit_mask);
}

static void resolveRelativeRelocs( void ) {
//*****************************************
// Do all relative relocs within the inline code and
// complain about references that are not internal and not defined by the
// compiler.

    asmreloc            *curr_reloc;
    asmreloc            **last;
    char                *keep_name;
    enum sym_state      state;

    curr_reloc = AsmRelocs;
    last = &AsmRelocs;
    while( curr_reloc ) {
        if( SymLocationKnown( SymLookup( curr_reloc->name ) ) ) {
            if( IS_RELOC_RELATIVE( curr_reloc->type ) ) {
                doReloc( curr_reloc );
            } else {
                // If not relative, we won't do it! (?)
                Error( ABS_REF_NOT_ALLOWED, curr_reloc->name );
            }
        } else {
            // See if it's defined outside.
            state = AsmQueryExternal( curr_reloc->name );
            if( state == SYM_UNDEFINED ) {
                Error( SYMBOL_NOT_DECLARED, curr_reloc->name );
            } else {
                if( IS_RELOC_RELATIVE( curr_reloc->type ) && state == SYM_STACK ) {
                    Error( CANNOT_JUMP_TO_STACKVAR );
                } else {
                    // Leave these in the list...
                    //Warning( "'%s' is left for CC to take care of", curr_reloc->name );
                    keep_name = MemAlloc( strlen( curr_reloc->name ) + 1 );
                    strcpy( keep_name, curr_reloc->name );
                    curr_reloc->name = keep_name;
                    last = &curr_reloc->next;
                    curr_reloc = curr_reloc->next;
                    continue;
                }
            }
        }
        *last = curr_reloc->next;
        MemFree( curr_reloc );
        curr_reloc = *last;
    }
}

static asmreloc *newReloc( owl_offset offset, char *name, owl_reloc_type type ) {
//*******************************************************************************

    asmreloc    *reloc;

    reloc = MemAlloc( sizeof( asmreloc ) );
    reloc->next = NULL;
    reloc->name = name;
    reloc->offset = offset;
    reloc->type = type;
    return( reloc );
}

static void doEmitReloc( owl_offset offset, void *target, owl_reloc_type type, bool named_sym ) {
//***********************************************************************************************

    asmreloc    *reloc;
    int_32      label_num;

    if( named_sym ) {
        assert( SymLookup( target ) != NULL );
        reloc = newReloc( offset, target, type );
        if( AsmRelocs == NULL ) {
            AsmRelocs = reloc;
            lastReloc = reloc;
        } else {
            lastReloc->next = reloc;
            lastReloc = reloc;
        }
    } else {
        label_num = *(int_32 *)target;
        AsNumLabelReloc( NULL, offset, label_num, type );
    }
}

static void doStackLabel( sym_handle sym ) {
//******************************************

    label_list          new_label;

    new_label = MemAlloc( sizeof( struct asm_label ) );
    new_label->sym = sym;
    new_label->next = labelList;
    new_label->is_numeric = 0;
    new_label->label_num = 0;
    labelList = new_label;
}

extern void ObjInit( void ) {
//***************************

⌨️ 快捷键说明

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