s37page.c

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

C
928
字号

    op1 = NULL;
    op2 = NULL;
    switch( bead->ins.class )  {
    case HWINS_RR:
        break;
    case HWINS_RX:
        op1 = &bead->rx.s2;
        break;
    case HWINS_RS1:
        op1 = &bead->rs1.s2;
        break;
    case HWINS_RS2:
        op1 = &bead->rs2.s2;
        break;
    case HWINS_SI:
        op1 = &bead->si.s1;
        break;
    case HWINS_S:
        op1 = &bead->s.s2;
        break;
    case HWINS_SS1:
        op1 = &bead->ss1.s1;
        op2 = &bead->ss1.s2;
        break;
    case HWINS_SS2:
        op1 = &bead->ss2.s1;
        op2 = &bead->ss2.s2;
        break;
    }
    if( op1 == NULL ){
         return( NULL );
    }
    if( op1->ref != NULL && op1->ref->entry.class == REF_LIT ) {
        return( op1->ref );
    }
    if( op2 == NULL ) {
        return( NULL );
    }
    if( op2->ref != NULL && op2->ref->entry.class == REF_LIT ) {
        return( op2->ref );
    }
    return( NULL );
}

static int CalcBackRefs( hw_sym *sym  ) {
/* calc number of backward references to label */
    offset address;
    ref_sym *ref;
    int     count;

    address = sym->def->address;
    count = 0;
    for( ref = &sym->refs->sym; ref != NULL; ref = ref->common.next ) {
        if( ref->use->address > address ) {
            count++;
        }
    }
    return( count );
}

static  void CodePages( page_entry *head, char br ) {
/****Dump out jumps literal etc*******/
    page_entry *curr;

    curr = head;
    while( curr != NULL ){
        DoLongJmps( curr, head, br );
        DoIndexJmps( curr, head, br );
        DoLits( &curr->pool, curr->code.end );
        curr = curr->next;
    }
}

static char FirstPage( page_entry *page ) {
/***find entry label and main base reg for function******/
    bead_def *bead;
    char      br;

    bead = page->code.start;
    br = 0;
    if( bead->class == BEAD_LABEL ){
            page->usesym = ((bead_label*)bead)->sym;
    }else{
        Zoiks( ZOIKS_066 ); /* no entry point */
    }

    while( bead != page->code.end ) {
        if( bead->class == BEAD_USING ) {
            br = ((bead_using*)bead)->reg;
        }
        bead = bead->next;

    }
    return( br );
}

static void AddUsing( page_entry *page, bead_def *prev, char br ) {
/***Add Label if needed and using statement **/
    bead_def *start;

    while( page != NULL ) {
        start = page->code.start;
        if( start->class == BEAD_LABEL ){
            page->usesym = ((bead_label*)start)->sym;
        }else{
            page->usesym = HWMKPLabel( &prev->next );
            start = prev->next;
            start->address = page->code.start_addr;
            page->code.start = start;
        }
        HWMKUsing( &start->next, page->usesym, br );
        prev = page->code.end;
        page = page->next;

    }
}

static void DoLongJmps( page_entry *page, page_entry *head, char br ) {
/***Dump out long branches to far away places*/
    sym_list *lsyms;
    hw_sym   *jmplabel;
    hw_sym   *basesym;
    bead_def *jmpvec;
    int       jmpdisp;

    lsyms = page->refs.lsyms;
    jmpvec = page->code.end;
    if( !(jmpvec->class == BEAD_BR &&((bead_hwins_rx *)jmpvec)->r1 == 15 )){
      /* need branch to next page */
        if( page->next != NULL ) {
            basesym = page->next->usesym;
            AddLoadBase( &jmpvec->next, basesym, &page->pool, br );
            jmpvec = jmpvec->next;
            AddBCR( &jmpvec->next, br );
            jmpvec = jmpvec->next;
        }
    }
    if( lsyms != NULL ) {
        jmplabel = HWMKPLabel( &jmpvec->next );
        jmpvec = jmpvec->next;
    }
    jmpdisp = 0;
    while( lsyms != NULL ) {
        if( !lsyms->defined ) {
            basesym = GetBaseFor(  lsyms->sym, head );
            IndirectRefs( lsyms->sym, &page->code, jmplabel, jmpdisp );
            AddLoadBase( &jmpvec->next, basesym, &page->pool, br );
            jmpvec = jmpvec->next;
            AddFarJmp( &jmpvec->next, lsyms->sym, basesym, br );
            jmpvec = jmpvec->next;
            jmpdisp += PAGE_JMP_COST;
        }
        lsyms = lsyms->next;
    }
    page->code.end = jmpvec;
}

