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