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