#include "config.h"
#include "system.h"
#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "except.h"
#include "function.h"
#include "expr.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "recog.h"
#include "real.h"
#include "obstack.h"
#include "bitmap.h"
enum machine_mode byte_mode;
enum machine_mode word_mode;
enum machine_mode double_mode;
enum machine_mode ptr_mode;
int reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
static int label_num = 1;
static int first_label_num;
static int last_label_num;
static int base_label_num;
static int no_line_numbers;
#ifdef __GNUC__
#define FLDI , {{0}}
#else
#define FLDI
#endif
struct _global_rtl global_rtl =
{
{PC, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{CC0, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
{REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI },
};
rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
rtx const_true_rtx;
REAL_VALUE_TYPE dconst0;
REAL_VALUE_TYPE dconst1;
REAL_VALUE_TYPE dconst2;
REAL_VALUE_TYPE dconstm1;
rtx struct_value_rtx;
rtx struct_value_incoming_rtx;
rtx static_chain_rtx;
rtx static_chain_incoming_rtx;
rtx pic_offset_table_rtx;
rtx return_address_pointer_rtx;
struct rtx_def const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
static rtx first_insn = NULL;
static rtx last_insn = NULL;
tree sequence_rtl_expr = NULL;
static int cur_insn_uid = 1;
static int last_linenum = 0;
static char *last_filename = 0;
char *regno_pointer_flag;
int regno_pointer_flag_length;
char *regno_pointer_align;
rtx *regno_reg_rtx;
struct sequence_stack *sequence_stack;
#define SEQUENCE_RESULT_SIZE 5
static struct sequence_stack *sequence_element_free_list;
static rtx sequence_result[SEQUENCE_RESULT_SIZE];
static rtx free_insn;
extern int rtx_equal_function_value_matters;
extern char *emit_filename;
extern int emit_lineno;
static rtx make_jump_insn_raw PROTO((rtx));
static rtx make_call_insn_raw PROTO((rtx));
static rtx find_line_note PROTO((rtx));
rtx
gen_rtx_CONST_INT (mode, arg)
enum machine_mode mode;
HOST_WIDE_INT arg;
{
if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT)
return &const_int_rtx[arg + MAX_SAVED_CONST_INT];
#if STORE_FLAG_VALUE != 1 && STORE_FLAG_VALUE != -1
if (const_true_rtx && arg == STORE_FLAG_VALUE)
return const_true_rtx;
#endif
return gen_rtx_raw_CONST_INT (mode, arg);
}
rtx
gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2)
enum machine_mode mode;
rtx arg0;
HOST_WIDE_INT arg1, arg2;
{
rtx r = rtx_alloc (CONST_DOUBLE);
int i;
PUT_MODE (r, mode);
XEXP (r, 0) = arg0;
XEXP (r, 1) = NULL_RTX;
XWINT (r, 2) = arg1;
XWINT (r, 3) = arg2;
for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 3; --i)
XWINT (r, i) = 0;
return r;
}
rtx
gen_rtx_REG (mode, regno)
enum machine_mode mode;
int regno;
{
if (mode == Pmode && !reload_in_progress)
{
if (regno == FRAME_POINTER_REGNUM)
return frame_pointer_rtx;
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
if (regno == HARD_FRAME_POINTER_REGNUM)
return hard_frame_pointer_rtx;
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
if (regno == ARG_POINTER_REGNUM)
return arg_pointer_rtx;
#endif
#ifdef RETURN_ADDRESS_POINTER_REGNUM
if (regno == RETURN_ADDRESS_POINTER_REGNUM)
return return_address_pointer_rtx;
#endif
if (regno == STACK_POINTER_REGNUM)
return stack_pointer_rtx;
}
return gen_rtx_raw_REG (mode, regno);
}
rtx
gen_rtx_MEM (mode, addr)
enum machine_mode mode;
rtx addr;
{
rtx rt = gen_rtx_raw_MEM (mode, addr);
MEM_ALIAS_SET (rt) = 0;
return rt;
}
rtx
gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
{
#ifndef ANSI_PROTOTYPES
enum rtx_code code;
enum machine_mode mode;
#endif
va_list p;
register int i;
register char *fmt;
register rtx rt_val;
VA_START (p, mode);
#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum rtx_code);
mode = va_arg (p, enum machine_mode);
#endif
switch (code)
{
case CONST_INT:
rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT));
break;
case CONST_DOUBLE:
{
rtx arg0 = va_arg (p, rtx);
HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
HOST_WIDE_INT arg2 = va_arg (p, HOST_WIDE_INT);
rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2);
}
break;
case REG:
rt_val = gen_rtx_REG (mode, va_arg (p, int));
break;
case MEM:
rt_val = gen_rtx_MEM (mode, va_arg (p, rtx));
break;
default:
rt_val = rtx_alloc (code);
rt_val->mode = mode;
fmt = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++)
{
switch (*fmt++)
{
case '0':
break;
case 'i':
XINT (rt_val, i) = va_arg (p, int);
break;
case 'w':
XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
break;
case 's':
XSTR (rt_val, i) = va_arg (p, char *);
break;
case 'e':
case 'u':
XEXP (rt_val, i) = va_arg (p, rtx);
break;
case 'E':
XVEC (rt_val, i) = va_arg (p, rtvec);
break;
case 'b':
XBITMAP (rt_val, i) = va_arg (p, bitmap);
break;
case 't':
XTREE (rt_val, i) = va_arg (p, tree);
break;
default:
abort ();
}
}
break;
}
va_end (p);
return rt_val;
}
rtvec
gen_rtvec VPROTO((int n, ...))
{
#ifndef ANSI_PROTOTYPES
int n;
#endif
int i;
va_list p;
rtx *vector;
VA_START (p, n);
#ifndef ANSI_PROTOTYPES
n = va_arg (p, int);
#endif
if (n == 0)
return NULL_RTVEC;
vector = (rtx *) alloca (n * sizeof (rtx));
for (i = 0; i < n; i++)
vector[i] = va_arg (p, rtx);
va_end (p);
return gen_rtvec_v (n, vector);
}
rtvec
gen_rtvec_v (n, argp)
int n;
rtx *argp;
{
register int i;
register rtvec rt_val;
if (n == 0)
return NULL_RTVEC;
rt_val = rtvec_alloc (n);
for (i = 0; i < n; i++)
rt_val->elem[i].rtx = *argp++;
return rt_val;
}
rtvec
gen_rtvec_vv (n, argp)
int n;
rtunion *argp;
{
register int i;
register rtvec rt_val;
if (n == 0)
return NULL_RTVEC;
rt_val = rtvec_alloc (n);
for (i = 0; i < n; i++)
rt_val->elem[i].rtx = (argp++)->rtx;
return rt_val;
}
rtx
gen_reg_rtx (mode)
enum machine_mode mode;
{
register rtx val;
if (no_new_pseudos)
abort ();
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
|| GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
{
rtx realpart, imagpart;
int size = GET_MODE_UNIT_SIZE (mode);
enum machine_mode partmode
= mode_for_size (size * BITS_PER_UNIT,
(GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
? MODE_FLOAT : MODE_INT),
0);
realpart = gen_reg_rtx (partmode);
imagpart = gen_reg_rtx (partmode);
return gen_rtx_CONCAT (mode, realpart, imagpart);
}
if (reg_rtx_no == regno_pointer_flag_length)
{
rtx *new1;
char *new =
(char *) savealloc (regno_pointer_flag_length * 2);
bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
regno_pointer_flag = new;
new = (char *) savealloc (regno_pointer_flag_length * 2);
bcopy (regno_pointer_align, new, regno_pointer_flag_length);
bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
regno_pointer_align = new;
new1 = (rtx *) savealloc (regno_pointer_flag_length * 2 * sizeof (rtx));
bcopy ((char *) regno_reg_rtx, (char *) new1,
regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) &new1[regno_pointer_flag_length],
regno_pointer_flag_length * sizeof (rtx));
regno_reg_rtx = new1;
regno_pointer_flag_length *= 2;
}
val = gen_rtx_raw_REG (mode, reg_rtx_no);
regno_reg_rtx[reg_rtx_no++] = val;
return val;
}
void
mark_user_reg (reg)
rtx reg;
{
if (GET_CODE (reg) == CONCAT)
{
REG_USERVAR_P (XEXP (reg, 0)) = 1;
REG_USERVAR_P (XEXP (reg, 1)) = 1;
}
else if (GET_CODE (reg) == REG)
REG_USERVAR_P (reg) = 1;
else
abort ();
}
void
mark_reg_pointer (reg, align)
rtx reg;
int align;
{
if (! REGNO_POINTER_FLAG (REGNO (reg)))
{
REGNO_POINTER_FLAG (REGNO (reg)) = 1;
if (align)
REGNO_POINTER_ALIGN (REGNO (reg)) = align;
}
else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg)))
REGNO_POINTER_ALIGN (REGNO (reg)) = align;
}
int
max_reg_num ()
{
return reg_rtx_no;
}
int
max_label_num ()
{
if (last_label_num && label_num == base_label_num)
return last_label_num;
return label_num;
}
int
get_first_label_num ()
{
return first_label_num;
}
rtx
gen_lowpart_common (mode, x)
enum machine_mode mode;
register rtx x;
{
int word = 0;
if (GET_MODE (x) == mode)
return x;
if (GET_MODE (x) != VOIDmode
&& ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
> ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
/ UNITS_PER_WORD)))
return 0;
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
word = ((GET_MODE_SIZE (GET_MODE (x))
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD);
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT))
{
if (GET_MODE (XEXP (x, 0)) == mode)
return XEXP (x, 0);
else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
return gen_lowpart_common (mode, XEXP (x, 0));
else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
else if (GET_CODE (x) == SUBREG
&& (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
|| GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
? SUBREG_REG (x)
: gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + word));
else if (GET_CODE (x) == REG)
{
if (WORDS_BIG_ENDIAN && REGNO (x) < FIRST_PSEUDO_REGISTER)
word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
- HARD_REGNO_NREGS (REGNO (x), mode));
if (REGNO (x) < FIRST_PSEUDO_REGISTER
&& ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)
&& HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
return 0;
else if (REGNO (x) < FIRST_PSEUDO_REGISTER
&& (! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
#ifdef CLASS_CANNOT_CHANGE_SIZE
&& ! (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (x))
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_FLOAT
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
REGNO (x))))
#endif
&& x != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& x != arg_pointer_rtx
#endif
&& x != stack_pointer_rtx)
return gen_rtx_REG (mode, REGNO (x) + word);
else
return gen_rtx_SUBREG (mode, x, word);
}
else if ((GET_MODE_CLASS (mode) == MODE_INT
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
&& GET_MODE (x) == VOIDmode
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
{
if (GET_MODE_BITSIZE (mode) >= 2 * HOST_BITS_PER_WIDE_INT)
return x;
else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
return 0;
else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
return (GET_CODE (x) == CONST_INT ? x
: GEN_INT (CONST_DOUBLE_LOW (x)));
else
{
int width = GET_MODE_BITSIZE (mode);
HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)
: CONST_DOUBLE_LOW (x));
val = val << (HOST_BITS_PER_WIDE_INT - width) >> (HOST_BITS_PER_WIDE_INT - width);
return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x
: GEN_INT (val));
}
}
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_CODE (x) == CONST_INT
&& sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)
#ifdef REAL_ARITHMETIC
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i;
i = INTVAL (x);
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
#else
{
union {HOST_WIDE_INT i; float d; } u;
u.i = INTVAL (x);
return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
}
#endif
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
&& GET_MODE (x) == VOIDmode
&& (sizeof (double) * HOST_BITS_PER_CHAR
== 2 * HOST_BITS_PER_WIDE_INT))
#ifdef REAL_ARITHMETIC
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i[2];
HOST_WIDE_INT low, high;
if (GET_CODE (x) == CONST_INT)
low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
else
low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
if (WORDS_BIG_ENDIAN)
i[0] = high, i[1] = low;
else
i[0] = low, i[1] = high;
r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
#else
{
union {HOST_WIDE_INT i[2]; double d; } u;
HOST_WIDE_INT low, high;
if (GET_CODE (x) == CONST_INT)
low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
else
low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
#ifdef HOST_WORDS_BIG_ENDIAN
u.i[0] = high, u.i[1] = low;
#else
u.i[0] = low, u.i[1] = high;
#endif
return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
}
#endif
#ifdef REAL_ARITHMETIC
else if (mode == SFmode && GET_CODE (x) == CONST_INT)
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i;
i = INTVAL (x);
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_CODE (x) == CONST_INT
&& (sizeof (double) * HOST_BITS_PER_CHAR
== HOST_BITS_PER_WIDE_INT))
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i;
i = INTVAL (x);
r = REAL_VALUE_FROM_TARGET_DOUBLE (&i);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
#endif
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& (GET_MODE_CLASS (mode) == MODE_INT
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
&& GET_CODE (x) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
return operand_subword (x, word, 0, GET_MODE (x));
else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& (GET_MODE_CLASS (mode) == MODE_INT
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
&& GET_CODE (x) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
{
rtx lowpart
= operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));
rtx highpart
= operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
if (lowpart && GET_CODE (lowpart) == CONST_INT
&& highpart && GET_CODE (highpart) == CONST_INT)
return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
}
return 0;
}
rtx
gen_realpart (mode, x)
enum machine_mode mode;
register rtx x;
{
if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)
return XEXP (x, 0);
else if (WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
&& REG_P (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
fatal ("Unable to access real part of complex value in a hard register on this target");
else if (WORDS_BIG_ENDIAN)
return gen_highpart (mode, x);
else
return gen_lowpart (mode, x);
}
rtx
gen_imagpart (mode, x)
enum machine_mode mode;
register rtx x;
{
if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)
return XEXP (x, 1);
else if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
else if (!WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
&& REG_P (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
fatal ("Unable to access imaginary part of complex value in a hard register on this target");
else
return gen_highpart (mode, x);
}
int
subreg_realpart_p (x)
rtx x;
{
if (GET_CODE (x) != SUBREG)
abort ();
return SUBREG_WORD (x) * UNITS_PER_WORD < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x)));
}
rtx
gen_lowpart (mode, x)
enum machine_mode mode;
register rtx x;
{
rtx result = gen_lowpart_common (mode, x);
if (result)
return result;
else if (GET_CODE (x) == REG)
{
result = gen_lowpart_common (mode, copy_to_reg (x));
if (result == 0)
abort ();
return result;
}
else if (GET_CODE (x) == MEM)
{
register int offset = 0;
if (WORDS_BIG_ENDIAN)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
}
else if (GET_CODE (x) == ADDRESSOF)
return gen_lowpart (mode, force_reg (GET_MODE (x), x));
else
abort ();
}
rtx
gen_highpart (mode, x)
enum machine_mode mode;
register rtx x;
{
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
abort ();
if (GET_CODE (x) == CONST_DOUBLE
#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT
#endif
)
return GEN_INT (CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode));
else if (GET_CODE (x) == CONST_INT)
{
if (HOST_BITS_PER_WIDE_INT <= BITS_PER_WORD)
return const0_rtx;
return GEN_INT (INTVAL (x) >> (HOST_BITS_PER_WIDE_INT - BITS_PER_WORD));
}
else if (GET_CODE (x) == MEM)
{
register int offset = 0;
if (! WORDS_BIG_ENDIAN)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
if (! BYTES_BIG_ENDIAN
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
offset -= (GET_MODE_SIZE (mode)
- MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (x))));
return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
}
else if (GET_CODE (x) == SUBREG)
{
if (SUBREG_WORD (x) != 0)
abort ();
return gen_highpart (mode, SUBREG_REG (x));
}
else if (GET_CODE (x) == REG)
{
int word;
if (WORDS_BIG_ENDIAN)
word = 0;
else if (REGNO (x) < FIRST_PSEUDO_REGISTER)
word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
- HARD_REGNO_NREGS (REGNO (x), mode));
else
word = ((GET_MODE_SIZE (GET_MODE (x))
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD);
if (REGNO (x) < FIRST_PSEUDO_REGISTER
&& (! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
&& x != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& x != arg_pointer_rtx
#endif
&& x != stack_pointer_rtx)
return gen_rtx_REG (mode, REGNO (x) + word);
else
return gen_rtx_SUBREG (mode, x, word);
}
else
abort ();
}
int
subreg_lowpart_p (x)
rtx x;
{
if (GET_CODE (x) != SUBREG)
return 1;
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
return 0;
if (WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
return (SUBREG_WORD (x)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
/ UNITS_PER_WORD));
return SUBREG_WORD (x) == 0;
}
rtx
operand_subword (op, i, validate_address, mode)
rtx op;
int i;
int validate_address;
enum machine_mode mode;
{
HOST_WIDE_INT val;
int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
int bits_per_word = BITS_PER_WORD;
if (mode == VOIDmode)
mode = GET_MODE (op);
if (mode == VOIDmode)
abort ();
if (mode != BLKmode
&& (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
return 0;
if (mode != BLKmode
&& (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
return const0_rtx;
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
if (GET_CODE (op) == REG)
{
if (REGNO (op) < FIRST_PSEUDO_REGISTER
&& REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
return 0;
if (REGNO (op) < FIRST_PSEUDO_REGISTER
&& (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
|| ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
return 0;
else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| (REG_FUNCTION_VALUE_P (op)
&& rtx_equal_function_value_matters)
|| op == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| op == arg_pointer_rtx
#endif
|| op == stack_pointer_rtx)
return gen_rtx_SUBREG (word_mode, op, i);
else
return gen_rtx_REG (word_mode, REGNO (op) + i);
}
else if (GET_CODE (op) == SUBREG)
return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));
else if (GET_CODE (op) == CONCAT)
{
int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
if (i < partwords)
return operand_subword (XEXP (op, 0), i, validate_address, mode);
return operand_subword (XEXP (op, 1), i - partwords,
validate_address, mode);
}
if (GET_CODE (op) == MEM)
{
rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);
rtx new;
if (validate_address)
{
if (reload_completed)
{
if (! strict_memory_address_p (word_mode, addr))
return 0;
}
else
addr = memory_address (word_mode, addr);
}
new = gen_rtx_MEM (word_mode, addr);
MEM_COPY_ATTRIBUTES (new, op);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
return new;
}
#ifdef REAL_ARITHMETIC
if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 64
&& GET_CODE (op) == CONST_DOUBLE)
{
long k[2];
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
if (BITS_PER_WORD == 32)
{
val = k[i];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
#if HOST_BITS_PER_WIDE_INT >= 64
else if (BITS_PER_WORD >= 64 && i == 0)
{
val = k[! WORDS_BIG_ENDIAN];
val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
val |= (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN] & 0xffffffff;
return GEN_INT (val);
}
#endif
else if (BITS_PER_WORD == 16)
{
val = k[i >> 1];
if ((i & 1) == !WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
return GEN_INT (val);
}
else
abort ();
}
else if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) > 64
&& GET_CODE (op) == CONST_DOUBLE)
{
long k[4];
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
if (BITS_PER_WORD == 32)
{
val = k[i];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
else
abort ();
}
#else
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& GET_CODE (op) == CONST_DOUBLE)
{
#ifdef HOST_WORDS_BIG_ENDIAN
return GEN_INT (i == WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#else
return GEN_INT (i != WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#endif
}
#endif
#ifdef REAL_ARITHMETIC
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 32
&& GET_CODE (op) == CONST_DOUBLE)
{
long l;
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, l);
val = l;
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
if (BITS_PER_WORD == 16)
{
if ((i & 1) == !WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
}
return GEN_INT (val);
}
#else
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& sizeof (float) * 8 == HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_CODE (op) == CONST_DOUBLE)
{
double d;
union {float f; HOST_WIDE_INT i; } u;
REAL_VALUE_FROM_CONST_DOUBLE (d, op);
u.f = d;
return GEN_INT (u.i);
}
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
&& sizeof (double) * 8 == HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_CODE (op) == CONST_DOUBLE)
{
double d;
union {double d; HOST_WIDE_INT i; } u;
REAL_VALUE_FROM_CONST_DOUBLE (d, op);
u.d = d;
return GEN_INT (u.i);
}
#endif
if (op == const0_rtx)
return op;
if (GET_MODE_CLASS (mode) != MODE_INT
|| (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)
|| BITS_PER_WORD > HOST_BITS_PER_WIDE_INT)
return 0;
if (WORDS_BIG_ENDIAN)
i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
val = (i / size_ratio == 0
? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))
: (GET_CODE (op) == CONST_INT
? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));
if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)
val = ((val >> ((i % size_ratio) * BITS_PER_WORD)));
if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT
&& ((val & ((HOST_WIDE_INT) (-1) << (bits_per_word - 1)))
!= ((HOST_WIDE_INT) (-1) << (bits_per_word - 1))))
val &= ((HOST_WIDE_INT) 1 << bits_per_word) - 1;
if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT
&& (val & ((HOST_WIDE_INT) 1 << (bits_per_word - 1))))
val |= ((HOST_WIDE_INT) (-1) << bits_per_word);
return GEN_INT (val);
}
rtx
operand_subword_force (op, i, mode)
rtx op;
int i;
enum machine_mode mode;
{
rtx result = operand_subword (op, i, 1, mode);
if (result)
return result;
if (mode != BLKmode && mode != VOIDmode)
{
if (GET_CODE (op) == REG)
op = copy_to_reg (op);
else
op = force_reg (mode, op);
}
result = operand_subword (op, i, 1, mode);
if (result == 0)
abort ();
return result;
}
void
reverse_comparison (insn)
rtx insn;
{
rtx body = PATTERN (insn);
rtx comp;
if (GET_CODE (body) == SET)
comp = SET_SRC (body);
else
comp = SET_SRC (XVECEXP (body, 0, 0));
if (GET_CODE (comp) == COMPARE)
{
rtx op0 = XEXP (comp, 0);
rtx op1 = XEXP (comp, 1);
XEXP (comp, 0) = op1;
XEXP (comp, 1) = op0;
}
else
{
rtx new = gen_rtx_COMPARE (VOIDmode, CONST0_RTX (GET_MODE (comp)), comp);
if (GET_CODE (body) == SET)
SET_SRC (body) = new;
else
SET_SRC (XVECEXP (body, 0, 0)) = new;
}
}
rtx
change_address (memref, mode, addr)
rtx memref;
enum machine_mode mode;
rtx addr;
{
rtx new;
if (GET_CODE (memref) != MEM)
abort ();
if (mode == VOIDmode)
mode = GET_MODE (memref);
if (addr == 0)
addr = XEXP (memref, 0);
if (reload_completed || reload_in_progress)
{
if (! memory_address_p (mode, addr))
abort ();
}
else
addr = memory_address (mode, addr);
if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
return memref;
new = gen_rtx_MEM (mode, addr);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);
MEM_COPY_ATTRIBUTES (new, memref);
return new;
}
rtx
gen_label_rtx ()
{
register rtx label;
label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX,
NULL_RTX, label_num++, NULL_PTR);
LABEL_NUSES (label) = 0;
return label;
}
rtx
gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
last_labelno, max_parm_regnum, max_regnum, args_size,
pops_args, stack_slots, forced_labels, function_flags,
outgoing_args_size, original_arg_vector,
original_decl_initial, regno_rtx, regno_flag,
regno_align, parm_reg_stack_loc)
rtx first_insn, first_parm_insn;
int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;
int pops_args;
rtx stack_slots;
rtx forced_labels;
int function_flags;
int outgoing_args_size;
rtvec original_arg_vector;
rtx original_decl_initial;
rtvec regno_rtx;
char *regno_flag;
char *regno_align;
rtvec parm_reg_stack_loc;
{
rtx header = gen_rtx_INLINE_HEADER (VOIDmode,
cur_insn_uid++, NULL_RTX,
first_insn, first_parm_insn,
first_labelno, last_labelno,
max_parm_regnum, max_regnum, args_size,
pops_args, stack_slots, forced_labels,
function_flags, outgoing_args_size,
original_arg_vector,
original_decl_initial,
regno_rtx, regno_flag, regno_align,
parm_reg_stack_loc);
return header;
}
void
set_new_first_and_last_insn (first, last)
rtx first, last;
{
rtx insn;
first_insn = first;
last_insn = last;
cur_insn_uid = 0;
for (insn = first; insn; insn = NEXT_INSN (insn))
cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn));
cur_insn_uid++;
}
void
set_new_first_and_last_label_num (first, last)
int first, last;
{
base_label_num = label_num;
first_label_num = first;
last_label_num = last;
}
void
save_emit_status (p)
struct function *p;
{
p->reg_rtx_no = reg_rtx_no;
p->first_label_num = first_label_num;
p->first_insn = first_insn;
p->last_insn = last_insn;
p->sequence_rtl_expr = sequence_rtl_expr;
p->sequence_stack = sequence_stack;
p->cur_insn_uid = cur_insn_uid;
p->last_linenum = last_linenum;
p->last_filename = last_filename;
p->regno_pointer_flag = regno_pointer_flag;
p->regno_pointer_align = regno_pointer_align;
p->regno_pointer_flag_length = regno_pointer_flag_length;
p->regno_reg_rtx = regno_reg_rtx;
}
void
restore_emit_status (p)
struct function *p;
{
int i;
reg_rtx_no = p->reg_rtx_no;
first_label_num = p->first_label_num;
last_label_num = 0;
first_insn = p->first_insn;
last_insn = p->last_insn;
sequence_rtl_expr = p->sequence_rtl_expr;
sequence_stack = p->sequence_stack;
cur_insn_uid = p->cur_insn_uid;
last_linenum = p->last_linenum;
last_filename = p->last_filename;
regno_pointer_flag = p->regno_pointer_flag;
regno_pointer_align = p->regno_pointer_align;
regno_pointer_flag_length = p->regno_pointer_flag_length;
regno_reg_rtx = p->regno_reg_rtx;
sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
free_insn = 0;
}
void
unshare_all_rtl (insn)
register rtx insn;
{
for (; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
}
copy_rtx_if_shared (stack_slot_list);
}
rtx
copy_rtx_if_shared (orig)
rtx orig;
{
register rtx x = orig;
register int i;
register enum rtx_code code;
register char *format_ptr;
int copied = 0;
if (x == 0)
return 0;
code = GET_CODE (x);
switch (code)
{
case REG:
case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
case SCRATCH:
return x;
case CONST:
if (GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
return x;
break;
case INSN:
case JUMP_INSN:
case CALL_INSN:
case NOTE:
case BARRIER:
return x;
case MEM:
if (CONSTANT_ADDRESS_P (XEXP (x, 0))
|| XEXP (x, 0) == virtual_stack_vars_rtx
|| XEXP (x, 0) == virtual_incoming_args_rtx)
return x;
if (GET_CODE (XEXP (x, 0)) == PLUS
&& (XEXP (XEXP (x, 0), 0) == virtual_stack_vars_rtx
|| XEXP (XEXP (x, 0), 0) == virtual_incoming_args_rtx)
&& CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
{
if (! x->used)
XEXP (x, 0) = copy_rtx_if_shared (XEXP (x, 0));
x->used = 1;
return x;
}
break;
default:
break;
}
if (x->used)
{
register rtx copy;
copy = rtx_alloc (code);
bcopy ((char *) x, (char *) copy,
(sizeof (*copy) - sizeof (copy->fld)
+ sizeof (copy->fld[0]) * GET_RTX_LENGTH (code)));
x = copy;
copied = 1;
}
x->used = 1;
format_ptr = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++)
{
switch (*format_ptr++)
{
case 'e':
XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i));
break;
case 'E':
if (XVEC (x, i) != NULL)
{
register int j;
int len = XVECLEN (x, i);
if (copied && len > 0)
XVEC (x, i) = gen_rtvec_vv (len, XVEC (x, i)->elem);
for (j = 0; j < len; j++)
XVECEXP (x, i, j) = copy_rtx_if_shared (XVECEXP (x, i, j));
}
break;
}
}
return x;
}
void
reset_used_flags (x)
rtx x;
{
register int i, j;
register enum rtx_code code;
register char *format_ptr;
if (x == 0)
return;
code = GET_CODE (x);
switch (code)
{
case REG:
case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
return;
case INSN:
case JUMP_INSN:
case CALL_INSN:
case NOTE:
case LABEL_REF:
case BARRIER:
return;
default:
break;
}
x->used = 0;
format_ptr = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++)
{
switch (*format_ptr++)
{
case 'e':
reset_used_flags (XEXP (x, i));
break;
case 'E':
for (j = 0; j < XVECLEN (x, i); j++)
reset_used_flags (XVECEXP (x, i, j));
break;
}
}
}
rtx
make_safe_from (x, other)
rtx x, other;
{
while (1)
switch (GET_CODE (other))
{
case SUBREG:
other = SUBREG_REG (other);
break;
case STRICT_LOW_PART:
case SIGN_EXTEND:
case ZERO_EXTEND:
other = XEXP (other, 0);
break;
default:
goto done;
}
done:
if ((GET_CODE (other) == MEM
&& ! CONSTANT_P (x)
&& GET_CODE (x) != REG
&& GET_CODE (x) != SUBREG)
|| (GET_CODE (other) == REG
&& (REGNO (other) < FIRST_PSEUDO_REGISTER
|| reg_mentioned_p (other, x))))
{
rtx temp = gen_reg_rtx (GET_MODE (x));
emit_move_insn (temp, x);
return temp;
}
return x;
}
rtx
get_insns ()
{
return first_insn;
}
rtx
get_last_insn ()
{
return last_insn;
}
void
set_last_insn (insn)
rtx insn;
{
if (NEXT_INSN (insn) != 0)
abort ();
last_insn = insn;
}
rtx
get_last_insn_anywhere ()
{
struct sequence_stack *stack;
if (last_insn)
return last_insn;
for (stack = sequence_stack; stack; stack = stack->next)
if (stack->last != 0)
return stack->last;
return 0;
}
int
get_max_uid ()
{
return cur_insn_uid;
}
rtx
next_insn (insn)
rtx insn;
{
if (insn)
{
insn = NEXT_INSN (insn);
if (insn && GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, 0);
}
return insn;
}
rtx
previous_insn (insn)
rtx insn;
{
if (insn)
{
insn = PREV_INSN (insn);
if (insn && GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
}
return insn;
}
rtx
next_nonnote_insn (insn)
rtx insn;
{
while (insn)
{
insn = NEXT_INSN (insn);
if (insn == 0 || GET_CODE (insn) != NOTE)
break;
}
return insn;
}
rtx
prev_nonnote_insn (insn)
rtx insn;
{
while (insn)
{
insn = PREV_INSN (insn);
if (insn == 0 || GET_CODE (insn) != NOTE)
break;
}
return insn;
}
rtx
next_real_insn (insn)
rtx insn;
{
while (insn)
{
insn = NEXT_INSN (insn);
if (insn == 0 || GET_CODE (insn) == INSN
|| GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
break;
}
return insn;
}
rtx
prev_real_insn (insn)
rtx insn;
{
while (insn)
{
insn = PREV_INSN (insn);
if (insn == 0 || GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
|| GET_CODE (insn) == JUMP_INSN)
break;
}
return insn;
}
rtx
next_active_insn (insn)
rtx insn;
{
while (insn)
{
insn = NEXT_INSN (insn);
if (insn == 0
|| GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
|| (GET_CODE (insn) == INSN
&& (! reload_completed
|| (GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER))))
break;
}
return insn;
}
rtx
prev_active_insn (insn)
rtx insn;
{
while (insn)
{
insn = PREV_INSN (insn);
if (insn == 0
|| GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
|| (GET_CODE (insn) == INSN
&& (! reload_completed
|| (GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER))))
break;
}
return insn;
}
rtx
next_label (insn)
rtx insn;
{
while (insn)
{
insn = NEXT_INSN (insn);
if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
break;
}
return insn;
}
rtx
prev_label (insn)
rtx insn;
{
while (insn)
{
insn = PREV_INSN (insn);
if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
break;
}
return insn;
}
#ifdef HAVE_cc0
void
link_cc0_insns (insn)
rtx insn;
{
rtx user = next_nonnote_insn (insn);
if (GET_CODE (user) == INSN && GET_CODE (PATTERN (user)) == SEQUENCE)
user = XVECEXP (PATTERN (user), 0, 0);
REG_NOTES (user) = gen_rtx_INSN_LIST (REG_CC_SETTER, insn, REG_NOTES (user));
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_CC_USER, user, REG_NOTES (insn));
}
rtx
next_cc0_user (insn)
rtx insn;
{
rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX);
if (note)
return XEXP (note, 0);
insn = next_nonnote_insn (insn);
if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, 0);
if (insn && GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& reg_mentioned_p (cc0_rtx, PATTERN (insn)))
return insn;
return 0;
}
rtx
prev_cc0_setter (insn)
rtx insn;
{
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
if (note)
return XEXP (note, 0);
insn = prev_nonnote_insn (insn);
if (! sets_cc0_p (PATTERN (insn)))
abort ();
return insn;
}
#endif
rtx
try_split (pat, trial, last)
rtx pat, trial;
int last;
{
rtx before = PREV_INSN (trial);
rtx after = NEXT_INSN (trial);
rtx seq = split_insns (pat, trial);
int has_barrier = 0;
rtx tem;
if (after && GET_CODE (after) == BARRIER)
{
has_barrier = 1;
after = NEXT_INSN (after);
}
if (seq)
{
if (GET_CODE (seq) == SEQUENCE)
{
int i;
if (GET_CODE (trial) == JUMP_INSN)
for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
{
JUMP_LABEL (XVECEXP (seq, 0, i)) = JUMP_LABEL (trial);
if (JUMP_LABEL (trial))
LABEL_NUSES (JUMP_LABEL (trial))++;
}
tem = emit_insn_after (seq, before);
delete_insn (trial);
if (has_barrier)
emit_barrier_after (tem);
for (tem = NEXT_INSN (before); tem != after;
tem = NEXT_INSN (tem))
if (! INSN_DELETED_P (tem)
&& GET_RTX_CLASS (GET_CODE (tem)) == 'i')
tem = try_split (PATTERN (tem), tem, 1);
}
else if (rtx_equal_p (seq, pat))
return trial;
else
{
PATTERN (trial) = seq;
INSN_CODE (trial) = -1;
try_split (seq, trial, last);
}
return last ? prev_active_insn (after) : next_active_insn (before);
}
return trial;
}
rtx
make_insn_raw (pattern)
rtx pattern;
{
register rtx insn;
if (free_insn != 0 && rtx_equal_function_value_matters)
{
insn = free_insn;
free_insn = NEXT_INSN (free_insn);
PUT_CODE (insn, INSN);
}
else
insn = rtx_alloc (INSN);
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
return insn;
}
static rtx
make_jump_insn_raw (pattern)
rtx pattern;
{
register rtx insn;
insn = rtx_alloc (JUMP_INSN);
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
JUMP_LABEL (insn) = NULL;
return insn;
}
static rtx
make_call_insn_raw (pattern)
rtx pattern;
{
register rtx insn;
insn = rtx_alloc (CALL_INSN);
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
CALL_INSN_FUNCTION_USAGE (insn) = NULL;
return insn;
}
void
add_insn (insn)
register rtx insn;
{
PREV_INSN (insn) = last_insn;
NEXT_INSN (insn) = 0;
if (NULL != last_insn)
NEXT_INSN (last_insn) = insn;
if (NULL == first_insn)
first_insn = insn;
last_insn = insn;
}
void
add_insn_after (insn, after)
rtx insn, after;
{
rtx next = NEXT_INSN (after);
if (optimize && INSN_DELETED_P (after))
abort ();
NEXT_INSN (insn) = next;
PREV_INSN (insn) = after;
if (next)
{
PREV_INSN (next) = insn;
if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
}
else if (last_insn == after)
last_insn = insn;
else
{
struct sequence_stack *stack = sequence_stack;
for (; stack; stack = stack->next)
if (after == stack->last)
{
stack->last = insn;
break;
}
if (stack == 0)
abort ();
}
NEXT_INSN (after) = insn;
if (GET_CODE (after) == INSN && GET_CODE (PATTERN (after)) == SEQUENCE)
{
rtx sequence = PATTERN (after);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
}
}
void
add_insn_before (insn, before)
rtx insn, before;
{
rtx prev = PREV_INSN (before);
if (optimize && INSN_DELETED_P (before))
abort ();
PREV_INSN (insn) = prev;
NEXT_INSN (insn) = before;
if (prev)
{
NEXT_INSN (prev) = insn;
if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
rtx sequence = PATTERN (prev);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
}
}
else if (first_insn == before)
first_insn = insn;
else
{
struct sequence_stack *stack = sequence_stack;
for (; stack; stack = stack->next)
if (before == stack->first)
{
stack->first = insn;
break;
}
if (stack == 0)
abort ();
}
PREV_INSN (before) = insn;
if (GET_CODE (before) == INSN && GET_CODE (PATTERN (before)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
}
void
remove_insn (insn)
rtx insn;
{
rtx next = NEXT_INSN (insn);
rtx prev = PREV_INSN (insn);
if (prev)
{
NEXT_INSN (prev) = next;
if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
rtx sequence = PATTERN (prev);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next;
}
}
else if (first_insn == insn)
first_insn = next;
else
{
struct sequence_stack *stack = sequence_stack;
for (; stack; stack = stack->next)
if (insn == stack->first)
{
stack->first = next;
break;
}
if (stack == 0)
abort ();
}
if (next)
{
PREV_INSN (next) = prev;
if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
}
else if (last_insn == insn)
last_insn = prev;
else
{
struct sequence_stack *stack = sequence_stack;
for (; stack; stack = stack->next)
if (insn == stack->last)
{
stack->last = prev;
break;
}
if (stack == 0)
abort ();
}
}
void
delete_insns_since (from)
rtx from;
{
if (from == 0)
first_insn = 0;
else
NEXT_INSN (from) = 0;
last_insn = from;
}
void
reorder_insns (from, to, after)
rtx from, to, after;
{
if (PREV_INSN (from))
NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
if (NEXT_INSN (to))
PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
if (last_insn == to)
last_insn = PREV_INSN (from);
if (first_insn == from)
first_insn = NEXT_INSN (to);
if (NEXT_INSN (after))
PREV_INSN (NEXT_INSN (after)) = to;
NEXT_INSN (to) = NEXT_INSN (after);
PREV_INSN (from) = after;
NEXT_INSN (after) = from;
if (after == last_insn)
last_insn = to;
}
static rtx
find_line_note (insn)
rtx insn;
{
if (no_line_numbers)
return 0;
for (; insn; insn = PREV_INSN (insn))
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) >= 0)
break;
return insn;
}
void
reorder_insns_with_line_notes (from, to, after)
rtx from, to, after;
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
reorder_insns (from, to, after);
if (from_line == after_line)
return;
if (from_line)
emit_line_note_after (NOTE_SOURCE_FILE (from_line),
NOTE_LINE_NUMBER (from_line),
after);
if (after_line)
emit_line_note_after (NOTE_SOURCE_FILE (after_line),
NOTE_LINE_NUMBER (after_line),
to);
}
rtx
emit_insn_before (pattern, before)
register rtx pattern, before;
{
register rtx insn = before;
if (GET_CODE (pattern) == SEQUENCE)
{
register int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
insn = XVECEXP (pattern, 0, i);
add_insn_before (insn, before);
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
{
insn = make_insn_raw (pattern);
add_insn_before (insn, before);
}
return insn;
}
rtx
emit_jump_insn_before (pattern, before)
register rtx pattern, before;
{
register rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_before (pattern, before);
else
{
insn = make_jump_insn_raw (pattern);
add_insn_before (insn, before);
}
return insn;
}
rtx
emit_call_insn_before (pattern, before)
register rtx pattern, before;
{
register rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_before (pattern, before);
else
{
insn = make_call_insn_raw (pattern);
add_insn_before (insn, before);
PUT_CODE (insn, CALL_INSN);
}
return insn;
}
rtx
emit_barrier_before (before)
register rtx before;
{
register rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
add_insn_before (insn, before);
return insn;
}
rtx
emit_label_before (label, before)
rtx label, before;
{
if (INSN_UID (label) == 0)
{
INSN_UID (label) = cur_insn_uid++;
add_insn_before (label, before);
}
return label;
}
rtx
emit_note_before (subtype, before)
int subtype;
rtx before;
{
register rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
add_insn_before (note, before);
return note;
}
rtx
emit_insn_after (pattern, after)
register rtx pattern, after;
{
register rtx insn = after;
if (GET_CODE (pattern) == SEQUENCE)
{
register int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
insn = XVECEXP (pattern, 0, i);
add_insn_after (insn, after);
after = insn;
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
{
insn = make_insn_raw (pattern);
add_insn_after (insn, after);
}
return insn;
}
void
emit_insn_after_with_line_notes (pattern, after, from)
rtx pattern, after, from;
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
rtx insn = emit_insn_after (pattern, after);
if (from_line)
emit_line_note_after (NOTE_SOURCE_FILE (from_line),
NOTE_LINE_NUMBER (from_line),
after);
if (after_line)
emit_line_note_after (NOTE_SOURCE_FILE (after_line),
NOTE_LINE_NUMBER (after_line),
insn);
}
rtx
emit_jump_insn_after (pattern, after)
register rtx pattern, after;
{
register rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_after (pattern, after);
else
{
insn = make_jump_insn_raw (pattern);
add_insn_after (insn, after);
}
return insn;
}
rtx
emit_barrier_after (after)
register rtx after;
{
register rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
add_insn_after (insn, after);
return insn;
}
rtx
emit_label_after (label, after)
rtx label, after;
{
if (INSN_UID (label) == 0)
{
INSN_UID (label) = cur_insn_uid++;
add_insn_after (label, after);
}
return label;
}
rtx
emit_note_after (subtype, after)
int subtype;
rtx after;
{
register rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
add_insn_after (note, after);
return note;
}
rtx
emit_line_note_after (file, line, after)
char *file;
int line;
rtx after;
{
register rtx note;
if (no_line_numbers && line > 0)
{
cur_insn_uid++;
return 0;
}
note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = file;
NOTE_LINE_NUMBER (note) = line;
add_insn_after (note, after);
return note;
}
rtx
emit_insn (pattern)
rtx pattern;
{
rtx insn = last_insn;
if (GET_CODE (pattern) == SEQUENCE)
{
register int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
insn = XVECEXP (pattern, 0, i);
add_insn (insn);
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
{
insn = make_insn_raw (pattern);
add_insn (insn);
}
return insn;
}
rtx
emit_insns (insn)
rtx insn;
{
rtx last = 0;
while (insn)
{
rtx next = NEXT_INSN (insn);
add_insn (insn);
last = insn;
insn = next;
}
return last;
}
rtx
emit_insns_before (insn, before)
rtx insn;
rtx before;
{
rtx last = 0;
while (insn)
{
rtx next = NEXT_INSN (insn);
add_insn_before (insn, before);
last = insn;
insn = next;
}
return last;
}
rtx
emit_insns_after (first, after)
register rtx first;
register rtx after;
{
register rtx last;
register rtx after_after;
if (!after)
abort ();
if (!first)
return first;
for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
continue;
after_after = NEXT_INSN (after);
NEXT_INSN (after) = first;
PREV_INSN (first) = after;
NEXT_INSN (last) = after_after;
if (after_after)
PREV_INSN (after_after) = last;
if (after == last_insn)
last_insn = last;
return last;
}
rtx
emit_jump_insn (pattern)
rtx pattern;
{
if (GET_CODE (pattern) == SEQUENCE)
return emit_insn (pattern);
else
{
register rtx insn = make_jump_insn_raw (pattern);
add_insn (insn);
return insn;
}
}
rtx
emit_call_insn (pattern)
rtx pattern;
{
if (GET_CODE (pattern) == SEQUENCE)
return emit_insn (pattern);
else
{
register rtx insn = make_call_insn_raw (pattern);
add_insn (insn);
PUT_CODE (insn, CALL_INSN);
return insn;
}
}
rtx
emit_label (label)
rtx label;
{
if (INSN_UID (label) == 0)
{
INSN_UID (label) = cur_insn_uid++;
add_insn (label);
}
return label;
}
rtx
emit_barrier ()
{
register rtx barrier = rtx_alloc (BARRIER);
INSN_UID (barrier) = cur_insn_uid++;
add_insn (barrier);
return barrier;
}
rtx
emit_line_note (file, line)
char *file;
int line;
{
emit_filename = file;
emit_lineno = line;
#if 0
if (no_line_numbers)
return 0;
#endif
return emit_note (file, line);
}
rtx
emit_note (file, line)
char *file;
int line;
{
register rtx note;
if (line > 0)
{
if (file && last_filename && !strcmp (file, last_filename)
&& line == last_linenum)
return 0;
last_filename = file;
last_linenum = line;
}
if (no_line_numbers && line > 0)
{
cur_insn_uid++;
return 0;
}
note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = file;
NOTE_LINE_NUMBER (note) = line;
add_insn (note);
return note;
}
rtx
emit_line_note_force (file, line)
char *file;
int line;
{
last_linenum = -1;
return emit_line_note (file, line);
}
void
force_next_line_note ()
{
last_linenum = -1;
}
void
set_unique_reg_note (insn, kind, datum)
rtx insn;
enum reg_note kind;
rtx datum;
{
rtx note = find_reg_note (insn, kind, NULL_RTX);
if (note)
remove_note (insn, note);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn));
}
enum rtx_code
classify_insn (x)
rtx x;
{
if (GET_CODE (x) == CODE_LABEL)
return CODE_LABEL;
if (GET_CODE (x) == CALL)
return CALL_INSN;
if (GET_CODE (x) == RETURN)
return JUMP_INSN;
if (GET_CODE (x) == SET)
{
if (SET_DEST (x) == pc_rtx)
return JUMP_INSN;
else if (GET_CODE (SET_SRC (x)) == CALL)
return CALL_INSN;
else
return INSN;
}
if (GET_CODE (x) == PARALLEL)
{
register int j;
for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
return CALL_INSN;
else if (GET_CODE (XVECEXP (x, 0, j)) == SET
&& SET_DEST (XVECEXP (x, 0, j)) == pc_rtx)
return JUMP_INSN;
else if (GET_CODE (XVECEXP (x, 0, j)) == SET
&& GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
return CALL_INSN;
}
return INSN;
}
rtx
emit (x)
rtx x;
{
enum rtx_code code = classify_insn (x);
if (code == CODE_LABEL)
return emit_label (x);
else if (code == INSN)
return emit_insn (x);
else if (code == JUMP_INSN)
{
register rtx insn = emit_jump_insn (x);
if (simplejump_p (insn) || GET_CODE (x) == RETURN)
return emit_barrier ();
return insn;
}
else if (code == CALL_INSN)
return emit_call_insn (x);
else
abort ();
}
void
start_sequence ()
{
struct sequence_stack *tem;
if (sequence_element_free_list)
{
tem = sequence_element_free_list;
sequence_element_free_list = tem->next;
}
else
tem = (struct sequence_stack *) permalloc (sizeof (struct sequence_stack));
tem->next = sequence_stack;
tem->first = first_insn;
tem->last = last_insn;
tem->sequence_rtl_expr = sequence_rtl_expr;
sequence_stack = tem;
first_insn = 0;
last_insn = 0;
}
void
start_sequence_for_rtl_expr (t)
tree t;
{
start_sequence ();
sequence_rtl_expr = t;
}
void
push_to_sequence (first)
rtx first;
{
rtx last;
start_sequence ();
for (last = first; last && NEXT_INSN (last); last = NEXT_INSN (last));
first_insn = first;
last_insn = last;
}
void
push_topmost_sequence ()
{
struct sequence_stack *stack, *top = NULL;
start_sequence ();
for (stack = sequence_stack; stack; stack = stack->next)
top = stack;
first_insn = top->first;
last_insn = top->last;
sequence_rtl_expr = top->sequence_rtl_expr;
}
void
pop_topmost_sequence ()
{
struct sequence_stack *stack, *top = NULL;
for (stack = sequence_stack; stack; stack = stack->next)
top = stack;
top->first = first_insn;
top->last = last_insn;
end_sequence ();
}
void
end_sequence ()
{
struct sequence_stack *tem = sequence_stack;
first_insn = tem->first;
last_insn = tem->last;
sequence_rtl_expr = tem->sequence_rtl_expr;
sequence_stack = tem->next;
tem->next = sequence_element_free_list;
sequence_element_free_list = tem;
}
int
in_sequence_p ()
{
return sequence_stack != 0;
}
rtx
gen_sequence ()
{
rtx result;
rtx tem;
int i;
int len;
len = 0;
for (tem = first_insn; tem; tem = NEXT_INSN (tem))
len++;
if (len == 1
&& ! RTX_FRAME_RELATED_P (first_insn)
&& (GET_CODE (first_insn) == INSN
|| GET_CODE (first_insn) == JUMP_INSN
|| (GET_CODE (first_insn) == CALL_INSN
&& CALL_INSN_FUNCTION_USAGE (first_insn) == NULL_RTX)))
{
NEXT_INSN (first_insn) = free_insn;
free_insn = first_insn;
return PATTERN (first_insn);
}
if (len < SEQUENCE_RESULT_SIZE && (result = sequence_result[len]) != 0)
sequence_result[len] = 0;
else
{
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len));
pop_obstacks ();
}
for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
XVECEXP (result, 0, i) = tem;
return result;
}
void
init_virtual_regs ()
{
regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
}
void
init_emit ()
{
int i;
first_insn = NULL;
last_insn = NULL;
sequence_rtl_expr = NULL;
cur_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
last_linenum = 0;
last_filename = 0;
first_label_num = label_num;
last_label_num = 0;
sequence_stack = NULL;
sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
free_insn = 0;
regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
regno_pointer_flag
= (char *) savealloc (regno_pointer_flag_length);
bzero (regno_pointer_flag, regno_pointer_flag_length);
regno_pointer_align
= (char *) savealloc (regno_pointer_flag_length);
bzero (regno_pointer_align, regno_pointer_flag_length);
regno_reg_rtx
= (rtx *) savealloc (regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
init_virtual_regs ();
REGNO_POINTER_FLAG (STACK_POINTER_REGNUM) = 1;
REGNO_POINTER_FLAG (FRAME_POINTER_REGNUM) = 1;
REGNO_POINTER_FLAG (HARD_FRAME_POINTER_REGNUM) = 1;
REGNO_POINTER_FLAG (ARG_POINTER_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_INCOMING_ARGS_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_CFA_REGNUM) = 1;
#ifdef STACK_BOUNDARY
REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (FRAME_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_INCOMING_ARGS_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_STACK_VARS_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = UNITS_PER_WORD;
#endif
#ifdef INIT_EXPANDERS
INIT_EXPANDERS;
#endif
}
void
init_emit_once (line_numbers)
int line_numbers;
{
int i;
enum machine_mode mode;
enum machine_mode double_mode;
no_line_numbers = ! line_numbers;
sequence_stack = NULL;
byte_mode = VOIDmode;
word_mode = VOIDmode;
double_mode = VOIDmode;
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
&& byte_mode == VOIDmode)
byte_mode = mode;
if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD
&& word_mode == VOIDmode)
word_mode = mode;
}
#ifndef DOUBLE_TYPE_SIZE
#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE
&& double_mode == VOIDmode)
double_mode = mode;
}
ptr_mode = mode_for_size (POINTER_SIZE, GET_MODE_CLASS (Pmode), 0);
for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
{
PUT_CODE (&const_int_rtx[i + MAX_SAVED_CONST_INT], CONST_INT);
PUT_MODE (&const_int_rtx[i + MAX_SAVED_CONST_INT], VOIDmode);
INTVAL (&const_int_rtx[i + MAX_SAVED_CONST_INT]) = i;
}
if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT
&& STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT)
const_true_rtx = &const_int_rtx[STORE_FLAG_VALUE + MAX_SAVED_CONST_INT];
else
const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);
dconst0 = REAL_VALUE_ATOF ("0", double_mode);
dconst1 = REAL_VALUE_ATOF ("1", double_mode);
dconst2 = REAL_VALUE_ATOF ("2", double_mode);
dconstm1 = REAL_VALUE_ATOF ("-1", double_mode);
for (i = 0; i <= 2; i++)
{
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
rtx tem = rtx_alloc (CONST_DOUBLE);
union real_extract u;
bzero ((char *) &u, sizeof u);
u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2;
bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (tem), sizeof u);
CONST_DOUBLE_MEM (tem) = cc0_rtx;
PUT_MODE (tem, mode);
const_tiny_rtx[i][(int) mode] = tem;
}
const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
const_tiny_rtx[i][(int) mode] = GEN_INT (i);
for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
const_tiny_rtx[i][(int) mode] = GEN_INT (i);
}
for (mode = GET_CLASS_NARROWEST_MODE (MODE_CC); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
const_tiny_rtx[0][(int) mode] = const0_rtx;
REGNO (stack_pointer_rtx) = STACK_POINTER_REGNUM;
PUT_MODE (stack_pointer_rtx, Pmode);
REGNO (frame_pointer_rtx) = FRAME_POINTER_REGNUM;
PUT_MODE (frame_pointer_rtx, Pmode);
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
REGNO (hard_frame_pointer_rtx) = HARD_FRAME_POINTER_REGNUM;
PUT_MODE (hard_frame_pointer_rtx, Pmode);
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
REGNO (arg_pointer_rtx) = ARG_POINTER_REGNUM;
PUT_MODE (arg_pointer_rtx, Pmode);
#endif
REGNO (virtual_incoming_args_rtx) = VIRTUAL_INCOMING_ARGS_REGNUM;
PUT_MODE (virtual_incoming_args_rtx, Pmode);
REGNO (virtual_stack_vars_rtx) = VIRTUAL_STACK_VARS_REGNUM;
PUT_MODE (virtual_stack_vars_rtx, Pmode);
REGNO (virtual_stack_dynamic_rtx) = VIRTUAL_STACK_DYNAMIC_REGNUM;
PUT_MODE (virtual_stack_dynamic_rtx, Pmode);
REGNO (virtual_outgoing_args_rtx) = VIRTUAL_OUTGOING_ARGS_REGNUM;
PUT_MODE (virtual_outgoing_args_rtx, Pmode);
REGNO (virtual_cfa_rtx) = VIRTUAL_CFA_REGNUM;
PUT_MODE (virtual_cfa_rtx, Pmode);
#ifdef RETURN_ADDRESS_POINTER_REGNUM
return_address_pointer_rtx
= gen_rtx_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
#endif
#ifdef STRUCT_VALUE
struct_value_rtx = STRUCT_VALUE;
#else
struct_value_rtx = gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM);
#endif
#ifdef STRUCT_VALUE_INCOMING
struct_value_incoming_rtx = STRUCT_VALUE_INCOMING;
#else
#ifdef STRUCT_VALUE_INCOMING_REGNUM
struct_value_incoming_rtx
= gen_rtx_REG (Pmode, STRUCT_VALUE_INCOMING_REGNUM);
#else
struct_value_incoming_rtx = struct_value_rtx;
#endif
#endif
#ifdef STATIC_CHAIN_REGNUM
static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
#ifdef STATIC_CHAIN_INCOMING_REGNUM
if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
static_chain_incoming_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
else
#endif
static_chain_incoming_rtx = static_chain_rtx;
#endif
#ifdef STATIC_CHAIN
static_chain_rtx = STATIC_CHAIN;
#ifdef STATIC_CHAIN_INCOMING
static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
#else
static_chain_incoming_rtx = static_chain_rtx;
#endif
#endif
#ifdef PIC_OFFSET_TABLE_REGNUM
pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
#endif
#ifdef INIT_EXPANDERS
INIT_EXPANDERS;
#endif
}
int
force_line_numbers ()
{
int old = no_line_numbers;
no_line_numbers = 0;
if (old)
force_next_line_note ();
return old;
}
void
restore_line_number_status (old_value)
int old_value;
{
no_line_numbers = old_value;
}