summaryrefslogtreecommitdiff
path: root/gcc/config/mn10300/mn10300.c
diff options
context:
space:
mode:
authorYamaArashi <shadow962@live.com>2016-02-11 01:12:34 -0800
committerYamaArashi <shadow962@live.com>2016-02-11 01:12:34 -0800
commitb84b6b23fa58beb5674b37279742eb65461ca076 (patch)
treea85da124cbf9f888a31b750ede3a832c2c6b96aa /gcc/config/mn10300/mn10300.c
parent23e2a17097740709d4466a802e03992116b12900 (diff)
delete irrelevant configs
Diffstat (limited to 'gcc/config/mn10300/mn10300.c')
-rwxr-xr-xgcc/config/mn10300/mn10300.c1006
1 files changed, 0 insertions, 1006 deletions
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
deleted file mode 100755
index 325d8bd..0000000
--- a/gcc/config/mn10300/mn10300.c
+++ /dev/null
@@ -1,1006 +0,0 @@
-/* Subroutines for insn-output.c for Matsushita MN10300 series
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
- Contributed by Jeff Law (law@cygnus.com).
-
-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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "config.h"
-#include <stdio.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"
-#include "flags.h"
-#include "recog.h"
-#include "expr.h"
-#include "tree.h"
-#include "obstack.h"
-
-/* The size of the callee register save area. Right now we save everything
- on entry since it costs us nothing in code size. It does cost us from a
- speed standpoint, so we want to optimize this sooner or later. */
-#define REG_SAVE_BYTES (4 * regs_ever_live[2] \
- + 4 * regs_ever_live[3] \
- + 4 * regs_ever_live[6] \
- + 4 * regs_ever_live[7])
-
-#undef REG_SAVE_BYTES
-#define REG_SAVE_BYTES (4 * regs_ever_live[2] \
- + 4 * regs_ever_live[3] \
- + 4 * regs_ever_live[6] \
- + 4 * regs_ever_live[7] \
- + 16 * (regs_ever_live[14] || regs_ever_live[15] \
- || regs_ever_live[16] || regs_ever_live[17]))
-
-void
-asm_file_start (file)
- FILE *file;
-{
- fprintf (file, "#\tGCC For the Matsushita MN10300\n");
- if (optimize)
- fprintf (file, "# -O%d\n", optimize);
- else
- fprintf (file, "\n\n");
-
- if (TARGET_AM33)
- fprintf (file, "\t.am33\n");
- output_file_directive (file, main_input_filename);
-}
-
-
-/* Print operand X using operand code CODE to assembly language output file
- FILE. */
-
-void
-print_operand (file, x, code)
- FILE *file;
- rtx x;
- int code;
-{
- switch (code)
- {
- case 'b':
- case 'B':
- /* These are normal and reversed branches. */
- switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
- {
- case NE:
- fprintf (file, "ne");
- break;
- case EQ:
- fprintf (file, "eq");
- break;
- case GE:
- fprintf (file, "ge");
- break;
- case GT:
- fprintf (file, "gt");
- break;
- case LE:
- fprintf (file, "le");
- break;
- case LT:
- fprintf (file, "lt");
- break;
- case GEU:
- fprintf (file, "cc");
- break;
- case GTU:
- fprintf (file, "hi");
- break;
- case LEU:
- fprintf (file, "ls");
- break;
- case LTU:
- fprintf (file, "cs");
- break;
- default:
- abort ();
- }
- break;
- case 'C':
- /* This is used for the operand to a call instruction;
- if it's a REG, enclose it in parens, else output
- the operand normally. */
- if (GET_CODE (x) == REG)
- {
- fputc ('(', file);
- print_operand (file, x, 0);
- fputc (')', file);
- }
- else
- print_operand (file, x, 0);
- break;
-
- /* These are the least significant word in a 64bit value. */
- case 'L':
- switch (GET_CODE (x))
- {
- case MEM:
- fputc ('(', file);
- output_address (XEXP (x, 0));
- fputc (')', file);
- break;
-
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- break;
-
- case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
- break;
-
- case CONST_DOUBLE:
- {
- long val[2];
- REAL_VALUE_TYPE rv;
-
- switch (GET_MODE (x))
- {
- case DFmode:
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
- print_operand_address (file, GEN_INT (val[0]));
- break;;
- case SFmode:
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
- print_operand_address (file, GEN_INT (val[0]));
- break;;
- case VOIDmode:
- case DImode:
- print_operand_address (file,
- GEN_INT (CONST_DOUBLE_LOW (x)));
- break;
- }
- break;
- }
-
- case CONST_INT:
- print_operand_address (file, x);
- break;
-
- default:
- abort ();
- }
- break;
-
- /* Similarly, but for the most significant word. */
- case 'H':
- switch (GET_CODE (x))
- {
- case MEM:
- fputc ('(', file);
- x = adj_offsettable_operand (x, 4);
- output_address (XEXP (x, 0));
- fputc (')', file);
- break;
-
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
- break;
-
- case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
- break;
-
- case CONST_DOUBLE:
- {
- long val[2];
- REAL_VALUE_TYPE rv;
-
- switch (GET_MODE (x))
- {
- case DFmode:
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
- print_operand_address (file, GEN_INT (val[1]));
- break;;
- case SFmode:
- abort ();
- case VOIDmode:
- case DImode:
- print_operand_address (file,
- GEN_INT (CONST_DOUBLE_HIGH (x)));
- break;
- }
- break;
- }
-
- case CONST_INT:
- if (INTVAL (x) < 0)
- print_operand_address (file, GEN_INT (-1));
- else
- print_operand_address (file, GEN_INT (0));
- break;
- default:
- abort ();
- }
- break;
-
- case 'A':
- fputc ('(', file);
- if (GET_CODE (XEXP (x, 0)) == REG)
- output_address (gen_rtx (PLUS, SImode, XEXP (x, 0), GEN_INT (0)));
- else
- output_address (XEXP (x, 0));
- fputc (')', file);
- break;
-
- case 'N':
- output_address (GEN_INT ((~INTVAL (x)) & 0xff));
- break;
-
- /* For shift counts. The hardware ignores the upper bits of
- any immediate, but the assembler will flag an out of range
- shift count as an error. So we mask off the high bits
- of the immediate here. */
- case 'S':
- if (GET_CODE (x) == CONST_INT)
- {
- fprintf (file, "%d", INTVAL (x) & 0x1f);
- break;
- }
- /* FALL THROUGH */
-
- default:
- switch (GET_CODE (x))
- {
- case MEM:
- fputc ('(', file);
- output_address (XEXP (x, 0));
- fputc (')', file);
- break;
-
- case PLUS:
- output_address (x);
- break;
-
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- break;
-
- case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
- break;
-
- /* This will only be single precision.... */
- case CONST_DOUBLE:
- {
- unsigned long val;
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- print_operand_address (file, GEN_INT (val));
- break;
- }
-
- case CONST_INT:
- case SYMBOL_REF:
- case CONST:
- case LABEL_REF:
- case CODE_LABEL:
- print_operand_address (file, x);
- break;
- default:
- abort ();
- }
- break;
- }
-}
-
-/* Output assembly language output for the address ADDR to FILE. */
-
-void
-print_operand_address (file, addr)
- FILE *file;
- rtx addr;
-{
- switch (GET_CODE (addr))
- {
- case POST_INC:
- print_operand_address (file, XEXP (addr, 0));
- fputc ('+', file);
- break;
- case REG:
- if (addr == stack_pointer_rtx)
- print_operand_address (file, gen_rtx (PLUS, SImode,
- stack_pointer_rtx,
- GEN_INT (0)));
- else
- print_operand (file, addr, 0);
- break;
- case PLUS:
- {
- rtx base, index;
- if (REG_P (XEXP (addr, 0))
- && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
- base = XEXP (addr, 0), index = XEXP (addr, 1);
- else if (REG_P (XEXP (addr, 1))
- && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
- base = XEXP (addr, 1), index = XEXP (addr, 0);
- else
- abort ();
- print_operand (file, index, 0);
- fputc (',', file);
- print_operand (file, base, 0);;
- break;
- }
- case SYMBOL_REF:
- output_addr_const (file, addr);
- break;
- default:
- output_addr_const (file, addr);
- break;
- }
-}
-
-int
-can_use_return_insn ()
-{
- /* size includes the fixed stack space needed for function calls. */
- int size = get_frame_size () + current_function_outgoing_args_size;
-
- /* And space for the return pointer. */
- size += current_function_outgoing_args_size ? 4 : 0;
-
- return (reload_completed
- && size == 0
- && !regs_ever_live[2]
- && !regs_ever_live[3]
- && !regs_ever_live[6]
- && !regs_ever_live[7]
- && !regs_ever_live[14]
- && !regs_ever_live[15]
- && !regs_ever_live[16]
- && !regs_ever_live[17]
- && !frame_pointer_needed);
-}
-
-void
-expand_prologue ()
-{
- unsigned int size;
-
- /* SIZE includes the fixed stack space needed for function calls. */
- size = get_frame_size () + current_function_outgoing_args_size;
- size += (current_function_outgoing_args_size ? 4 : 0);
-
- /* If this is an old-style varargs function, then its arguments
- need to be flushed back to the stack. */
- if (current_function_varargs)
- {
- emit_move_insn (gen_rtx (MEM, SImode,
- gen_rtx (PLUS, Pmode, stack_pointer_rtx,
- GEN_INT (4))),
- gen_rtx (REG, SImode, 0));
- emit_move_insn (gen_rtx (MEM, SImode,
- gen_rtx (PLUS, Pmode, stack_pointer_rtx,
- GEN_INT (8))),
- gen_rtx (REG, SImode, 1));
- }
-
- /* And now store all the registers onto the stack with a
- single two byte instruction. */
- if (regs_ever_live[2] || regs_ever_live[3]
- || regs_ever_live[6] || regs_ever_live[7]
- || regs_ever_live[14] || regs_ever_live[15]
- || regs_ever_live[16] || regs_ever_live[17]
- || frame_pointer_needed)
- emit_insn (gen_store_movm ());
-
- /* Now put the frame pointer into the frame pointer register. */
- if (frame_pointer_needed)
- emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-
- /* Allocate stack for this frame. */
- if (size)
- emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-size)));
-}
-
-void
-expand_epilogue ()
-{
- unsigned int size;
-
- /* SIZE includes the fixed stack space needed for function calls. */
- size = get_frame_size () + current_function_outgoing_args_size;
- size += (current_function_outgoing_args_size ? 4 : 0);
-
- /* Maybe cut back the stack, except for the register save area.
-
- If the frame pointer exists, then use the frame pointer to
- cut back the stack.
-
- If the stack size + register save area is more than 255 bytes,
- then the stack must be cut back here since the size + register
- save size is too big for a ret/retf instruction.
-
- Else leave it alone, it will be cut back as part of the
- ret/retf instruction, or there wasn't any stack to begin with.
-
- Under no circumstanes should the register save area be
- deallocated here, that would leave a window where an interrupt
- could occur and trash the register save area. */
- if (frame_pointer_needed)
- {
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- size = 0;
- }
- else if ((regs_ever_live[2] || regs_ever_live[3]
- || regs_ever_live[14] || regs_ever_live[15]
- || regs_ever_live[16] || regs_ever_live[17]
- || regs_ever_live[6] || regs_ever_live[7])
- && size + REG_SAVE_BYTES > 255)
- {
- emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (size)));
- size = 0;
- }
-
- /* For simplicity, we just movm all the callee saved registers to
- the stack with one instruction.
-
- ?!? Only save registers which are actually used. Reduces
- stack requirements and is faster. */
- if (regs_ever_live[2] || regs_ever_live[3]
- || regs_ever_live[6] || regs_ever_live[7]
- || regs_ever_live[14] || regs_ever_live[15]
- || regs_ever_live[16] || regs_ever_live[17]
- || frame_pointer_needed)
- emit_jump_insn (gen_return_internal_regs (GEN_INT (size + REG_SAVE_BYTES)));
- else
- {
- if (size)
- {
- emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (size)));
- emit_jump_insn (gen_return_internal ());
- }
- else
- {
- emit_jump_insn (gen_return ());
- }
- }
-}
-
-/* Update the condition code from the insn. */
-
-void
-notice_update_cc (body, insn)
- rtx body;
- rtx insn;
-{
- switch (get_attr_cc (insn))
- {
- case CC_NONE:
- /* Insn does not affect CC at all. */
- break;
-
- case CC_NONE_0HIT:
- /* Insn does not change CC, but the 0'th operand has been changed. */
- if (cc_status.value1 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
- cc_status.value1 = 0;
- break;
-
- case CC_SET_ZN:
- /* Insn sets the Z,N flags of CC to recog_operand[0].
- V,C are unusable. */
- CC_STATUS_INIT;
- cc_status.flags |= CC_NO_CARRY | CC_OVERFLOW_UNUSABLE;
- cc_status.value1 = recog_operand[0];
- break;
-
- case CC_SET_ZNV:
- /* Insn sets the Z,N,V flags of CC to recog_operand[0].
- C is unusable. */
- CC_STATUS_INIT;
- cc_status.flags |= CC_NO_CARRY;
- cc_status.value1 = recog_operand[0];
- break;
-
- case CC_COMPARE:
- /* The insn is a compare instruction. */
- CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (body);
- break;
-
- case CC_INVERT:
- /* The insn is a compare instruction. */
- CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (body);
- cc_status.flags |= CC_INVERTED;
- break;
-
- case CC_CLOBBER:
- /* Insn doesn't leave CC in a usable state. */
- CC_STATUS_INIT;
- break;
-
- default:
- abort ();
- }
-}
-
-/* Return true if OP is a valid call operand. */
-
-int
-call_address_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
-}
-
-/* What (if any) secondary registers are needed to move IN with mode
- MODE into a register from in register class CLASS.
-
- We might be able to simplify this. */
-enum reg_class
-secondary_reload_class (class, mode, in)
- enum reg_class class;
- enum machine_mode mode;
- rtx in;
-{
- int regno;
-
- /* Memory loads less than a full word wide can't have an
- address or stack pointer destination. They must use
- a data register as an intermediate register. */
- if (GET_CODE (in) == MEM
- && (mode == QImode || mode == HImode)
- && (class == ADDRESS_REGS || class == SP_REGS))
- {
- if (TARGET_AM33)
- return DATA_OR_EXTENDED_REGS;
- return DATA_REGS;
- }
-
- /* We can't directly load sp + const_int into a data register;
- we must use an address register as an intermediate. */
- if (class != SP_REGS
- && class != ADDRESS_REGS
- && class != SP_OR_ADDRESS_REGS
- && class != SP_OR_EXTENDED_REGS
- && class != ADDRESS_OR_EXTENDED_REGS
- && class != SP_OR_ADDRESS_OR_EXTENDED_REGS
- && (in == stack_pointer_rtx
- || (GET_CODE (in) == PLUS
- && (XEXP (in, 0) == stack_pointer_rtx
- || XEXP (in, 1) == stack_pointer_rtx))))
- return ADDRESS_REGS;
-
- if (GET_CODE (in) == PLUS
- && (XEXP (in, 0) == stack_pointer_rtx
- || XEXP (in, 1) == stack_pointer_rtx))
- {
- if (TARGET_AM33)
- return DATA_OR_EXTENDED_REGS;
- return DATA_REGS;
- }
-
- /* Otherwise assume no secondary reloads are needed. */
- return NO_REGS;
-}
-
-int
-initial_offset (from, to)
- int from, to;
-{
- /* The difference between the argument pointer and the frame pointer
- is the size of the callee register save area. */
- if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- {
- if (regs_ever_live[2] || regs_ever_live[3]
- || regs_ever_live[6] || regs_ever_live[7]
- || regs_ever_live[14] || regs_ever_live[15]
- || regs_ever_live[16] || regs_ever_live[17]
- || frame_pointer_needed)
- return REG_SAVE_BYTES;
- else
- return 0;
- }
-
- /* The difference between the argument pointer and the stack pointer is
- the sum of the size of this function's frame, the callee register save
- area, and the fixed stack space needed for function calls (if any). */
- if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- {
- if (regs_ever_live[2] || regs_ever_live[3]
- || regs_ever_live[6] || regs_ever_live[7]
- || regs_ever_live[14] || regs_ever_live[15]
- || regs_ever_live[16] || regs_ever_live[17]
- || frame_pointer_needed)
- return (get_frame_size () + REG_SAVE_BYTES
- + (current_function_outgoing_args_size
- ? current_function_outgoing_args_size + 4 : 0));
- else
- return (get_frame_size ()
- + (current_function_outgoing_args_size
- ? current_function_outgoing_args_size + 4 : 0));
- }
-
- /* The difference between the frame pointer and stack pointer is the sum
- of the size of this function's frame and the fixed stack space needed
- for function calls (if any). */
- if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- return (get_frame_size ()
- + (current_function_outgoing_args_size
- ? current_function_outgoing_args_size + 4 : 0));
-
- abort ();
-}
-
-/* Flush the argument registers to the stack for a stdarg function;
- return the new argument pointer. */
-rtx
-mn10300_builtin_saveregs (arglist)
- tree arglist;
-{
- rtx offset;
- tree fntype = TREE_TYPE (current_function_decl);
- int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
- && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
- != void_type_node)))
- ? UNITS_PER_WORD : 0);
-
- if (argadj)
- offset = plus_constant (current_function_arg_offset_rtx, argadj);
- else
- offset = current_function_arg_offset_rtx;
-
- emit_move_insn (gen_rtx (MEM, SImode, current_function_internal_arg_pointer),
- gen_rtx (REG, SImode, 0));
- emit_move_insn (gen_rtx (MEM, SImode,
- plus_constant
- (current_function_internal_arg_pointer, 4)),
- gen_rtx (REG, SImode, 1));
- return copy_to_reg (expand_binop (Pmode, add_optab,
- current_function_internal_arg_pointer,
- offset, 0, 0, OPTAB_LIB_WIDEN));
-}
-
-/* Return an RTX to represent where a value with mode MODE will be returned
- from a function. If the result is 0, the argument is pushed. */
-
-rtx
-function_arg (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
-{
- rtx result = 0;
- int size, align;
-
- /* We only support using 2 data registers as argument registers. */
- int nregs = 2;
-
- /* Figure out the size of the object to be passed. */
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
-
- /* Figure out the alignment of the object to be passed. */
- align = size;
-
- cum->nbytes = (cum->nbytes + 3) & ~3;
-
- /* Don't pass this arg via a register if all the argument registers
- are used up. */
- if (cum->nbytes > nregs * UNITS_PER_WORD)
- return 0;
-
- /* Don't pass this arg via a register if it would be split between
- registers and memory. */
- if (type == NULL_TREE
- && cum->nbytes + size > nregs * UNITS_PER_WORD)
- return 0;
-
- switch (cum->nbytes / UNITS_PER_WORD)
- {
- case 0:
- result = gen_rtx (REG, mode, 0);
- break;
- case 1:
- result = gen_rtx (REG, mode, 1);
- break;
- default:
- result = 0;
- }
-
- return result;
-}
-
-/* Return the number of registers to use for an argument passed partially
- in registers and partially in memory. */
-
-int
-function_arg_partial_nregs (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
-{
- int size, align;
-
- /* We only support using 2 data registers as argument registers. */
- int nregs = 2;
-
- /* Figure out the size of the object to be passed. */
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
-
- /* Figure out the alignment of the object to be passed. */
- align = size;
-
- cum->nbytes = (cum->nbytes + 3) & ~3;
-
- /* Don't pass this arg via a register if all the argument registers
- are used up. */
- if (cum->nbytes > nregs * UNITS_PER_WORD)
- return 0;
-
- if (cum->nbytes + size <= nregs * UNITS_PER_WORD)
- return 0;
-
- /* Don't pass this arg via a register if it would be split between
- registers and memory. */
- if (type == NULL_TREE
- && cum->nbytes + size > nregs * UNITS_PER_WORD)
- return 0;
-
- return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
-}
-
-/* Output a tst insn. */
-char *
-output_tst (operand, insn)
- rtx operand, insn;
-{
- rtx temp;
- int past_call = 0;
-
- /* We can save a byte if we can find a register which has the value
- zero in it. */
- temp = PREV_INSN (insn);
- while (optimize && temp)
- {
- rtx set;
-
- /* We allow the search to go through call insns. We record
- the fact that we've past a CALL_INSN and reject matches which
- use call clobbered registers. */
- if (GET_CODE (temp) == CODE_LABEL
- || GET_CODE (temp) == JUMP_INSN
- || GET_CODE (temp) == BARRIER)
- break;
-
- if (GET_CODE (temp) == CALL_INSN)
- past_call = 1;
-
- if (GET_CODE (temp) == NOTE)
- {
- temp = PREV_INSN (temp);
- continue;
- }
-
- /* It must be an insn, see if it is a simple set. */
- set = single_set (temp);
- if (!set)
- {
- temp = PREV_INSN (temp);
- continue;
- }
-
- /* Are we setting a data register to zero (this does not win for
- address registers)?
-
- If it's a call clobbered register, have we past a call?
-
- Make sure the register we find isn't the same as ourself;
- the mn10300 can't encode that.
-
- ??? reg_set_between_p return nonzero anytime we pass a CALL_INSN
- so the code to detect calls here isn't doing anything useful. */
- if (REG_P (SET_DEST (set))
- && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
- && !reg_set_between_p (SET_DEST (set), temp, insn)
- && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
- == REGNO_REG_CLASS (REGNO (operand)))
- && REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
- && REGNO (SET_DEST (set)) != REGNO (operand)
- && (!past_call
- || !call_used_regs[REGNO (SET_DEST (set))]))
- {
- rtx xoperands[2];
- xoperands[0] = operand;
- xoperands[1] = SET_DEST (set);
-
- output_asm_insn ("cmp %1,%0", xoperands);
- return "";
- }
-
- if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
- && REG_P (SET_DEST (set))
- && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
- && !reg_set_between_p (SET_DEST (set), temp, insn)
- && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
- != REGNO_REG_CLASS (REGNO (operand)))
- && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
- && REGNO (SET_DEST (set)) != REGNO (operand)
- && (!past_call
- || !call_used_regs[REGNO (SET_DEST (set))]))
- {
- rtx xoperands[2];
- xoperands[0] = operand;
- xoperands[1] = SET_DEST (set);
-
- output_asm_insn ("cmp %1,%0", xoperands);
- return "";
- }
-
- temp = PREV_INSN (temp);
- }
- return "cmp 0,%0";
-}
-
-int
-impossible_plus_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- extern rtx *reg_equiv_mem;
- rtx reg1, reg2;
-
- if (GET_CODE (op) != PLUS)
- return 0;
-
- if (XEXP (op, 0) == stack_pointer_rtx
- || XEXP (op, 1) == stack_pointer_rtx)
- return 1;
-
- return 0;
-}
-
-/* Return 1 if X is a CONST_INT that is only 8 bits wide. This is used
- for the btst insn which may examine memory or a register (the memory
- variant only allows an unsigned 8 bit integer). */
-int
-const_8bit_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) >= 0
- && INTVAL (op) < 256);
-}
-
-/* Similarly, but when using a zero_extract pattern for a btst where
- the source operand might end up in memory. */
-int
-mask_ok_for_mem_btst (len, bit)
- int len;
- int bit;
-{
- int mask = 0;
-
- while (len > 0)
- {
- mask |= (1 << bit);
- bit++;
- len--;
- }
-
- /* MASK must bit into an 8bit value. */
- return (((mask & 0xff) == mask)
- || ((mask & 0xff00) == mask)
- || ((mask & 0xff0000) == mask)
- || ((mask & 0xff000000) == mask));
-}
-
-/* Return 1 if X contains a symbolic expression. We know these
- expressions will have one of a few well defined forms, so
- we need only check those forms. */
-int
-symbolic_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
- case CONST:
- op = XEXP (op, 0);
- return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
- default:
- return 0;
- }
-}
-
-/* Try machine dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new valid address.
- This macro is used in only one place: `memory_address' in explow.c.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE and WIN are passed so that this macro can use
- GO_IF_LEGITIMATE_ADDRESS.
-
- Normally it is always safe for this macro to do nothing. It exists to
- recognize opportunities to optimize the output.
-
- But on a few ports with segmented architectures and indexed addressing
- (mn10300, hppa) it is used to rewrite certain problematical addresses. */
-rtx
-legitimize_address (x, oldx, mode)
- rtx x;
- rtx oldx;
- enum machine_mode mode;
-{
- /* Uh-oh. We might have an address for x[n-100000]. This needs
- special handling to avoid creating an indexed memory address
- with x-100000 as the base. */
- if (GET_CODE (x) == PLUS
- && symbolic_operand (XEXP (x, 1), VOIDmode))
- {
- /* Ugly. We modify things here so that the address offset specified
- by the index expression is computed first, then added to x to form
- the entire address. */
-
- rtx regx1, regx2, regy1, regy2, y;
-
- /* Strip off any CONST. */
- y = XEXP (x, 1);
- if (GET_CODE (y) == CONST)
- y = XEXP (y, 0);
-
- if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
- {
- regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
- regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
- regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
- regx1 = force_reg (Pmode,
- gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
- return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
- }
- }
- return x;
-}