watloc.c

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

C
594
字号
        }
        break;
    case NOLOCATION :
    default:
        location->locvoid.class = NOLOCATION;
        break;
    }
    return( ptr );
}

typedef struct {
    unsigned    ci      : 5;
    unsigned    start   : 4;
    unsigned    len     : 7;
} reg_entry;

static const reg_entry RegTable[] = {
    { CI_EAX, 0, 8 },
    { CI_EAX, 8, 8 },
    { CI_EBX, 0, 8 },
    { CI_EBX, 8, 8 },
    { CI_ECX, 0, 8 },
    { CI_ECX, 8, 8 },
    { CI_EDX, 0, 8 },
    { CI_EDX, 8, 8 },
    { CI_EAX, 0, 16 },
    { CI_EBX, 0, 16 },
    { CI_ECX, 0, 16 },
    { CI_EDX, 0, 16 },
    { CI_ESI, 0, 16 },
    { CI_EDI, 0, 16 },
    { CI_EBP, 0, 16 },
    { CI_ESP, 0, 16 },
    { CI_CS,  0, 16 },
    { CI_SS,  0, 16 },
    { CI_DS,  0, 16 },
    { CI_ES,  0, 16 },
    { CI_ST0, 0, 80 },
    { CI_ST1, 0, 80 },
    { CI_ST2, 0, 80 },
    { CI_ST3, 0, 80 },
    { CI_ST4, 0, 80 },
    { CI_ST5, 0, 80 },
    { CI_ST6, 0, 80 },
    { CI_ST7, 0, 80 },
    { CI_EAX, 0, 32 },
    { CI_EBX, 0, 32 },
    { CI_ECX, 0, 32 },
    { CI_EDX, 0, 32 },
    { CI_ESI, 0, 32 },
    { CI_EDI, 0, 32 },
    { CI_EBP, 0, 32 },
    { CI_ESP, 0, 32 },
    { CI_FS,  0, 16 },
    { CI_GS,  0, 16 },
};

unsigned RegSize( unsigned idx )
{
    return( RegTable[idx].len / 8 );
}

struct loc_stack_entry {
    union {
        unsigned_32     num;
        location_list   ll;
    }           u;
    enum {
        LS_NUM,
        LS_ADDR,
    }           type;
};

#define MAX_LOC_STACK   10

static struct loc_stack_entry LocStack[MAX_LOC_STACK];
static int LocStkPtr = 0;

void PushBaseLocation( location_list *ll )
{
    LocStack[LocStkPtr].u.ll = *ll;
    LocStack[LocStkPtr].type = LS_ADDR;
    ++LocStkPtr;
}


