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