home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
kaffe-0.5p4-src.tgz
/
tar.out
/
contrib
/
kaffe
/
kaffevm
/
jit
/
basecode.c
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
7KB
|
410 lines
/*
* basecode.c
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, June 1996.
*/
#include <assert.h>
#include "gtypes.h"
#include "slots.h"
#include "seq.h"
#include "registers.h"
#include "icode.h"
#include "basecode.h"
#include "md.h"
#include "flags.h"
/* Modify references */
#define INCREF(_s) if ((_s) && (_s)->insn) { \
(_s)->insn->ref++; \
}
#define LINCREF(_s) if (_s) { \
if ((_s)[0].insn) { \
(_s)[0].insn->ref++; \
} \
if ((_s)[1].insn) { \
(_s)[1].insn->ref++; \
} \
}
#define ASSIGNSLOT(_d, _s) \
(_d).s.slot = (_s); \
(_d).s.seq = ((_s) ? (_s)->insn : 0)
#define LASSIGNSLOT(_d, _s) \
ASSIGNSLOT(_d, _s)
/*
* Optimise destination to remove any overwrites.
*/
#define OPTIMISE_WRITE(_d) if (flag_optimise) overwrite_optimise((_d)->insn)
/*
* Optimise operands to eliminate addition moves.
*/
#define OPTIMISE_READ(_s) if (flag_optimise) (_s) = move_optimise(_s)
static slots* move_optimise(slots*);
void overwrite_optimise(sequence*);
extern void nop(sequence*);
void
_slot_const_const(slots* dst, int s1, int s2, ifunc f, int type)
{
sequence* seq = nextSeq();
seq->u[1].iconst = s1;
seq->u[2].iconst = s2;
ASSIGNSLOT(seq->u[0], dst);
if (dst != 0) {
OPTIMISE_WRITE(dst);
dst->insn = seq;
}
seq->opt = USE_NO_SLOTS;
seq->type = type;
seq->func = f;
}
void
_slot_slot_const(slots* dst, slots* s1, int s2, ifunc f, int type)
{
sequence* seq;
#if defined(TWO_OPERAND)
slots* olddst = 0;
#endif
OPTIMISE_READ(s1);
#if defined(TWO_OPERAND)
/* Two operand systems cannot handle three operand ops.
* We need to fixit so the dst is one of the source ops.
*/
if (s1 != 0 && dst != 0) {
if (s1 != dst && type != Tload) {
move_any(dst, s1);
s1 = dst;
}
}
#endif
seq = nextSeq();
INCREF(s1);
ASSIGNSLOT(seq->u[1], s1);
seq->u[2].iconst = s2;
ASSIGNSLOT(seq->u[0], dst);
if (dst != 0) {
OPTIMISE_WRITE(dst);
dst->insn = seq;
}
seq->opt = USE_SLOT_1;
seq->type = type;
seq->func = f;
}
void
_slot_slot_fconst(slots* dst, slots* s1, double s2, ifunc f, int type)
{
sequence* seq = nextSeq();
OPTIMISE_READ(s1);
ASSIGNSLOT(seq->u[1], s1);
seq->u[2].fconst = s2;
ASSIGNSLOT(seq->u[0], dst);
INCREF(s1);
if (dst != 0) {
OPTIMISE_WRITE(dst);
dst->insn = seq;
}
seq->opt = USE_SLOT_1;
seq->type = type;
seq->func = f;
}
void
_slot_slot_slot(slots* dst, slots* s1, slots* s2, ifunc f, int type)
{
sequence* seq;
#if defined(TWO_OPERAND)
slots* olddst = 0;
#endif
OPTIMISE_READ(s1);
OPTIMISE_READ(s2);
#if defined(TWO_OPERAND)
/* Two operand systems cannot handle three operand ops.
* We need to fixit so the dst is one of the source ops.
*/
if (s1 != 0 && s2 != 0 && dst != 0) {
if (s2 == dst) {
olddst = dst;
slot_alloctmp(dst);
}
if (s1 != dst) {
move_any(dst, s1);
s1 = dst;
}
}
#endif
seq = nextSeq();
INCREF(s1);
INCREF(s2);
ASSIGNSLOT(seq->u[1], s1);
ASSIGNSLOT(seq->u[2], s2);
ASSIGNSLOT(seq->u[0], dst);
if (dst != 0) {
OPTIMISE_WRITE(dst);
dst->insn = seq;
}
seq->opt = USE_SLOT_12;
seq->type = type;
seq->func = f;
#if defined(TWO_OPERAND)
if (olddst != 0) {
move_any(olddst, dst);
}
#endif
}
void
_lslot_lslot_lslot(slots* dst, slots* s1, slots* s2, ifunc f, int type)
{
sequence* seq;
#if defined(TWO_OPERAND)
/* Two operand systems cannot handle three operand ops.
* We need to fixit so the dst is one of the source ops.
*/
slots* olddst = 0;
if (s1 != 0 && s2 != 0 && dst != 0) {
if (s2 == dst) {
olddst = dst;
slot_alloc2tmp(dst);
}
if (s1 != dst) {
move_anylong(dst, s1);
s1 = dst;
}
}
#endif
seq = nextSeq();
LASSIGNSLOT(seq->u[1], s1);
LASSIGNSLOT(seq->u[2], s2);
ASSIGNSLOT(seq->u[0], dst);
LINCREF(s1);
LINCREF(s2);
if (dst != 0) {
dst[0].insn = seq;
dst[1].insn = 0;
}
seq->opt = USE_NO_SLOTS;
seq->type = type;
seq->func = f;
if (olddst != 0) {
move_anylong(olddst, dst);
}
}
void
_lslot_lslot_slot(slots* dst, slots* s1, slots* s2, ifunc f, int type)
{
sequence* seq;
#if defined(TWO_OPERAND)
/* Two operand systems cannot handle three operand ops.
* We need to fixit so the dst is one of the source ops.
*/
slots* olddst = 0;
if (s1 != 0 && s2 != 0 && dst != 0) {
if (s2 == dst) {
olddst = dst;
slot_alloctmp(dst);
}
if (s1 != dst) {
move_any(dst, s1);
s1 = dst;
}
}
#endif
seq = nextSeq();
LASSIGNSLOT(seq->u[1], s1);
ASSIGNSLOT(seq->u[2], s2);
ASSIGNSLOT(seq->u[0], dst);
LINCREF(s1);
INCREF(s2);
if (dst != 0) {
dst[0].insn = seq;
dst[1].insn = 0;
}
seq->opt = USE_NO_SLOTS;
seq->type = type;
seq->func = f;
#if defined(TWO_OPERAND)
if (olddst != 0) {
move_any(olddst, dst);
}
#endif
}
void
_slot_slot_lslot(slots* dst, slots* s1, slots* s2, ifunc f, int type)
{
sequence* seq;
#if defined(TWO_OPERAND)
/* Two operand systems cannot handle three operand ops.
* We need to fixit so the dst is one of the source ops.
*/
slots* olddst = 0;
if (s1 != 0 && s2 != 0 && dst != 0) {
if (s2 == dst) {
olddst = dst;
slot_alloctmp(dst);
}
if (s1 != dst) {
move_any(dst, s1);
s1 = dst;
}
}
#endif
seq = nextSeq();
ASSIGNSLOT(seq->u[1], s1);
LASSIGNSLOT(seq->u[2], s2);
ASSIGNSLOT(seq->u[0], dst);
INCREF(s1);
LINCREF(s2);
if (dst != 0) {
dst->insn = seq;
}
seq->type = type;
seq->func = f;
#if defined(TWO_OPERAND)
if (olddst != 0) {
move_any(olddst, dst);
}
#endif
}
void
_lslot_slot_lconst(slots* dst, slots* s1, jlong s2, ifunc f, int type)
{
sequence* seq = nextSeq();
ASSIGNSLOT(seq->u[1], s1);
seq->u[2].lconst = s2;
ASSIGNSLOT(seq->u[0], dst);
INCREF(s1);
if (dst != 0) {
dst[0].insn = seq;
dst[1].insn = 0;
}
seq->opt = USE_NO_SLOTS;
seq->type = type;
seq->func = f;
}
void
_lslot_slot_fconst(slots* dst, slots* s1, double s2, ifunc f, int type)
{
sequence* seq = nextSeq();
ASSIGNSLOT(seq->u[1], s1);
seq->u[2].fconst = s2;
ASSIGNSLOT(seq->u[0], dst);
INCREF(s1);
if (dst != 0) {
dst[0].insn = seq;
dst[1].insn = 0;
}
seq->opt = USE_NO_SLOTS;
seq->type = type;
seq->func = f;
}
/*
* Optimise sources by removing move operations.
*/
static
slots*
move_optimise(slots* s)
{
sequence* nseq;
if (s == 0) {
return (s);
}
nseq = s->insn;
if (nseq == 0) {
return (s);
}
for (;;) {
if (nseq->type != Tcopy) {
return (s);
}
if (seq_seq(nseq, 2) == 0) {
return (s);
}
if (seq_slot(nseq, 2)->insn != seq_seq(nseq, 2)) {
return (s);
}
s = seq_slot(nseq, 2);
nseq = seq_seq(nseq, 2);
}
}
/*
* Optimise destinations by cancelling overwrites.
*/
void
overwrite_optimise(sequence* seq)
{
if (seq != 0 && --seq->ref == 0) {
if (SLOT_1(seq->opt)) {
overwrite_optimise(seq_seq(seq, 1));
}
if (SLOT_2(seq->opt)) {
overwrite_optimise(seq_seq(seq, 2));
}
}
}
/*
* Pop a sequence.
*/
void
seq_pop(sequence* seq)
{
seq->ref--;
if (seq->ref != 0) {
return;
}
if (SLOT_1(seq->opt) && seq_slot(seq, 1)) {
seq_slot(seq, 1)->insn = seq_seq(seq, 1);
}
if (SLOT_2(seq->opt) && seq_slot(seq, 2)) {
seq_slot(seq, 2)->insn = seq_seq(seq, 2);
}
}