s37page.c

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

C
928
字号
/****************************************************************************
*
*                            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 <stdio.h>
#include <string.h>
#include "standard.h"
#include "sysmacro.h"
#include "cg.h"
#include "cgaux.h"
#include "bckdef.h"
#include "offset.h"
#include "model.h"
#include "zoiks.h"
#include "s37bead.h"
#include "s37page.h"

#include "s37page.def"

extern offset HWCalcAddr(bead_def *,offset );
extern hw_sym *HWMKPLabel(bead_def **);
extern void HWMKUsing(bead_def **,hw_sym *,char );
extern void HWMKDrop(bead_def **,char );
extern ref_any *HWDispRef(hw_sym *,hw_sym *);
extern void HWMKBRGen(bead_def **,char ,hwins_op_any *);
extern void HWMKInsGen(bead_def **,hwins_opcode,
                                   hwins_op_any *,
                                   hwins_op_any *,
                                   hwins_op_any *);
extern ref_any *HWLitAddr( hw_sym *,offset,bool );
extern int HWLitAlign(bead_def *);

extern void HWMakePages( bead_def *bead ) {
/******* add long refs and literals **********/
    page_entry  *head;
    page_entry  *curr_page;
    page_entry  **end_ptr;
    char        br;

    for(;;){
        head = NULL;
        end_ptr = &head;
        while( bead != NULL ) {
            if(  bead->class == BEAD_STARTPROC) break;
            bead = bead->next;
        }
        if( bead == NULL )break;
        bead = bead->next;
        while( bead->class != BEAD_EPILOGUE ) {
            curr_page = PageInit( bead );
            *end_ptr = curr_page;
            end_ptr = &curr_page->next;
            bead = CollectPage( curr_page );
        }
        bead = CollectToEnd( curr_page, bead );
        if( head->next == NULL ){ /* small routine */
            bead = CollectSmall( bead, head );
            continue; /* either retry routine large or NULL */
        }
        br = FirstPage( head );
        AddUsing( head->next, head->code.end, br );
        CodePages( head, br );
        FreePages( head );
    }
}

static bead_def *CollectSmall( bead_def *bead, page_entry *head ) {
/***********************************************
    collect routines < PAGE_MAX with a floating LTORG
*/
    ltorg_entry lstack;
    bead_def    *startproc;
    char        br;

    InitLtorg( &lstack, head );
    for(;;){
        br = FirstPage( head );
        AddUsing( head->next, head->code.end, br );
        CodePages( head, br );
        FreePages( head );
        while( bead != NULL ) { /* tab to routine */
            if(  bead->class == BEAD_STARTPROC) break;
            bead = bead->next;
        }
        startproc = bead;
        if( bead == NULL )break; /* done */
        bead = bead->next;
        head = PageInit( bead );
        CopyPool( &head->pool, &lstack.pool ); /* inherit pool */
        head->size = lstack.pool.size; /* set starting size */
        bead = CollectPage( head );
        if( bead->class != BEAD_EPILOGUE ){ /* bigger than max */
            bead = startproc;
            break; /* collect big */
        }
        bead = CollectToEnd( head, bead );
        if( head->next != NULL ){
            /* EPILOGUE over */
            bead = startproc;
            FreePages( head );
            break; /* collect big */
        }
        FloatLtorg( &lstack, head );
        if( lstack.has_page == FALSE ){
         /* LTORG got dumped better start over*/
            bead = startproc;
            FreePages( head );
            break; /* collect big */
        }
    }
    if( lstack.has_page ){
       /*still have last page's lits */
        DumpFloatLtorg( &lstack );
    }
    return( bead );
}

static void InitLtorg( ltorg_entry *lstack, page_entry *page ){
/*************************************************************
 Init lstack with values to force FloatLtorg to copy page
 */
     lstack->prev_code = 0;
     lstack->code = page->code;
     CopyPool( &lstack->pool, &page->pool );
     lstack->has_page = TRUE;
     page->pool.head = NULL; /* won't get dumped by code pages */

 }

static void CopyPool( lit_pool *to, lit_pool *from ){
/*************************************************************
 Copy the from pool to to
 */
     *to = *from;
     if( to->head == NULL ){
         to->end_lnk = &to->head;
     }
 }