dip_status EvalLocation( imp_image_handle *ii, location_context *lc, loc_expr e,
                        location_list *ll )
{
    char                        *end;
    struct loc_stack_entry      *sp, *op1, *start;
    int                         i;
    int                         j;
    loc_entry                   loc;
    union {
      struct loc_stack_entry    lse;
      location_list             ll;
      unsigned_32               num;
      address                   addr;
    }                           tmp;
    union {
        unsigned_16             so;
        unsigned_32             lo;
        addr32_ptr              sa;
        addr48_ptr              la;
    }                           item;
    unsigned                    item_size;
    reg_entry                   const *reg;
    int                         item_addr;
    dip_status                  ok;

    end = SkipLocation( e );
    if( *e & LOC_EXPR_IND ) {
        ++e;
    }
    ok = DS_OK;
    sp = &LocStack[LocStkPtr-1];
    start = sp;
    while( e < end ) {
        e = ParseLocEntry( ii, e, &loc );
        switch( loc.locvoid.class ) {
        case BP_OFFSET:
            ++sp;
            sp->type = LS_ADDR;
            ok = DCItemLocation( lc, CI_FRAME, &sp->u.ll );
            if( ok != DS_OK ) {
                DCStatus( ok );
                goto done;
            }
            LocationAdd( &sp->u.ll, loc.bp_offset.offset*8 );
            break;
        case CONSTANT + ADDR386:
            ++sp;
            sp->type = LS_ADDR;
            LocationCreate( &sp->u.ll, LT_ADDR, &loc.memory.addr );
            break;
        case CONSTANT + INT_4:
            ++sp;
            sp->type = LS_NUM;
            sp->u.num = loc.constant.val;
            break;
        case MULTI_REG:
            ++sp;
            sp->type = LS_ADDR;
            sp->u.ll.flags = 0;
            j = 0;
            for( i = 0; i < loc.multi_reg.numregs; ++i ) {
                reg = &RegTable[loc.multi_reg.regs[i]];
                ok = DCItemLocation( lc, reg->ci, &tmp.ll );
                if( ok != DS_OK ) {
                    DCStatus( ok );
                    goto done;
                }
                memcpy( &sp->u.ll.e[j], &tmp.ll.e[0],
                        tmp.ll.num * sizeof( tmp.ll.e[0] ) );
                sp->u.ll.e[j].bit_start += reg->start;
                sp->u.ll.e[j].bit_length = reg->len;
                j += tmp.ll.num;
                sp->u.ll.flags |= tmp.ll.flags;
            }
            sp->u.ll.num = j;
            break;
        case OPERATOR + LOP_IND_2:
            item_addr = 0;
            item_size = 2;
            goto do_ind;
        case OPERATOR + LOP_IND_4:
            item_addr = 0;
            item_size = 4;
            goto do_ind;
        case OPERATOR + LOP_IND_ADDR286:
            item_addr = 1;
            item_size = 4;
            goto do_ind;
        case OPERATOR + LOP_IND_ADDR386:
            item_addr = 1;
            item_size = 6;
do_ind:
            if( sp->type == LS_NUM ) {
                tmp.num = sp->u.num;
                ok = DCItemLocation( lc, CI_DEF_ADDR_SPACE, &sp->u.ll );
                if( ok != DS_OK ) goto done;
                sp->u.ll.e[0].u.addr.mach.offset = tmp.num;
            }
            LocationCreate( &tmp.ll, LT_INTERNAL, &item );
            ok = DCAssignLocation( &tmp.ll, &sp->u.ll, item_size );
            if( ok != DS_OK ) {
                DCStatus( ok );
                goto done;
            }
            if( item_addr ) {
                if( item_size == 4 ) {
                    ConvAddr32ToAddr48( item.sa, tmp.addr.mach );
                } else {
                    tmp.addr.mach = item.la;
                }
                DCAddrSection( &tmp.addr );
                LocationCreate( &sp->u.ll, LT_ADDR, &tmp.addr );
                sp->type = LS_ADDR;
            } else {
                if( item_size == 2 ) {
                    sp->u.num = item.so;
                } else {
                    sp->u.num = item.lo;
                }
                sp->type = LS_NUM;
            }
            break;
        case OPERATOR + LOP_ZEB:
            sp->u.num &= (unsigned_32) 0xff;
            break;
        case OPERATOR + LOP_ZEW:
            sp->u.num &= (unsigned_32) 0xffff;
            break;
        case OPERATOR + LOP_MK_FP:
            op1 = &sp[0];
            --sp;
            if( sp->type == LS_NUM ) {
                tmp.addr = NilAddr;
                tmp.addr.mach.segment = sp->u.num;
            } else {
                if( sp->u.ll.num != 1 || sp->u.ll.e[0].type != LT_ADDR ) {
                    ok = DS_ERR|DS_BAD_PARM;
                    goto done;
                }
                tmp.addr = sp->u.ll.e[0].u.addr;
            }
            if( op1->type == LS_NUM ) {
                tmp.addr.mach.offset = op1->u.num;
            } else {
                if( op1->u.ll.num != 1 || op1->u.ll.e[0].type != LT_ADDR ) {
                    ok = DS_ERR|DS_BAD_LOCATION;
                    goto done;
                }
                tmp.addr.mach.offset = op1->u.ll.e[0].u.addr.mach.offset;
            }
            if( sp->type == LS_NUM ) {
                DCAddrSection( &tmp.addr );
            }
            LocationCreate( &sp->u.ll, LT_ADDR, &tmp.addr );
            sp->type = LS_ADDR;
            break;
        case OPERATOR + LOP_POP:
            --sp;
            break;
        case OPERATOR + LOP_XCHG:
            tmp.lse = sp[0];
            sp[0] = sp[-loc.op.stk];
            sp[-loc.op.stk] = tmp.lse;
            break;
        case OPERATOR + LOP_ADD:
            op1 = &sp[0];
            --sp;
            if( op1->type == LS_ADDR ) {
                /* get the address into sp */
                tmp.lse = *sp;
                *sp = *op1;
                *op1 = tmp.lse;
            }
            if( sp->type == LS_ADDR ) {
                if( op1->type == LS_ADDR ) {
                    tmp.num = op1->u.ll.e[0].u.addr.mach.offset;
                } else {
                    tmp.num = op1->u.num;
                }
                LocationAdd( &sp->u.ll, tmp.num*8 );
                sp->type = LS_ADDR;
            } else {
                sp->u.num += op1->u.num;
                sp->type = LS_NUM;
            }
            break;
        case OPERATOR + LOP_DUP:
            sp[1] = sp[0];
            ++sp;
            break;
        case OPERATOR + LOP_NOP:
            /* well, what did you expect? */
            break;
        }
    }
    if( LocStkPtr == 0 && sp == start ) {
        /* empty location */
        ok = DS_ERR|DS_BAD_LOCATION;
        goto done;
    }
    if( sp->type == LS_ADDR ) {
        *ll = sp->u.ll;
    } else {
        DCItemLocation( lc, CI_DEF_ADDR_SPACE, ll );
        ll->e[0].u.addr.mach.offset = sp->u.num;
    }
done:
    LocStkPtr = 0;
    return( ok );
}

⌨️ 快捷键说明

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