ack/lang/cem/cemcom/util.c

238 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