home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
gcc-2.3.3-src.lha
/
GNU
/
src
/
amiga
/
gcc-2.3.3
/
config
/
vax.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-06
|
16KB
|
669 lines
/* Subroutines for insn-output.c for Vax.
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
/* This is like nonimmediate_operand with a restriction on the type of MEM. */
void
split_quadword_operands (operands, low, n)
rtx *operands, *low;
int n;
{
int i;
/* Split operands. */
low[0] = low[1] = low[2] = 0;
for (i = 0; i < 3; i++)
{
if (low[i])
/* it's already been figured out */;
else if (GET_CODE (operands[i]) == MEM
&& (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
{
rtx addr = XEXP (operands[i], 0);
operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
if (which_alternative == 0 && i == 0)
{
addr = XEXP (operands[i], 0);
operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
}
}
else
{
low[i] = operand_subword (operands[i], 0, 0, DImode);
operands[i] = operand_subword (operands[i], 1, 0, DImode);
}
}
}
print_operand_address (file, addr)
FILE *file;
register rtx addr;
{
register rtx reg1, reg2, breg, ireg;
rtx offset;
retry:
switch (GET_CODE (addr))
{
case MEM:
fprintf (file, "*");
addr = XEXP (addr, 0);
goto retry;
case REG:
fprintf (file, "(%s)", reg_names[REGNO (addr)]);
break;
case PRE_DEC:
fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
break;
case POST_INC:
fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
break;
case PLUS:
/* There can be either two or three things added here. One must be a
REG. One can be either a REG or a MULT of a REG and an appropriate
constant, and the third can only be a constant or a MEM.
We get these two or three things and put the constant or MEM in
OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
a register and can't tell yet if it is a base or index register,
put it into REG1. */
reg1 = 0; ireg = 0; breg = 0; offset = 0;
if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
|| GET_CODE (XEXP (addr, 0)) == MEM)
{
offset = XEXP (addr, 0);
addr = XEXP (addr, 1);
}
else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
|| GET_CODE (XEXP (addr, 1)) == MEM)
{
offset = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
else if (GET_CODE (XEXP (addr, 1)) == MULT)
{
ireg = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
else if (GET_CODE (XEXP (addr, 0)) == MULT)
{
ireg = XEXP (addr, 0);
addr = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (addr, 1)) == REG)
{
reg1 = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
else if (GET_CODE (XEXP (addr, 0)) == REG)
{
reg1 = XEXP (addr, 0);
addr = XEXP (addr, 1);
}
else
abort ();
if (GET_CODE (addr) == REG)
{
if (reg1)
ireg = addr;
else
reg1 = addr;
}
else if (GET_CODE (addr) == MULT)
ireg = addr;
else if (GET_CODE (addr) == PLUS)
{
if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
|| GET_CODE (XEXP (addr, 0)) == MEM)
{
if (offset)
{
if (GET_CODE (offset) == CONST_INT)
offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
else
abort ();
}
offset = XEXP (addr, 0);
}
else if (GET_CODE (XEXP (addr, 0)) == REG)
{
if (reg1)
ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
else
reg1 = XEXP (addr, 0);
}
else if (GET_CODE (XEXP (addr, 0)) == MULT)
{
if (ireg)
abort ();
ireg = XEXP (addr, 0);
}
else
abort ();
if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
|| GET_CODE (XEXP (addr, 1)) == MEM)
{
if (offset)
{
if (GET_CODE (offset) == CONST_INT)
offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
else
abort ();
}
offset = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (addr, 1)) == REG)
{
if (reg1)
ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
else
reg1 = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (addr, 1)) == MULT)
{
if (ireg)
abort ();
ireg = XEXP (addr, 1);
}
else
abort ();
}
else
abort ();
/* If REG1 is non-zero, figure out if it is a base or index register. */
if (reg1)
{
if (breg != 0 || (offset && GET_CODE (offset) == MEM))
{
if (ireg)
abort ();
ireg = reg1;
}
else
breg = reg1;
}
if (offset != 0)
output_address (offset);
if (breg != 0)
fprintf (file, "(%s)", reg_names[REGNO (breg)]);
if (ireg != 0)
{
if (GET_CODE (ireg) == MULT)
ireg = XEXP (ireg, 0);
if (GET_CODE (ireg) != REG)
abort ();
fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
}
break;
default:
output_addr_const (file, addr);
}
}
char *
rev_cond_name (op)
rtx op;
{
switch (GET_CODE (op))
{
case EQ:
return "neq";
case NE:
return "eql";
case LT:
return "geq";
case LE:
return "gtr";
case GT:
return "leq";
case GE:
return "lss";
case LTU:
return "gequ";
case LEU:
return "gtru";
case GTU:
return "lequ";
case GEU:
return "lssu";
default:
abort ();
}
}
int
vax_float_literal(c)
register rtx c;
{
register enum machine_mode mode;
int i;
union {double d; int i[2];} val;
if (GET_CODE (c) != CONST_DOUBLE)
return 0;
mode = GET_MODE (c);
if (c == const_tiny_rtx[(int) mode][0]
|| c == const_tiny_rtx[(int) mode][1]
|| c == const_tiny_rtx[(int) mode][2])
return 1;
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
val.i[0] = CONST_DOUBLE_LOW (c);
val.i[1] = CONST_DOUBLE_HIGH (c);
for (i = 0; i < 7; i ++)
if (val.d == 1 << i || val.d == 1 / (1 << i))
return 1;
#endif
return 0;
}
/* Return the cost in cycles of a memory address, relative to register
indirect.
Each of the following adds the indicated number of cycles:
1 - symbolic address
1 - pre-decrement
1 - indexing and/or offset(register)
2 - indirect */
int vax_address_cost(addr)
register rtx addr;
{
int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
rtx plus_op0 = 0, plus_op1 = 0;
restart:
switch (GET_CODE (addr))
{
case PRE_DEC:
predec = 1;
case REG:
case SUBREG:
case POST_INC:
reg = 1;
break;
case MULT:
indexed = 1; /* 2 on VAX 2 */
break;
case CONST_INT:
/* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
if (offset == 0)
offset = (unsigned)(INTVAL(addr)+128) > 256;
break;
case CONST:
case SYMBOL_REF:
offset = 1; /* 2 on VAX 2 */
break;
case LABEL_REF: /* this is probably a byte offset from the pc */
if (offset == 0)
offset = 1;
break;
case PLUS:
if (plus_op0)
plus_op1 = XEXP (addr, 0);
else
plus_op0 = XEXP (addr, 0);
addr = XEXP (addr, 1);
goto restart;
case MEM:
indir = 2; /* 3 on VAX 2 */
addr = XEXP (addr, 0);
goto restart;
}
/*