#include "config.h"
#include "system.h"
#include "rtl.h"
#include "tree.h"
#include "tm_p.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
#include "except.h"
#include "function.h"
#include "recog.h"
#include "expr.h"
#include "optabs.h"
#include "toplev.h"
#include "basic-block.h"
#include "ggc.h"
#include "target.h"
#include "target-def.h"
rtx pj_cmp_op0;
rtx pj_cmp_op1;
enum machine_mode pj_cmp_mode;
static void pj_output_rval PARAMS ((rtx, enum machine_mode, rtx));
static void pj_output_store_into_lval PARAMS ((enum machine_mode mode, rtx op));
static void pj_output_push_int PARAMS ((int));
static void pj_output_load PARAMS ((enum machine_mode, int));
static void pj_output_inc PARAMS ((rtx, int));
static void pj_output_cnv_op PARAMS ((enum insn_code, rtx));
static char mode_to_char PARAMS ((enum machine_mode));
static void pj_output_varidx PARAMS ((enum machine_mode, int, int));
static void pj_print_cond PARAMS ((enum rtx_code));
static rtx *unique_src_operand PARAMS ((rtx *, rtx));
short pj_si_vars_offset_vec[FIRST_PSEUDO_REGISTER];
short pj_di_vars_offset_vec[FIRST_PSEUDO_REGISTER];
short pj_debugreg_renumber_vec[FIRST_PSEUDO_REGISTER];
static int nfakes;
int pj_stuff_on_line;
struct gcc_target targetm = TARGET_INITIALIZER;
static void
pj_printf VPARAMS ((const char *template, ...))
{
register int c;
int ops_read = 0;
rtx operands[10];
VA_OPEN (argptr, template);
VA_FIXEDARG (argptr, const char *, template);
while ((c = *template++))
{
int was_stuff_on_line = pj_stuff_on_line;
pj_stuff_on_line = 1;
switch (c)
{
case '\n':
putc (c, asm_out_file);
pj_stuff_on_line = 0;
break;
default:
putc (c, asm_out_file);
break;
case '%':
{
switch (*template)
{
case '%':
putc ('%', asm_out_file);
template++;
pj_stuff_on_line = 1;
break;
case '*':
if (was_stuff_on_line)
fprintf (asm_out_file, "; ");
template++;
break;
case 'd':
template++;
fprintf (asm_out_file, "%d", va_arg (argptr, int));
break;
case 'x':
template++;
fprintf (asm_out_file, "%x", va_arg (argptr, int));
break;
case 'c':
template++;
fprintf (asm_out_file, "%c", va_arg (argptr, int));
break;
case 's':
template++;
fputs (va_arg (argptr, const char *), asm_out_file);
break;
case 'X':
template++;
output_addr_const (asm_out_file, va_arg (argptr, rtx));
break;
default:
{
int code = 0;
rtx send;
if (ISALPHA (*template))
code = *template++;
if (ISDIGIT (*template))
{
int num = atoi (template);
template++;
while (ops_read <= num)
operands[ops_read++] = va_arg (argptr, rtx);
send = operands[num];
}
else
send = va_arg (argptr, rtx);
if (send)
pj_print_operand (asm_out_file, send, code);
}
}
}
}
}
VA_CLOSE (argptr);
}
static void
pj_output_push_int (val)
int val;
{
int low = ((val & 0x8000) ? ~0xffff : 0) | (val & 0xffff);
if (low == -1)
pj_printf ("%*iconst_m1");
else if (low >= 0 && low <= 5)
pj_printf ("%*iconst_%d", low);
else if (low >= -128 && low < 128)
pj_printf ("%*bipush %d", low);
else
pj_printf ("%*sipush %d", low);
if ((low & 0xffff0000) != (val & 0xffff0000))
pj_printf ("%*sethi 0x%x", (val >> 16) & 0xffff);
}
static void
pj_output_print_add_k (int size)
{
if (size >= 0)
{
pj_output_push_int (size);
pj_printf ("%*iadd");
}
else
{
pj_output_push_int (-size);
pj_printf ("%*isub");
}
}
static void
pj_output_load (mode, uns)
enum machine_mode mode;
int uns;
{
int i;
switch (GET_MODE_SIZE (mode))
{
case 1:
pj_printf (uns ? "%*load_ubyte" : "%*load_byte");
break;
case 2:
pj_printf (uns ? "%*load_char" : "%*load_short");
break;
case 8:
if (TARGET_TM_EXTENSIONS)
{
pj_printf ("%*tm_load_long");
break;
}
default:
for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
{
pj_printf ("%*dup");
pj_output_print_add_k (i - 4);
pj_printf ("%*load_word");
pj_printf ("%*swap");
}
pj_printf ("%*load_word");
}
}
static void
pj_output_inc (op, size)
rtx op;
int size;
{
if (STACK_REG_RTX_P (op))
pj_printf ("%*iinc %d,%d", pj_si_vars_offset_vec[REGNO (op)], size);
else
{
pj_output_rval (op, SImode, 0);
pj_output_push_int (size);
pj_printf ("%*iadd");
pj_output_store_into_lval (SImode, op);
}
}
static void
pj_output_cnv_op (e, op)
enum insn_code e;
rtx op;
{
pj_printf ((const char *) insn_data[(int) e].output, 0, XEXP (op, 0));
}
static char
mode_to_char (mode)
enum machine_mode mode;
{
switch (mode)
{
case QImode:
case HImode:
case SImode:
return 'i';
break;
case DImode:
return 'l';
break;
case DFmode:
return 'd';
break;
case SFmode:
return 'f';
break;
default:
abort ();
}
}
static void
pj_output_varidx (mode, do_store, idx)
enum machine_mode mode;
int do_store;
int idx;
{
pj_printf ("%*%c%s%c%d",
mode_to_char (mode),
do_store ? "store" : "load",
(GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
&& idx <= 3 ? '_' : ' ', idx);
}
static void
pj_output_rval (op, mode, outer_op)
rtx op;
enum machine_mode mode;
rtx outer_op;
{
enum rtx_code code = GET_CODE (op);
optab tab;
if (code == DIV && GET_MODE_CLASS (mode) == MODE_INT)
tab = sdiv_optab;
else
tab = code_to_optab[code];
if (code == PLUS)
{
pj_output_rval (XEXP (op, 0), mode, op);
pj_output_rval (XEXP (op, 1), mode, op);
pj_printf ("%*%cadd", mode_to_char (mode));
}
else if (tab && tab->handlers[mode].insn_code != CODE_FOR_nothing)
{
const char *const template =
(const char *) insn_data[tab->handlers[mode].insn_code].output;
if (code == NEG)
pj_printf (template, 0, XEXP (op, 0));
else
pj_printf (template, 0, XEXP (op, 0), XEXP (op, 1));
}
else
switch (GET_CODE (op))
{
case PC:
fprintf (asm_out_file, " pc ");
break;
case CONST:
pj_output_rval (XEXP (op, 0), mode, op);
break;
case MEM:
pj_output_rval (XEXP (op, 0), Pmode, op);
pj_output_load (mode, 0);
break;
case SYMBOL_REF:
pj_printf ("%*ipush %X", op);
break;
case REG:
switch (mode)
{
case SImode:
case SFmode:
case HImode:
case QImode:
if (pj_si_vars_offset_vec[REGNO (op)] >= 0)
pj_output_varidx (mode, 0, pj_si_vars_offset_vec[REGNO (op)]);
else
pj_printf ("%*read_%s", reg_names[REGNO (op)]);
break;
case DImode:
case DFmode:
if (pj_di_vars_offset_vec[REGNO (op)] >= 0)
pj_output_varidx (mode, 0, pj_di_vars_offset_vec[REGNO (op)]);
else
switch (REGNO (op))
{
case G1_REG:
pj_printf ("%*read_global2");
pj_printf ("%*read_global1");
break;
case G0_REG:
pj_printf ("%*read_optop");
pj_printf ("%*read_global0");
break;
default:
abort ();
}
break;
default:
abort ();
}
break;
case CONST_DOUBLE:
pj_printf (pj_standard_float_constant (op));
break;
case CONST_INT:
if (mode == SImode || mode == HImode || mode == QImode)
pj_output_push_int (INTVAL (op));
else if (mode == DImode)
{
int v = INTVAL (op);
if (v == 1)
pj_printf ("%*lconst_1", 0);
else if (v == 0)
pj_printf ("%*lconst_0", 0);
else
{
rtx hi = GEN_INT (v < 0 ? -1 : 0);
rtx lo = op;
pj_output_rval (TARGET_LITTLE_ENDIAN ? hi : lo, SImode, op);
pj_output_rval (TARGET_LITTLE_ENDIAN ? lo : hi, SImode, op);
}
}
else
abort ();
break;
case FLOAT_TRUNCATE:
pj_printf ("%S0%*d2f", XEXP (op, 0));
break;
case LABEL_REF:
pj_printf ("%*ipush %X", XEXP (op, 0));
break;
case SUBREG:
pj_output_rval (alter_subreg (&op), mode, outer_op);
break;
case POST_INC:
pj_output_rval (XEXP (op, 0), mode, op);
pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
break;
case POST_DEC:
pj_output_rval (XEXP (op, 0), mode, op);
pj_output_inc (XEXP (op, 0), -GET_MODE_SIZE (GET_MODE (outer_op)));
break;
case PRE_INC:
pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
pj_output_rval (XEXP (op, 0), mode, op);
break;
case PRE_DEC:
if (OPTOP_REG_RTX_P (XEXP (op, 0)))
pj_output_rval (XEXP (op, 0), mode, op);
else if (STACK_REG_RTX_P (XEXP (op, 0)))
{
pj_output_inc (XEXP (op, 0),
-GET_MODE_SIZE (GET_MODE (outer_op)));
pj_output_rval (XEXP (op, 0), mode, op);
}
else
{
pj_printf ("%S0", XEXP (op, 0));
pj_output_print_add_k (-GET_MODE_SIZE (GET_MODE (outer_op)));
pj_printf ("%*dup%R0", XEXP (op, 0));
}
break;
case FIX:
pj_output_cnv_op (fixtrunctab[GET_MODE (XEXP (op, 0))][mode][0], op);
break;
case FLOAT:
if (mode == DFmode && GET_CODE (XEXP (op, 0)) == CONST_INT)
pj_output_cnv_op (floattab[mode][SImode][0], op);
else
pj_output_cnv_op (floattab[mode][GET_MODE (XEXP (op, 0))][0], op);
break;
case FLOAT_EXTEND:
case SIGN_EXTEND:
if (mode == SImode && GET_CODE (XEXP (op, 0)) == MEM)
pj_output_rval (XEXP (op, 0), GET_MODE (XEXP (op, 0)), op);
else
pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][0], op);
break;
case ZERO_EXTEND:
pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][1], op);
break;
default:
abort ();
break;
}
}
static void
pj_output_store_into_lval (mode, op)
enum machine_mode mode;
rtx op;
{
if (GET_CODE (op) == REG)
{
int rn = REGNO (op);
if (!OUTGOING_REG_RTX_P (op))
{
switch (GET_MODE (op))
{
case SImode:
case QImode:
case HImode:
case SFmode:
if (pj_si_vars_offset_vec[rn] >= 0)
pj_output_varidx (mode, 1, pj_si_vars_offset_vec[rn]);
else
pj_printf ("%*write_%s", reg_names[rn]);
break;
case DImode:
case DFmode:
if (pj_di_vars_offset_vec[rn] >= 0)
pj_output_varidx (mode, 1, pj_di_vars_offset_vec[rn]);
else
switch (rn)
{
case G1_REG:
pj_printf ("%*write_global1");
pj_printf ("%*write_global2");
break;
default:
abort ();
}
break;
default:
abort ();
}
}
}
else
{
pj_output_rval (XEXP (op, 0), Pmode, op);
switch (GET_MODE_SIZE (mode))
{
case 1:
pj_printf ("%*store_byte", 0);
break;
case 2:
pj_printf ("%*store_short", 0);
break;
case 8:
if (TARGET_TM_EXTENSIONS)
{
pj_printf ("%*tm_store_long");
break;
}
default:
{
int i;
for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
{
pj_printf ("%*dup_x1", 0);
pj_printf ("%*store_word", 0);
pj_printf ("%*iconst_4", 0);
pj_printf ("%*iadd", 0);
}
}
pj_printf ("%*store_word", 0);
break;
}
}
}
static void
pj_print_cond (code)
enum rtx_code code;
{
switch (code)
{
case EQ:
fputs ("eq", asm_out_file);
break;
case NE:
fputs ("ne", asm_out_file);
break;
case GT:
case GTU:
fputs ("gt", asm_out_file);
break;
case GE:
case GEU:
fputs ("ge", asm_out_file);
break;
case LT:
case LTU:
fputs ("lt", asm_out_file);
break;
case LE:
case LEU:
fputs ("le", asm_out_file);
break;
default:
abort ();
}
}
void
pj_print_operand (stream, x, code)
FILE *stream;
rtx x;
int code;
{
static int last_call_known;
switch (code)
{
case 'C':
if (GET_CODE (x) == SYMBOL_REF)
{
last_call_known = 1;
pj_printf ("%*.check_call %0", x);
}
else
last_call_known = 0;
break;
case 'D':
pj_output_rval (x,
GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x),
NULL_RTX);
break;
case 'E':
if (last_call_known)
pj_printf (",%d", INTVAL (x));
break;
case 'I':
pj_output_rval (XEXP (x, 0), GET_MODE (XEXP (x, 0)), NULL_RTX);
break;
case 'J':
if (GET_CODE (x) == CONST_INT)
pj_printf ("%d", INTVAL (x));
else if (GET_CODE (x) == REG)
pj_printf ("%d", pj_si_vars_offset_vec[REGNO (x)]);
else
abort ();
break;
case 'P':
if (TARGET_LITTLE_ENDIAN)
pj_printf ("%*iconst_0", 0);
pj_output_rval (x,
GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
NULL_RTX);
if (!TARGET_LITTLE_ENDIAN)
pj_printf ("%*iconst_0", 0);
break;
case 'R':
pj_output_store_into_lval (GET_MODE (x), x);
break;
case 'S':
pj_output_rval (x,
GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
NULL_RTX);
break;
case 'X':
fputc (GET_CODE (x) == LT || GET_CODE (x) == LE ? 'g' : 'l', stream);
break;
case 'Y':
pj_print_cond (GET_CODE (x));
break;
case 'Z':
pj_print_cond (reverse_condition (GET_CODE (x)));
break;
case '*':
pj_printf ("%*");
break;
default:
output_addr_const (stream, x);
break;
}
}
rtx
pj_workout_arg_words (stack_size, next_arg_reg)
rtx stack_size ATTRIBUTE_UNUSED;
rtx next_arg_reg;
{
return GEN_INT ((next_arg_reg ? REGNO (next_arg_reg) - O0_REG : 0) + 2);
}
rtx
pj_function_incoming_arg (cum, mode, passed_type, named_arg)
CUMULATIVE_ARGS *cum;
enum machine_mode mode;
tree passed_type ATTRIBUTE_UNUSED;
int named_arg ATTRIBUTE_UNUSED;
{
int arg_words = PJ_ARG_WORDS (mode);
if (cum->total_words + arg_words <= ARGS_IN_REGS)
{
int i;
if (mode == DImode || mode == DFmode)
{
cum->arg_adjust[cum->total_words + 0] = 1;
cum->arg_adjust[cum->total_words + 1] = -1;
}
else
for (i = 0; i < arg_words; i++)
cum->arg_adjust[cum->total_words + i] = 0;
return gen_rtx (REG, mode, I0_REG + cum->total_words);
}
return NULL_RTX;
}
const char *
pj_output_addsi3 (operands)
rtx *operands;
{
if (OPTOP_REG_RTX_P (operands[0]) && OPTOP_REG_RTX_P (operands[1])
&& GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >= -32 && INTVAL (operands[2]) <= 32)
{
static struct
{
const char *two;
const char *one;
}
name[2] =
{
{ "pop2", "pop"},
{ "lconst_0", "iconst_0"}
};
int size = INTVAL (operands[2]);
int d = 0;
if (size < 0)
{
d = 1;
size = -size;
}
for (; size >= 8; size -= 8)
output_asm_insn (name[d].two, 0);
if (size > 0)
output_asm_insn (name[d].one, 0);
return "";
}
if (STACK_REG_RTX_P (operands[0])
&& rtx_equal_p (operands[0], operands[1])
&& GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) <= 127)
{
return "iinc %J0,%J2";
}
return "%S1%S2%*iadd%R0";
}
void
pj_expand_prologue ()
{
int i;
int off = 0;
int arg_words = current_function_args_info.named_words;
memset (pj_si_vars_offset_vec, -1, sizeof (pj_si_vars_offset_vec));
memset (pj_di_vars_offset_vec, -1, sizeof (pj_di_vars_offset_vec));
for (i = 0; i < current_function_args_info.named_words; i++)
{
pj_debugreg_renumber_vec[I0_REG + i]
= off + R0_REG + current_function_args_info.arg_adjust[i];
pj_si_vars_offset_vec[I0_REG + i]
= off + current_function_args_info.arg_adjust[i];
pj_di_vars_offset_vec[I0_REG + i] = off;
off++;
}
if (current_function_varargs || current_function_stdarg)
{
emit_insn (gen_varargs (GEN_INT (arg_words * 4)));
pj_si_vars_offset_vec[VA_REG] = off++;
off++;
arg_words += 2;
}
off += 2;
nfakes = 0;
for (i = LAST_I_REG; i >= R0_REG; i--)
if (regs_ever_live[i] && pj_si_vars_offset_vec[i] == -1)
{
nfakes++;
pj_si_vars_offset_vec[i] = off;
pj_di_vars_offset_vec[i] = off - 1;
pj_debugreg_renumber_vec[i] = off + R0_REG;
off++;
}
if (TARGET_TEST)
{
fprintf (asm_out_file, "\n\t! args %d, size %d, fakes %d\n",
arg_words,
get_frame_size () / 4,
nfakes);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (pj_si_vars_offset_vec[i] >= 0)
fprintf (asm_out_file, "\t!vars - %d %d: %s\n",
pj_si_vars_offset_vec[i],
pj_di_vars_offset_vec[i],
reg_names[i]);
}
if (TARGET_TM_EXTENSIONS)
RTX_FRAME_RELATED_P (emit_insn (gen_tm_frame (GEN_INT (arg_words),
GEN_INT (nfakes)))) = 1;
else
RTX_FRAME_RELATED_P (emit_insn
(gen_addsi3
(gen_rtx_REG (SImode, OPTOP_REG),
gen_rtx_REG (SImode, OPTOP_REG),
GEN_INT (-nfakes * 4)))) = 1;
if (frame_pointer_needed)
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
if (get_frame_size ())
RTX_FRAME_RELATED_P (emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT
(-get_frame_size ())))) = 1;
emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
}
void
pj_expand_epilogue ()
{
if (frame_pointer_needed)
emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
else if (get_frame_size ())
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, GEN_INT (get_frame_size ())));
if (nfakes)
emit_insn (gen_addsi3 (gen_rtx_REG (SImode, OPTOP_REG),
gen_rtx_REG (SImode, OPTOP_REG),
GEN_INT (nfakes * 4)));
if (current_function_varargs || current_function_stdarg)
emit_insn (gen_varargs_finish
(GEN_INT (current_function_args_info.named_words + 1)));
emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
}
const char *
pj_standard_float_constant (op)
rtx op;
{
REAL_VALUE_TYPE r;
enum machine_mode mode = GET_MODE (op);
if (GET_CODE (op) != CONST_DOUBLE || (mode != DFmode && mode != SFmode))
return NULL;
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
if (REAL_VALUES_EQUAL (r, dconst0) && !REAL_VALUE_MINUS_ZERO (r))
return mode == DFmode ? "%*dconst_0" : "%*fconst_0";
if (REAL_VALUES_EQUAL (r, dconst1))
return mode == DFmode ? "%*dconst_1" : "%*fconst_1";
if (REAL_VALUES_EQUAL (r, dconst2))
return mode == DFmode ? 0 : "%*fconst_2";
return NULL;
}
rtx
pj_expand_builtin_va_arg (valist, type)
tree valist;
tree type;
{
tree addr_tree, t;
HOST_WIDE_INT align;
HOST_WIDE_INT rounded_size;
rtx addr;
align = PARM_BOUNDARY / BITS_PER_UNIT;
rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
addr_tree = valist;
addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = copy_to_reg (addr);
if (AGGREGATE_TYPE_P (type) || rounded_size > 8)
{
addr = gen_rtx_MEM (Pmode, addr);
rounded_size = 4;
}
if (rounded_size > 4)
addr = gen_rtx_PLUS (Pmode, addr, GEN_INT (-4));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
build (MINUS_EXPR, TREE_TYPE (valist), valist,
build_int_2 (rounded_size, 0)));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
return addr;
}
int
pj_source_operand (op, mode)
rtx op;
enum machine_mode mode;
{
return !OUTGOING_REG_RTX_P (op) && general_operand (op, mode);
}
int
pj_signed_comparison_operator (op, mode)
rtx op;
enum machine_mode mode;
{
if (mode != GET_MODE (op))
return 0;
switch (GET_CODE (op))
{
case EQ:
case NE:
case LE:
case LT:
case GE:
case GT:
return 1;
default:
return 0;
}
}
int
pj_unsigned_comparison_operator (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (mode != GET_MODE (op))
return 0;
switch (GET_CODE (op))
{
case GTU:
case GEU:
case LTU:
case LEU:
return 1;
default:
return 0;
}
}
#define NOT_UNIQUE (&const0_rtx)
static rtx *
unique_src_operand (pat, reg)
rtx *pat;
rtx reg;
{
register rtx *result = 0;
register const char *fmt;
register int i;
register int j;
if (GET_CODE (*pat) == SET)
{
if (GET_CODE (XEXP (*pat, 0)) == MEM)
result = unique_src_operand (&XEXP (SET_DEST (*pat), 0), reg);
pat = &SET_SRC (*pat);
}
if (GET_CODE (*pat) == REG && REGNO (*pat) == REGNO (reg))
return pat;
fmt = GET_RTX_FORMAT (GET_CODE (*pat));
for (i = GET_RTX_LENGTH (GET_CODE (*pat)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
{
rtx *new_result = unique_src_operand (&XEXP (*pat, i), reg);
if (new_result)
{
if (result)
return NOT_UNIQUE;
result = new_result;
}
}
else if (fmt[i] == 'E')
{
for (j = XVECLEN (*pat, i) - 1; j >= 0; j--)
{
rtx *new_result =
unique_src_operand (&XVECEXP (*pat, i, j), reg);
if (new_result)
{
if (result)
return NOT_UNIQUE;
result = new_result;
}
}
}
}
return result;
}
void
pj_machine_dependent_reorg (insns)
rtx insns;
{
rtx cursor;
if (!optimize || !TARGET_REORG)
return;
for (cursor = insns; cursor; cursor = NEXT_INSN (cursor))
{
rtx links;
rtx cursor_pat;
if ((GET_CODE (cursor) != INSN && GET_CODE (cursor) != JUMP_INSN)
|| GET_CODE (cursor_pat = PATTERN (cursor)) == USE
|| GET_CODE (cursor_pat) == CLOBBER
|| GET_CODE (cursor_pat) == ADDR_VEC
|| GET_CODE (cursor_pat) == ADDR_DIFF_VEC)
continue;
for (links = LOG_LINKS (cursor); links; links = XEXP (links, 1))
{
rtx prev = XEXP (links, 0);
rtx prev_pat;
rtx prev_dest;
rtx prev_src;
rtx *dst_place;
if (GET_CODE (prev) == INSN
&& GET_CODE (prev_pat = PATTERN (prev)) == SET
&& GET_CODE (prev_dest = SET_DEST (prev_pat)) == REG
&& dead_or_set_p (cursor, prev_dest)
&& !reg_used_between_p (prev_dest, prev, cursor)
&& no_labels_between_p (prev, cursor)
&& no_jumps_between_p (prev, cursor)
&& !modified_between_p ((prev_src = SET_SRC (prev_pat)), prev,
cursor)
&& (dst_place = unique_src_operand (&cursor_pat, prev_dest))
&& dst_place != NOT_UNIQUE
&& REGNO (prev_dest) != OPTOP_REG
&& GET_MODE (prev_dest) != XFmode
&& GET_MODE (*dst_place) == GET_MODE (SET_DEST (prev_pat)))
{
*dst_place = SET_SRC (prev_pat);
PUT_CODE (prev, NOTE);
NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;
}
}
}
}