/* Target Code for R8C/M16C/M32C
- Copyright (C) 2005, 2006, 2007
+ Copyright (C) 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Red Hat.
GCC 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
+ by the Free Software Foundation; either version 3, or (at your
option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
License for more details.
You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "target-def.h"
#include "tm_p.h"
#include "langhooks.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "df.h"
/* Prototypes */
static tree function_vector_handler (tree *, tree, tree, int, bool *);
static int interrupt_p (tree node);
static bool m32c_asm_integer (rtx, unsigned int, int);
-static int m32c_comp_type_attributes (tree, tree);
+static int m32c_comp_type_attributes (const_tree, const_tree);
static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
static struct machine_function *m32c_init_machine_status (void);
static void m32c_insert_attributes (tree, tree *);
static bool m32c_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
- tree, bool);
-static bool m32c_promote_prototypes (tree);
+ const_tree, bool);
+static bool m32c_promote_prototypes (const_tree);
static int m32c_pushm_popm (Push_Pop_Type);
static bool m32c_strict_argument_naming (CUMULATIVE_ARGS *);
static rtx m32c_struct_value_rtx (tree, int);
/* Used by m32c_register_move_cost to determine if a move is
impossibly expensive. */
static int
-class_can_hold_mode (int class, enum machine_mode mode)
+class_can_hold_mode (int rclass, enum machine_mode mode)
{
/* Cache the results: 0=untested 1=no 2=yes */
static char results[LIM_REG_CLASSES][MAX_MACHINE_MODE];
- if (results[class][mode] == 0)
+ if (results[rclass][mode] == 0)
{
int r, n, i;
- results[class][mode] = 1;
+ results[rclass][mode] = 1;
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
- if (class_contents[class][0] & (1 << r)
+ if (class_contents[rclass][0] & (1 << r)
&& HARD_REGNO_MODE_OK (r, mode))
{
int ok = 1;
n = HARD_REGNO_NREGS (r, mode);
for (i = 1; i < n; i++)
- if (!(class_contents[class][0] & (1 << (r + i))))
+ if (!(class_contents[rclass][0] & (1 << (r + i))))
ok = 0;
if (ok)
{
- results[class][mode] = 2;
+ results[rclass][mode] = 2;
break;
}
}
}
#if DEBUG0
fprintf (stderr, "class %s can hold %s? %s\n",
- class_names[class], mode_name[mode],
- (results[class][mode] == 2) ? "yes" : "no");
+ class_names[rclass], mode_name[mode],
+ (results[rclass][mode] == 2) ? "yes" : "no");
#endif
- return results[class][mode] == 2;
+ return results[rclass][mode] == 2;
}
/* Run-time Target Specification. */
#undef TARGET_PROMOTE_FUNCTION_RETURN
#define TARGET_PROMOTE_FUNCTION_RETURN m32c_promote_function_return
bool
-m32c_promote_function_return (tree fntype ATTRIBUTE_UNUSED)
+m32c_promote_function_return (const_tree fntype ATTRIBUTE_UNUSED)
{
return false;
}
/* Implements HARD_REGNO_NREGS. This is complicated by the fact that
different registers are different sizes from each other, *and* may
be different sizes in different chip families. */
-int
-m32c_hard_regno_nregs (int regno, enum machine_mode mode)
+static int
+m32c_hard_regno_nregs_1 (int regno, enum machine_mode mode)
{
if (regno == FLG_REGNO && mode == CCmode)
return 1;
return 0;
}
+int
+m32c_hard_regno_nregs (int regno, enum machine_mode mode)
+{
+ int rv = m32c_hard_regno_nregs_1 (regno, mode);
+ return rv ? rv : 1;
+}
+
/* Implements HARD_REGNO_MODE_OK. The above function does the work
already; just test its return value. */
int
m32c_hard_regno_ok (int regno, enum machine_mode mode)
{
- return m32c_hard_regno_nregs (regno, mode) != 0;
+ return m32c_hard_regno_nregs_1 (regno, mode) != 0;
}
/* Implements MODES_TIEABLE_P. In general, modes aren't tieable since
int b = exact_log2 ((value ^ 0xff) & 0xff);
return (b >= 0 && b <= 7);
}
+ if (memcmp (str, "ImB", 3) == 0)
+ {
+ int b = exact_log2 ((value ^ 0xffff) & 0xffff);
+ return (b >= 0 && b <= 7);
+ }
if (memcmp (str, "Ilw", 3) == 0)
{
int b = exact_log2 (value);
if (TARGET_A24)
{
- mode = SImode;
+ /* It's four bytes */
+ mode = PSImode;
offset = 4;
}
else
case 0:
return A0_REGNO;
case 1:
- return A1_REGNO;
+ if (TARGET_A16)
+ return R3_REGNO;
+ else
+ return R1_REGNO;
default:
return INVALID_REGNUM;
}
{
if (fixed_regs[regno])
return 0;
- if (cfun->calls_eh_return)
+ if (crtl->calls_eh_return)
return 1;
if (regno == FP_REGNO)
return 0;
int n_dwarfs = 0;
int nosave_mask = 0;
- if (cfun->return_rtx
- && GET_CODE (cfun->return_rtx) == PARALLEL
- && !(cfun->calls_eh_return || cfun->machine->is_interrupt))
+ if (crtl->return_rtx
+ && GET_CODE (crtl->return_rtx) == PARALLEL
+ && !(crtl->calls_eh_return || cfun->machine->is_interrupt))
{
- rtx exp = XVECEXP (cfun->return_rtx, 0, 0);
+ rtx exp = XVECEXP (crtl->return_rtx, 0, 0);
rtx rv = XEXP (exp, 0);
int rv_bytes = GET_MODE_SIZE (GET_MODE (rv));
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES m32c_promote_prototypes
static bool
-m32c_promote_prototypes (tree fntype ATTRIBUTE_UNUSED)
+m32c_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
{
return 0;
}
static bool
m32c_pass_by_reference (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
return 0;
/* Implements FUNCTION_VALUE. Functions and libcalls have the same
conventions. */
rtx
-m32c_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+m32c_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
{
/* return reg or parallel */
- enum machine_mode mode = TYPE_MODE (valtype);
+ const enum machine_mode mode = TYPE_MODE (valtype);
return m32c_libcall_value (mode);
}
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS m32c_rtx_costs
static bool
-m32c_rtx_costs (rtx x, int code, int outer_code, int *total)
+m32c_rtx_costs (rtx x, int code, int outer_code, int *total,
+ bool speed ATTRIBUTE_UNUSED)
{
switch (code)
{
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST m32c_address_cost
static int
-m32c_address_cost (rtx addr)
+m32c_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
{
+ int i;
/* fprintf(stderr, "\naddress_cost\n");
debug_rtx(addr);*/
switch (GET_CODE (addr))
{
case CONST_INT:
- return COSTS_N_INSNS(1);
+ i = INTVAL (addr);
+ if (i == 0)
+ return COSTS_N_INSNS(1);
+ if (0 < i && i <= 255)
+ return COSTS_N_INSNS(2);
+ if (0 < i && i <= 65535)
+ return COSTS_N_INSNS(3);
+ return COSTS_N_INSNS(4);
case SYMBOL_REF:
- return COSTS_N_INSNS(3);
+ return COSTS_N_INSNS(4);
case REG:
- return COSTS_N_INSNS(2);
+ return COSTS_N_INSNS(1);
+ case PLUS:
+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ {
+ i = INTVAL (XEXP (addr, 1));
+ if (i == 0)
+ return COSTS_N_INSNS(1);
+ if (0 < i && i <= 255)
+ return COSTS_N_INSNS(2);
+ if (0 < i && i <= 65535)
+ return COSTS_N_INSNS(3);
+ }
+ return COSTS_N_INSNS(4);
default:
return 0;
}
void
m32c_print_operand_address (FILE * stream, rtx address)
{
- gcc_assert (GET_CODE (address) == MEM);
- m32c_print_operand (stream, XEXP (address, 0), 0);
+ if (GET_CODE (address) == MEM)
+ address = XEXP (address, 0);
+ else
+ /* cf: gcc.dg/asm-4.c. */
+ gcc_assert (GET_CODE (address) == REG);
+
+ m32c_print_operand (stream, address, 0);
}
/* Implements ASM_OUTPUT_REG_PUSH. Control registers are pushed
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
static int
-m32c_comp_type_attributes (tree type1 ATTRIBUTE_UNUSED,
- tree type2 ATTRIBUTE_UNUSED)
+m32c_comp_type_attributes (const_tree type1 ATTRIBUTE_UNUSED,
+ const_tree type2 ATTRIBUTE_UNUSED)
{
/* 0=incompatible 1=compatible 2=warning */
return 1;
&& GET_CODE (XEXP (XEXP (XEXP (operands[0], 0), 0), 0)) == SYMBOL_REF
&& MEM_SCALAR_P (operands[0])
&& !MEM_IN_STRUCT_P (operands[0])
- && !(XINT (XEXP (XEXP (XEXP (operands[0], 0), 0), 1), 0) %4)
+ && !(INTVAL (XEXP (XEXP (XEXP (operands[0], 0), 0), 1)) %4)
&& GET_CODE (XEXP (operands[2], 0)) == CONST
&& GET_CODE (XEXP (XEXP (operands[2], 0), 0)) == PLUS
&& GET_CODE (XEXP (XEXP (XEXP (operands[2], 0), 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
&& MEM_SCALAR_P (operands[0])
&& !MEM_IN_STRUCT_P (operands[0])
- && !(XINT (XEXP (XEXP (operands[0], 0), 1), 0) %4)
+ && !(INTVAL (XEXP (XEXP (operands[0], 0), 1)) %4)
&& REGNO (XEXP (XEXP (operands[2], 0), 0)) == FB_REGNO
&& GET_CODE (XEXP (XEXP (operands[2], 0), 1)) == CONST_INT
&& MEM_SCALAR_P (operands[2])
okflag = 0;
break;
case 3:
- offset1 = XINT (XEXP (XEXP (operands[0], 0), 1), 0);
- offset2 = XINT (XEXP (XEXP (operands[2], 0), 1), 0);
+ offset1 = INTVAL (XEXP (XEXP (operands[0], 0), 1));
+ offset2 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
offsetsign = offset1 >> ((sizeof (offset1) * 8) -1);
if (((offset2-offset1) == 2) && offsetsign != 0)
okflag = 1;
HOST_WIDE_INT val;
operands[4] = gen_rtx_MEM (SImode, XEXP (operands[0], 0));
- val = (XINT (operands[3], 0) << 16) + (XINT (operands[1], 0) & 0xFFFF);
+ val = (INTVAL (operands[3]) << 16) + (INTVAL (operands[1]) & 0xFFFF);
operands[5] = gen_rtx_CONST_INT (VOIDmode, val);
return true;
struct sequence_stack *seq;
int rv;
- saved_first = cfun->emit->x_first_insn;
- saved_last = cfun->emit->x_last_insn;
- for (seq = cfun->emit->sequence_stack; seq && seq->next; seq = seq->next)
+ saved_first = crtl->emit.x_first_insn;
+ saved_last = crtl->emit.x_last_insn;
+ for (seq = crtl->emit.sequence_stack; seq && seq->next; seq = seq->next)
;
if (seq)
{
- cfun->emit->x_first_insn = seq->first;
- cfun->emit->x_last_insn = seq->last;
+ crtl->emit.x_first_insn = seq->first;
+ crtl->emit.x_last_insn = seq->last;
}
rv = leaf_function_p ();
- cfun->emit->x_first_insn = saved_first;
- cfun->emit->x_last_insn = saved_last;
+ crtl->emit.x_first_insn = saved_first;
+ crtl->emit.x_last_insn = saved_last;
return rv;
}
rtx fb = gen_rtx_REG (Pmode, FB_REGNO);
insn = get_insns ();
- for (seq = cfun->emit->sequence_stack;
+ for (seq = crtl->emit.sequence_stack;
seq;
insn = seq->first, seq = seq->next);
(fudged), and return (fudged). This is actually easier to do in
assembler, so punt to libgcc. */
emit_jump_insn (gen_eh_epilogue (ret_addr, cfun->machine->eh_stack_adjust));
- /* emit_insn (gen_rtx_CLOBBER (HImode, gen_rtx_REG (HImode, R0L_REGNO))); */
+ /* emit_clobber (gen_rtx_REG (HImode, R0L_REGNO)); */
emit_barrier ();
}
char *
m32c_output_compare (rtx insn, rtx *operands)
{
- static char template[] = ";cmp.b\t%1,%0";
+ static char templ[] = ";cmp.b\t%1,%0";
/* ^ 5 */
- template[5] = " bwll"[GET_MODE_SIZE(GET_MODE(operands[0]))];
+ templ[5] = " bwll"[GET_MODE_SIZE(GET_MODE(operands[0]))];
if (m32c_compare_redundant (insn, operands))
{
#if DEBUG_CMP
fprintf(stderr, "cbranch: cmp not needed\n");
#endif
- return template;
+ return templ;
}
#if DEBUG_CMP
- fprintf(stderr, "cbranch: cmp needed: `%s'\n", template);
+ fprintf(stderr, "cbranch: cmp needed: `%s'\n", templ);
#endif
- return template + 1;
+ return templ + 1;
}
#undef TARGET_ENCODE_SECTION_INFO