237 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
 | 
						|
/* M I S C E L L A N E O U S   U T I L I T I E S */
 | 
						|
 | 
						|
/* $Header$ */
 | 
						|
 | 
						|
/*	Code for the allocation and de-allocation of temporary variables,
 | 
						|
	allowing re-use.
 | 
						|
*/
 | 
						|
 | 
						|
#include	<em.h>
 | 
						|
#include	<em_reg.h>
 | 
						|
#include	<alloc.h>
 | 
						|
#include	<em_mes.h>
 | 
						|
 | 
						|
#include	"lint.h"
 | 
						|
#include	"util.h"
 | 
						|
#include	"use_tmp.h"
 | 
						|
#include	"regcount.h"
 | 
						|
#include	"sizes.h"
 | 
						|
#include	"align.h"
 | 
						|
#include	"stack.h"
 | 
						|
#include	"Lpars.h"
 | 
						|
#include	"def.h"
 | 
						|
 | 
						|
static struct localvar	*FreeTmps;
 | 
						|
#ifdef USE_TMP
 | 
						|
static int	loc_id;
 | 
						|
#endif USE_TMP
 | 
						|
 | 
						|
#ifdef PEEPHOLE
 | 
						|
#undef REGCOUNT
 | 
						|
#define REGCOUNT 1
 | 
						|
#endif
 | 
						|
 | 
						|
extern char options[];
 | 
						|
 | 
						|
LocalInit()
 | 
						|
{
 | 
						|
#ifdef USE_TMP
 | 
						|
	C_insertpart(loc_id = C_getid());
 | 
						|
#endif USE_TMP
 | 
						|
}
 | 
						|
 | 
						|
arith
 | 
						|
LocalSpace(sz, al)
 | 
						|
	arith sz;
 | 
						|
{
 | 
						|
	register struct stack_level *stl = local_level;
 | 
						|
 | 
						|
	stl->sl_max_block = - align(sz - stl->sl_max_block, al);
 | 
						|
	return stl->sl_max_block;
 | 
						|
}
 | 
						|
 | 
						|
#define TABSIZ 32
 | 
						|
static struct localvar *regs[TABSIZ];
 | 
						|
 | 
						|
arith
 | 
						|