static void FloatLtorg( ltorg_entry *lstack, page_entry *page ){
/**********************************************************************
 Try to float the ltorg as long as possible so people won't gripe.
 If the current page  + accured lits puts starting code out of range
 dump lits. Lits currently are sorted by size cause IBM assembler does
 this could change so new lits are added to end.
 A stack isn't really needed for this scheme.
*/
    int  prev_code; /* size of previous code */

    prev_code = page->code.start_addr-lstack->code.start_addr;
    prev_code += lstack->prev_code; /* plus before it */
    if( prev_code+page->size > PAGE_MAX ){ /* current code plus lits */
        DumpFloatLtorg( lstack );
    }else{
        lstack->prev_code = prev_code;
        lstack->code = page->code;
        CopyPool( &lstack->pool, &page->pool );
        page->pool.head = NULL; /* won't get dumped by code pages */
    }
}

static void DumpFloatLtorg( ltorg_entry *lstack  ){
/************************************************
    dump ltorg at head
*/
    DoLits( &lstack->pool, lstack->code.end );
    lstack->prev_code = 0;
    lstack->has_page = FALSE;
}

static bead_def *CollectPage( page_entry *page ) {
/******* collect until a PAGE_MAX is         ****/
/******* or the base epilogue is reached     ****/
    int       size;
    bead_def *bead;
    bead_def *next;

    bead = page->code.start;
    next = bead->next;
    while( bead->class != BEAD_EPILOGUE ) {
    /* not dead on for size cause of alignment gaps */
        size = next->address - page->code.end_addr+page->size;
        if( size > PAGE_MAX ) break;
        page->size = size;
        if(  bead->class == BEAD_HWINS ) {
            if( ChkRefLit( page, (any_bead_hwins *)bead ) )break;
        }else if(  bead->class == BEAD_BR ) {
            if( ChkBrRef( page,(bead_hwins_rx  *) bead ) )break;
        }else if(  bead->class == BEAD_BINDEX ) {
            AddITab( page, (bead_bindex *) bead );
        }else if(  bead->class == BEAD_LABEL ) {
            ChkLabel( page, (bead_label *) bead );
        }
        page->code.end = bead;
        page->code.end_addr = next->address;
        bead = next;
        next = bead->next;
    }
//  printf( "total %d code %d lits %d \n", page->size,
//           page->code.end_addr - page->code.start->address,
//           page->pool.size );
    return( bead );
}

static bead_def *CollectToEnd( page_entry *page, bead_def *start ) {
/** If the epilogue fits on the last page stick it there else have  **/
/** it start on a page by itself,return ENDPROC bead                **/
    bead_def   *bead;
    bead_def   *last;
    page_entry *new;
    int         size;

    bead = start;
    while( bead->class != BEAD_ENDPROC ) {
        last = bead;
        bead = bead->next;
    }
    size = last->address - start->address;
    if( page->size + size <= PAGE_MAX
     && page->refs.frefs == 0 ) { /* can't have longrefs in epilogue*/
        page->size += size;
        page->code.end = last;
        page->code.end_addr = last->address;
    }else{
        new = PageInit( start );
        new->size = size;
        new->code.end = last;
        new->code.end_addr = last->address;
        page->next = new;
    }
    return( bead );
}

static bool ChkRefLit( page_entry *page, any_bead_hwins *bead ) {
/************ add lit to pool if not over PAGE_MAX **************/
    ref_lit  *lit;
    bead_def *litdef;
    bool     over;
    int      size;
    int      lit_size;

    over = FALSE;
    lit = GetLit( (any_bead_hwins *) bead );
    if( lit != NULL ) {
        lit->common.next = NULL;
        litdef = FindLit( page->pool.head, lit->val );
        if( litdef != NULL ) {
            lit->def = litdef;
        }else { /* then value is def */
            litdef = lit->val;
            litdef->next = NULL;
            lit_size =  HWCalcAddr( litdef, 0 );
            size = page->size + lit_size;
            if( size > PAGE_MAX ) {
                over = TRUE;
            }else {
                page->size = size;
                lit->def = litdef;
                *page->pool.end_lnk = litdef;
                page->pool.size += lit_size;
                page->pool.end = litdef;
                page->pool.end_lnk = &litdef->next;
            }
        }
    }
    return( over );
}