static void DoIndexJmps( page_entry *page, page_entry *head, char br ) {
/***Fixup index table for index jumps*************************/
    bindex_list *bri_list;
    bead_def    *table;
    bead_bindex *bri;
    bool        br_load;

    bri_list = page->bri_list;
    while( bri_list != NULL ) {
        bri = bri_list->bri;
        bri->br = br;
        table = bri->table->def;
        br_load = UpdateDisps(  table, page->usesym, head );
        ExpandBri( bri, br_load);
        bri_list = bri_list->next;
    }
}

static void AddFarJmp( bead_def **at, hw_sym *sym, hw_sym *base, char br  ) {
    hwins_op_any  dst;

    dst.sx.ref = HWDispRef( sym, base );
    dst.sx.disp = 0;
    dst.sx.a = 0;
    dst.sx.b = br;
    HWMKBRGen( at, 15,  &dst );
}

static void AddBCR( bead_def **at, char br  ) {
/*** to A BCR  br *****************************/
    hwins_op_any  cc;
    hwins_op_any  dst;

    cc.r = 15;
    dst.r = br;
    HWMKInsGen( at, HWOP_BCR, &cc, &dst, NULL );
}

static void AddLoadBase( bead_def **at,   hw_sym *sym,
                         lit_pool  *pool, char    br  ) {

    hwins_op_any   hwop1;
    hwins_op_any   hwop2;

    hwop1.r = br;
    hwop2.sx.ref = MakeLitAddr( pool, sym );
    hwop2.sx.disp = 0;
    hwop2.sx.a = 0;
    hwop2.sx.b = 0;
    HWMKInsGen( at, HWOP_L, &hwop1,  &hwop2, NULL );
}

static ref_lit *MakeLitAddr( lit_pool *pool, hw_sym *sym ) {
/*** Add litaddr of sym to pool ***************************/
    ref_lit       *lit;
    bead_def      *litdef;

    lit = HWLitAddr( sym, 0, FALSE );
    lit->common.next = NULL;
    litdef = FindLit( pool->head, lit->val );
    if( litdef != NULL ) {
        lit->def = litdef;
    }else { /* then value is def */
        litdef = lit->val;
        litdef->next = NULL;
        lit->def = litdef;
        *pool->end_lnk = litdef;
        pool->end = litdef;
        pool->end_lnk = &litdef->next;
    }
    return( lit );
  }

static hw_sym *GetBaseFor( hw_sym *sym, page_entry *page_list ) {
/* find the using sym for page where sym is defined in */
    offset address;

    address = sym->def->address;
    while( address > page_list->code.end_addr  ) {
        page_list = page_list->next;
    }
    return( page_list->usesym );
}

static void IndirectRefs( hw_sym *sym,   code_entry *code,
                          hw_sym *label, int         disp   ) {
/** Adjust refs of symbol in page to indirect to jmp table */
    ref_sym  *refs;
    ref_sym  **end_lnk;
    bead_def *use;

    end_lnk = &sym->refs;
    refs = *end_lnk;
    while( refs != NULL ) {
        use = refs->use;
        if( use->address >= code->start_addr
         && use->address < code->end_addr  ) {
             *end_lnk = refs->common.next;
             refs->sym = label;
             refs->common.next = label->refs;
             label->refs = refs;
             ((bead_hwins_rx*)use)->s2.disp = disp;
        }else {
            end_lnk  = &refs->common.next;
        }
        refs = *end_lnk;
    }

}

static void DoLits( lit_pool *pool, bead_def *end ) {
/** Dump literals out************************/
    bead_ltorg *ltorg;

    if( pool->head != NULL ) {
        ltorg = _Alloc( ltorg, sizeof( *ltorg ) );
        ltorg->common.class = BEAD_LTORG;
        *pool->end_lnk = NULL; /* snip pool at end */
        ltorg->align = SortLitPool( pool );
        *pool->end_lnk = end->next; /* link to rest of beads */
        ltorg->common.next = pool->head;
        ltorg->end = pool->end;
        end->next = (bead_def*)ltorg;
    }
}


static bool UpdateDisps( bead_def *table, hw_sym *curr_base, page_entry *head ){
/*** Update disp addr with base symbol where table used **/
    hw_sym  *base;
    bool    expand;
    bead_disp *disp;
    bead_disp *bead;

    expand = FALSE;
    disp = (bead_disp *)table->next;
    while( disp != NULL && disp->common.class == BEAD_DISP ) {
        base = GetBaseFor( disp->ref, head );
        disp->base = base;
        if( curr_base != base ) {
            expand = TRUE;
        }
        disp = (bead_disp *)disp->common.next;
    }
    if( expand ) {
        disp = (bead_disp *)table->next;
        while( disp != NULL && disp->common.class == BEAD_DISP ) {
            _Alloc( bead, sizeof( *bead ) );
            bead->common.class = BEAD_DISP;
            bead->val = 0;
            bead->ref =  disp->base;
            bead->base = curr_base;
            bead->op_len = DISP_SUB|2;
            bead->common.next = (bead_def *)disp;
            table->next = (bead_def *)bead;
            table = (bead_def *)disp;
            disp = (bead_disp *)disp->common.next;
        }
    }
    return( expand );
}

