watloc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 594 行 · 第 1/2 页
C
594 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "dipwat.h"
#include "watloc.h"
#include <string.h>
extern byte *GetAddress( imp_image_handle *, byte *, address *, int );
extern address NilAddr;
void LocationCreate( location_list *ll, location_type lt, void *d )
{
ll->num = 1;
ll->flags = 0;
ll->e[0].bit_start = 0;
ll->e[0].bit_length = 0;
ll->e[0].type = lt;
if( lt == LT_ADDR ) {
ll->e[0].u.addr = *(address *)d;
} else {
ll->e[0].u.p = d;
}
}
void LocationAdd( location_list *ll, long sbits )
{
location_entry *le;
unsigned long add;
unsigned num;
unsigned long bits;
bits = sbits;
if( sbits < 0 ) {
bits = -bits;
add = (bits + 7) / 8;
if( ll->e[0].type == LT_ADDR ) {
ll->e[0].u.addr.mach.offset -= add;
} else {
ll->e[0].u.p = (byte *)ll->e[0].u.p - add;
}
bits = 8 - (bits % 8);
bits %= 8;
}
num = 0;
le = &ll->e[0];
for( ;; ) {
if( le->bit_length == 0 ) break;
if( le->bit_length > bits ) break;
bits -= le->bit_length;
++num;
}
if( num != 0 ) {
ll->num -= num;
memcpy( &ll->e[0], le, ll->num * sizeof( ll->e[0] ) );
}
add = bits / 8;
bits = bits % 8;
ll->e[0].bit_start += bits;
if( ll->e[0].bit_length != 0 ) ll->e[0].bit_length -= bits;
if( ll->e[0].type == LT_ADDR ) {
ll->e[0].u.addr.mach.offset += add;
} else {
ll->e[0].u.p = (byte *)ll->e[0].u.p + add;
}
}
void LocationTrunc( location_list *ll, unsigned bits )
{
unsigned i;
if( bits == 0 ) return;
i = 0;
for( ;; ) {
if( i >= ll->num ) return;
if( ll->e[i].bit_length == 0 ) break;
if( ll->e[i].bit_length > bits ) break;
bits -= ll->e[i].bit_length;
++i;
}
ll->e[i].bit_length = bits;
}
static unsigned SizeLocation( loc_expr e )
{
unsigned subclass;
if( *e & LOC_EXPR_IND ) {
return( *e & ~LOC_EXPR_IND );
}
subclass = *e & SUBCLASS_MASK;
switch( *e & CLASS_MASK ) {
case NOLOCATION:
case REG:
return( 1 );
case BP_OFFSET:
subclass += (INT_1-BP_OFF_BYTE);
/* fall through */
case CONSTANT:
switch( subclass ) {
case INT_1: /* also BP_OFF_BYTE */
return( 2 );
case INT_2: /* also BP_OFF_WORD */
return( 3 );
case INT_4: /* also BP_OFF_DWORD */
case ADDR286:
return( 5 );
case ADDR386:
return( 7 );
}
break;
case MULTI_REG:
return( subclass + 2 );
case IND_REG:
switch( subclass ) {
case IR_CALLOC_NEAR:
case IR_RALLOC_NEAR:
return( 2 );
case IR_CALLOC_FAR:
case IR_RALLOC_FAR:
return( 3 );
}
break;
case OPERATOR:
switch( subclass ) {
case LOP_XCHG:
return( 2 );
default:
return( 1 );
}
}
/* should never get here */
return( 1 );
}
byte *SkipLocation( loc_expr e )
{
return( e + SizeLocation( e ) );
}
location_info InfoLocation( loc_expr e )
{
static signed char OpNeed[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 0 };
static signed char OpAdj[] = { 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, 1, 0 };
unsigned size;
unsigned item;
int depth;
location_info info;
unsigned subclass;
size = SizeLocation( e );
if( *e & LOC_EXPR_IND ) {
--size;
++e;
}
info = NEED_NOTHING | EMPTY_EXPR;
depth = 0;
while( size != 0 ) {
switch( *e & CLASS_MASK ) {
case BP_OFFSET:
case MULTI_REG:
case REG:
case IND_REG:
info |= NEED_REGISTERS;
/* fall through */
case CONSTANT:
info &= ~EMPTY_EXPR;
++depth;
break;
case OPERATOR:
subclass = *e & SUBCLASS_MASK;
if( subclass != LOP_NOP ) info &= ~EMPTY_EXPR;
if( depth < OpNeed[ subclass ] ) info |= NEED_BASE;
depth += OpAdj[ subclass & SUBCLASS_MASK ];
break;
}
item = SizeLocation( e );
e += item;
size -= item;
}
return( info );
}
static byte *ParseLocEntry( imp_image_handle *ii, byte *ptr,
loc_entry *location )
{
unsigned int numregs;
location->bp_offset.class = *ptr++;
switch( location->bp_offset.class & CLASS_MASK ) {
case BP_OFFSET :
switch( location->bp_offset.class ) {
case BP_OFFSET + BP_OFF_BYTE:
location->bp_offset.offset = *((signed char *) ptr);
ptr += sizeof( signed char );
break;
case BP_OFFSET + BP_OFF_WORD:
location->bp_offset.offset = *((signed short *) ptr);
ptr += sizeof( signed short );
break;
case BP_OFFSET + BP_OFF_DWORD:
location->bp_offset.offset = *((signed long *) ptr);
ptr += sizeof( signed long );
break;
}
location->bp_offset.class = BP_OFFSET;
break;
case CONSTANT:
switch( location->memory.class ) {
case CONSTANT + ADDR386:
ptr = GetAddress( ii, ptr, &location->memory.addr, 1 );
break;
case CONSTANT + ADDR286:
ptr = GetAddress( ii, ptr, &location->memory.addr, 0 );
location->constant.class = CONSTANT + ADDR386;
break;
case CONSTANT + INT_1:
location->constant.val = *((signed_8 *) ptr);
ptr += sizeof( signed_8 );
location->constant.class = CONSTANT + INT_4;
break;
case CONSTANT + INT_2:
location->constant.val = *((signed_16 *) ptr);
ptr += sizeof( signed_16 );
location->constant.class = CONSTANT + INT_4;
break;
case CONSTANT + INT_4:
location->constant.val = *((signed_32 *) ptr);
ptr += sizeof( signed_32 );
location->constant.class = CONSTANT + INT_4;
break;
}
break;
case MULTI_REG :
numregs = (location->multi_reg.class & SUBCLASS_MASK) + 1;
location->multi_reg.class &= CLASS_MASK;
location->multi_reg.numregs = numregs;
do {
location->multi_reg.regs[ location->multi_reg.numregs - numregs ]
= *ptr++;
} while( --numregs != 0 );
break;
case REG :
location->multi_reg.regs[0] = location->multi_reg.class & SUBCLASS_MASK;
location->multi_reg.numregs = 1;
location->multi_reg.class = MULTI_REG;
break;
case IND_REG :
switch( location->ind_reg_far.class & SUBCLASS_MASK ) {
case IR_CALLOC_NEAR:
case IR_RALLOC_NEAR:
location->ind_reg_near.off_reg = *ptr++;
break;
default:
location->ind_reg_far.off_reg = *ptr++;
location->ind_reg_far.seg_reg = *ptr++;
break;
}
break;
case OPERATOR:
switch( location->op.class ) {
case OPERATOR+LOP_XCHG:
location->op.stk = *ptr++;
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?