static bool ChkBrRef( page_entry *page, bead_hwins_rx *bead ) {
/***** check for long refs add if not over PAGE_MAX *****/
    bool      over;
    int       size;
    ref_sym  *ref;
    hw_sym   *sym;
    sym_list *lsyms;
    sym_list **link;

    over = FALSE;
    ref = bead->s2.ref;
    sym = ref->sym;
    link = &page->refs.lsyms;
    lsyms = *link;
    while( lsyms != NULL ) {
        if( lsyms->sym == sym )break;
        link  = &lsyms->next;
        lsyms = *link;
    }
    if( lsyms == NULL ) {
        size = page->size + PAGE_REF_COST;
        if( size > PAGE_MAX ) {
            over = TRUE;
        }else {
            page->size = size;
            page->refs.frefs++;
            _Alloc( lsyms, sizeof( *lsyms ) );
            lsyms->sym = sym;
            lsyms->next = NULL;
            lsyms->defined = FALSE;
            lsyms->frefs = 1;
            lsyms->brefs = 0;
            *link = lsyms;
        }
    }else {
        if( lsyms->defined ) {
            lsyms->brefs--;
            page->refs.brefs--;
        } else {
            lsyms->frefs++;
            page->refs.frefs++;
        }
    }

    return( over );
}

static void ChkLabel( page_entry *page, bead_label *bead ) {
/****** say sym is defined on sym list ***********/
    hw_sym   *sym;
    sym_list *lsyms;
    sym_list **link;

    sym = bead->sym;
    link = &page->refs.lsyms;
    lsyms = *link;
    while( lsyms != NULL ) {
        if( lsyms->sym == sym )break;
        link  = &lsyms->next;
        lsyms = *link;
    }
    if( lsyms == NULL ) {
        _Alloc( lsyms, sizeof( *lsyms ) );
        lsyms->sym = sym;
        lsyms->next = NULL;
        lsyms->frefs = 0;
        *link = lsyms;
    } else { /* subtract fref size cost and sym fref count */
        page->refs.frefs -= lsyms->frefs;
        page->size -= PAGE_REF_COST;
    }
    lsyms->brefs = CalcBackRefs( sym );
    page->refs.brefs += lsyms->brefs;
    lsyms->defined = TRUE;
 }

static void AddITab( page_entry *page, bead_bindex *bead ) {
/**** Add index table to table list ************************/
    bindex_list *new;
    ref_lit     *lit;
    bead_def *litdef;

    _Alloc( new, sizeof( *new ) );
    new->bri = bead;
    new->next = page->bri_list;
    page->bri_list = new;
    lit = bead->lit;
    litdef = lit->val;
    litdef->next = NULL;
    lit->def = litdef; /* lit only used by bindex */
    *page->pool.end_lnk = litdef;
    page->pool.size += 4; /* lit for table */
    page->pool.end_lnk = &litdef->next;
}

static bead_def *FindLit( bead_def *curr, bead_def *litval ) {
/***** Find equivalent bead in list or return NULL   ********/
    while( curr != NULL ) {
        if( curr->class == litval->class  ) {
            switch( curr->class ) {
            case BEAD_ADDR:
                if( ((bead_addr*) curr)->ref==((bead_addr *)litval)->ref
                &&  ((bead_addr*) curr)->val==((bead_addr *)litval)->val ) {
                return( curr );
                }
                break;
            case BEAD_INT:
                if( ((bead_int*) curr)->value==((bead_int *)litval)->value
                &&  ((bead_int*) curr)->size ==((bead_int *)litval)->size ) {
                return( curr );
                }
                break;
            case BEAD_FLT:
                if( ((bead_flt*) curr)->value==((bead_flt *)litval)->value
                &&  ((bead_flt*) curr)->size ==((bead_flt *)litval)->size ) {
                return( curr );
                }
                break;
            }
        }
        curr = curr->next;
    }
    return( curr );
}

static int  SortLitPool( lit_pool *pool ){
/**** sort the lit pool by D F H X alignment ***/
/**** return alignment                       ***/
    int i;
    int align;
    bead_def *list;
    struct { bead_def *head; bead_def **end_lnk;} cell[4];

    for( i = 0; i < 4; ++i ){
        cell[i].head = NULL;
        cell[i].end_lnk = &cell[i].head;
    }
    list = pool->head;
    while( list != NULL ){
        i = HWLitAlign( list );
        *cell[i].end_lnk = list;
        cell[i].end_lnk = &list->next;
        list = list->next;

    }
    list = NULL;
    for( i = 0; i < 4; ++i ){
        if( cell[i].head != NULL ){
            align = i;
            *cell[i].end_lnk = list;
            list = cell[i].head;
        }
    }
    pool->head = list;
    if( list != NULL ){
         while( list->next != NULL ){
             list = list->next;
         }
        pool->end = list;
        pool->end_lnk = &list->next;
    }
    return( 1<< align );
}

static ref_lit *GetLit( any_bead_hwins *bead ) {
/*******Assume one lit per bead************/
    hwins_op_sx  *op1;
    hwins_op_sx  *op2;

⌨️ 快捷键说明

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