static void ExpandBri( bead_bindex *bri, bool br_load){
/**** Expand Index macro into AH's and branches**/
    bead_def     *curr_ins;
    hwins_op_any hwop1;
    hwins_op_any hwop2;

    curr_ins = (bead_def *)bri;
    hwop1.r = bri->reg;
    if( br_load ) {
        HWMKInsGen( &curr_ins->next, HWOP_AR, &hwop1, &hwop1, NULL );
        curr_ins = curr_ins->next;
    }
    hwop2.sx.ref = bri->lit;
    hwop2.sx.disp = 0;
    hwop2.sx.a = 0;
    hwop2.sx.b = 0;
    HWMKInsGen( &curr_ins->next, HWOP_A, &hwop1, &hwop2, NULL );
    curr_ins = curr_ins->next;
    if( br_load ) {
        hwop1.r = bri->br;
        hwop2.sx.b = bri->reg;
        hwop2.sx.ref  = NULL;
        hwop2.sx.a = 0;
        hwop2.sx.disp = 0;
        HWMKInsGen( &curr_ins->next, HWOP_AH, &hwop1, &hwop2, NULL );
        curr_ins = curr_ins->next;
        hwop2.sx.disp = 2;
    }else{
        hwop2.sx.disp = 0;
    }
    hwop1.r = bri->reg;
    hwop2.sx.b = bri->reg;
    hwop2.sx.ref  = NULL;
    hwop2.sx.a = 0;
    HWMKInsGen( &curr_ins->next, HWOP_LH, &hwop1, &hwop2, NULL );
    curr_ins = curr_ins->next;
    hwop2.sx.ref = NULL;
    hwop2.sx.disp = 0;
    hwop2.sx.a = bri->reg;
    hwop2.sx.b = bri->br;
    HWMKBRGen( &curr_ins->next, 15,  &hwop2 );
    bri->size = 0;
}

static page_entry *PageInit( bead_def *bead ) {
/**** Init page entry to start state *********/
    page_entry *page;

    _Alloc( page, sizeof( *page ) );
    page->next = NULL;
    page->size = 8; /* lit pool alignment adjustment */
    page->usesym = NULL;
    page->code.start = bead;
    page->code.start_addr = bead->address;
    page->code.end = bead;
    page->code.end_addr = bead->address;
    page->refs.frefs = 0;
    page->refs.brefs = 0;
    page->refs.lsyms = NULL;
    page->pool.head = NULL;
    page->pool.end = NULL;
    page->pool.end_lnk = &page->pool.head;
    page->pool.size = 8;  /* lit pool adjustment */
    page->bri_list = NULL;
    return( page );
}

static void FreePages( page_entry *page ) {
/*****************************************
    Free a page and all it's trash
*/

    while( page != NULL ){
        page_entry *next;
        /*** free syms ***/
        {
            sym_list          *lsyms, *next;

            for( lsyms = page->refs.lsyms; lsyms != NULL; lsyms = next ){
                next = lsyms->next;
                _Free( lsyms, sizeof( *lsyms ) );
            }
        }
        /*** free index branch ***/
        {
            bindex_list *bri_list, *next;

            for( bri_list = page->bri_list; bri_list != NULL; bri_list = next ){
                next = bri_list->next;
                _Free( bri_list, sizeof( *bri_list ) );
            }
        }

        next = page->next;
        _Free( page, sizeof( *page ) );
        page = next;
    }
}

extern void HWShortRef( bead_startproc *list ){
/**********************************************
 convert any L r,=(A) to LA r,A if in range
*/
#if 0
    bead_def *bead, *endproc, **lnk;
    ref_lit  *lit;
    bead_def *litdef;
    hw_sym *using;

    using = NULL;
    while(  list != NULL ){
        lnk = &list->common.next;
        endproc = (bead_def *)list->endproc;
        while( (bead = *lnk) != endproc ){
            if( bead->class == BEAD_USING ) {
                using = ((bead_using*)bead->sym;
            }else if( bead->class == BEAD_HWINS ) {
                if( ((any_bead_hwins*)bead)->ins.op == HWOP_L ){
                    lit = GetLit( (any_bead_hwins *) bead );
                    litdef = lit->value;
                    if( litdef->class == BEAD_ADDR ){
                      InRange( using->sym, (bead_addr*)litdef, bead );
                    }
                }
            }
            lnk = &bead->next;
        }
        list = list->prev;
    }
#endif
}
#if 0
static void InRange( hw_sym *base, bead_addr *acon, bead_hwins_rx *ins ){
/****************************************************
    is the acon in range of base sym so we can do a LA
*/
    hw_sym *sym;

    sym = acon->ref;
    if( sym->class != HW_EXTERN ){
    }
}
#endif

⌨️ 快捷键说明

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