NewLocal(sz, al, regtype, sc)
 | 
						|
	arith sz;
 | 
						|
{
 | 
						|
	register struct localvar *tmp = FreeTmps;
 | 
						|
	struct localvar *prev = 0;
 | 
						|
	register int index;
 | 
						|
 | 
						|
	while (tmp) {
 | 
						|
		if (tmp->t_align >= al &&
 | 
						|
		    tmp->t_size >= sz &&
 | 
						|
		    tmp->t_sc == sc &&
 | 
						|
		    tmp->t_regtype == regtype) {
 | 
						|
			if (prev) {
 | 
						|
				prev->next = tmp->next;
 | 
						|
			}
 | 
						|
			else	FreeTmps = tmp->next;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		prev = tmp;
 | 
						|
		tmp = tmp->next;
 | 
						|
	}
 | 
						|
	if (! tmp) {
 | 
						|
		tmp = new_localvar();
 | 
						|
		tmp->t_offset = LocalSpace(sz, al);
 | 
						|
		tmp->t_align = al;
 | 
						|
		tmp->t_size = sz;
 | 
						|
		tmp->t_sc = sc;
 | 
						|
		tmp->t_regtype = regtype;
 | 
						|
		tmp->t_count = REG_DEFAULT;
 | 
						|
	}
 | 
						|
	index = (int) (tmp->t_offset >> 2) & (TABSIZ - 1);
 | 
						|
	tmp->next = regs[index];
 | 
						|
	regs[index] = tmp;
 | 
						|
	return tmp->t_offset;
 | 
						|
}
 | 
						|
 | 
						|
FreeLocal(off)
 | 
						|
	arith off;
 | 
						|
{
 | 
						|
	int index = (int) (off >> 2) & (TABSIZ - 1);
 | 
						|
	register struct localvar *tmp = regs[index];
 | 
						|
	struct localvar *prev = 0;
 | 
						|
 | 
						|
	while (tmp && tmp->t_offset != off) {
 | 
						|
		prev = tmp;
 | 
						|
		tmp = tmp->next;
 | 
						|
	}
 | 
						|
	if (tmp) {
 | 
						|
		if (prev)	prev->next = tmp->next;
 | 
						|
		else		regs[index] = tmp->next;
 | 
						|
		tmp->next = FreeTmps;
 | 
						|
		FreeTmps = tmp;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
LocalFinish()
 | 
						|
{
 | 
						|
	register struct localvar *tmp, *tmp1;
 | 
						|
	register int i;
 | 
						|
 | 
						|
#ifdef USE_TMP
 | 
						|
	C_beginpart(loc_id);
 | 
						|
#endif
 | 
						|
	tmp = FreeTmps;
 | 
						|
	while (tmp) {
 | 
						|
		tmp1 = tmp;
 | 
						|
		if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
 | 
						|
		if (! options['n'] && tmp->t_regtype >= 0) {
 | 
						|
			C_ms_reg(tmp->t_offset, tmp->t_size, tmp->t_regtype, tmp->t_count);
 | 
						|
		}
 | 
						|
		tmp = tmp->next;
 | 
						|
		free_localvar(tmp1);
 | 
						|
	}
 | 
						|
	FreeTmps = 0;
 | 
						|
	for (i = 0; i < TABSIZ; i++) {
 | 
						|
		tmp = regs[i];
 | 
						|
		while (tmp) {
 | 
						|
			if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
 | 
						|
			tmp1 = tmp;
 | 
						|
			if (! options['n'] && tmp->t_regtype >= 0) {
 | 
						|
				C_ms_reg(tmp->t_offset,
 | 
						|
					 tmp->t_size,
 | 
						|
					 tmp->t_regtype,
 | 
						|
					 tmp->t_count);
 | 
						|
			}
 | 
						|
			tmp = tmp->next;
 | 
						|
			free_localvar(tmp1);
 | 
						|
		}
 | 
						|
		regs[i] = 0;
 | 
						|
	}
 | 
						|
	if (! options['n']) {
 | 
						|
		C_mes_begin(ms_reg);
 | 
						|
		C_mes_end();
 | 
						|
	}
 | 
						|
#ifdef USE_TMP
 | 
						|
	C_endpart(loc_id);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
RegisterAccount(offset, size, regtype, sc)
 | 
						|
	arith offset, size;
 | 
						|
{
 | 
						|
	register struct localvar *p;
 | 
						|
	int index;
 | 
						|
 | 
						|
	if (regtype < 0) return;
 | 
						|
 | 
						|
	p = new_localvar();
 | 
						|
	index = (int) (offset >> 2) & (TABSIZ - 1);
 | 
						|
	p->t_offset = offset;
 | 
						|
	p->t_regtype = regtype;
 | 
						|
	p->t_count = REG_DEFAULT;
 | 
						|
	p->t_sc = sc;
 | 
						|
	p->t_size = size;
 | 
						|
	p->next = regs[index];
 | 
						|
	regs[index] = p;
 | 
						|
}
 | 
						|
 | 
						|
static struct localvar *
 | 
						|
find_reg(off)
 | 
						|
	arith off;
 | 
						|
{
 | 
						|
	register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)];
 | 
						|
 | 
						|
	while (p && p->t_offset != off) p = p->next;
 | 
						|
	return p;
 | 
						|
}
 | 
						|
 | 
						|
LoadLocal(off, sz)
 | 
						|
	arith off, sz;
 | 
						|
{
 | 
						|
	register struct localvar *p = find_reg(off);
 | 
						|
 | 
						|
#ifdef USE_TMP
 | 
						|
#ifdef REGCOUNT
 | 
						|
	if (p) p->t_count++;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	if (sz == word_size) C_lol(off);
 | 
						|
	else if (sz == dword_size) C_ldl(off);
 | 
						|
	else {
 | 
						|
		if (p) p->t_regtype = -1;
 | 
						|
		C_lal(off);
 | 
						|
		C_loi(sz);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
StoreLocal(off, sz)
 | 
						|
	arith off, sz;
 | 
						|
{
 | 
						|
	register struct localvar *p = find_reg(off);
 | 
						|
 | 
						|
#ifdef USE_TMP
 | 
						|
#ifdef REGCOUNT
 | 
						|
	if (p) p->t_count++;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
	if (sz == word_size) C_stl(off);
 | 
						|
	else if (sz == dword_size) C_sdl(off);
 | 
						|
	else {
 | 
						|
		if (p) p->t_regtype = -1;
 | 
						|
		C_lal(off);
 | 
						|
		C_sti(sz);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#ifndef	LINT
 | 
						|
AddrLocal(off)
 | 
						|
	arith off;
 | 
						|
{
 | 
						|
	register struct localvar *p = find_reg(off);
 | 
						|
 | 
						|
	if (p) p->t_regtype = -1;
 | 
						|
	C_lal(off);
 | 
						|
}
 | 
						|
#endif	LINT
 |