aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i960/i960.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i960/i960.c')
-rw-r--r--gcc/config/i960/i960.c125
1 files changed, 100 insertions, 25 deletions
diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c
index 6aec8c50239..102729e444b 100644
--- a/gcc/config/i960/i960.c
+++ b/gcc/config/i960/i960.c
@@ -46,6 +46,8 @@ Boston, MA 02111-1307, USA. */
static void i960_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void i960_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void i960_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
@@ -98,13 +100,54 @@ static int ret_label = 0;
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE i960_output_function_epilogue
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK i960_output_mi_thunk
+#undef TARGET_CAN_ASM_OUTPUT_MI_THUNK
+#define TARGET_CAN_ASM_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
struct gcc_target targetm = TARGET_INITIALIZER;
-/* Initialize variables before compiling any files. */
+/* Override conflicting target switch options.
+ Doesn't actually detect if more than one -mARCH option is given, but
+ does handle the case of two blatantly conflicting -mARCH options.
+
+ Also initialize variables before compiling any files. */
void
i960_initialize ()
{
+ if (TARGET_K_SERIES && TARGET_C_SERIES)
+ {
+ warning ("conflicting architectures defined - using C series");
+ target_flags &= ~TARGET_FLAG_K_SERIES;
+ }
+ if (TARGET_K_SERIES && TARGET_MC)
+ {
+ warning ("conflicting architectures defined - using K series");
+ target_flags &= ~TARGET_FLAG_MC;
+ }
+ if (TARGET_C_SERIES && TARGET_MC)
+ {
+ warning ("conflicting architectures defined - using C series");
+ target_flags &= ~TARGET_FLAG_MC;
+ }
+ if (TARGET_IC_COMPAT3_0)
+ {
+ flag_short_enums = 1;
+ flag_signed_char = 1;
+ target_flags |= TARGET_FLAG_CLEAN_LINKAGE;
+ if (TARGET_IC_COMPAT2_0)
+ {
+ warning ("iC2.0 and iC3.0 are incompatible - using iC3.0");
+ target_flags &= ~TARGET_FLAG_IC_COMPAT2_0;
+ }
+ }
+ if (TARGET_IC_COMPAT2_0)
+ {
+ flag_signed_char = 1;
+ target_flags |= TARGET_FLAG_CLEAN_LINKAGE;
+ }
+
if (TARGET_IC_COMPAT2_0)
{
i960_maxbitalignment = 8;
@@ -115,6 +158,9 @@ i960_initialize ()
i960_maxbitalignment = 128;
i960_last_maxbitalignment = 8;
}
+
+ /* Tell the compiler which flavor of TFmode we're using. */
+ real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
}
/* Return true if OP can be used as the source of an fp move insn. */
@@ -321,8 +367,8 @@ bitpos (val)
return -1;
}
-/* Return non-zero if OP is a mask, i.e. all one bits are consecutive.
- The return value indicates how many consecutive non-zero bits exist
+/* Return nonzero if OP is a mask, i.e. all one bits are consecutive.
+ The return value indicates how many consecutive nonzero bits exist
if this is a mask. This is the same as the next function, except that
it does not indicate what the start and stop bit positions are. */
@@ -764,13 +810,13 @@ i960_output_ldconst (dst, src)
output_asm_insn ("ldconst %1,%0", operands);
return "";
}
- else if (mode == XFmode)
+ else if (mode == TFmode)
{
REAL_VALUE_TYPE d;
long value_long[3];
int i;
- if (fp_literal_zero (src, XFmode))
+ if (fp_literal_zero (src, TFmode))
return "movt 0,%0";
REAL_VALUE_FROM_CONST_DOUBLE (d, src);
@@ -1746,7 +1792,6 @@ i960_print_operand (file, x, code)
}
else if (rtxcode == CONST_DOUBLE)
{
- REAL_VALUE_TYPE d;
char dstr[30];
if (x == CONST0_RTX (GET_MODE (x)))
@@ -1760,8 +1805,7 @@ i960_print_operand (file, x, code)
return;
}
- REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- REAL_VALUE_TO_DECIMAL (d, "%#g", dstr);
+ real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
fprintf (file, "0f%s", dstr);
return;
}
@@ -2169,7 +2213,7 @@ hard_regno_mode_ok (regno, mode)
case DImode: case DFmode:
return (regno & 1) == 0;
- case TImode: case XFmode:
+ case TImode: case TFmode:
return (regno & 3) == 0;
default:
@@ -2180,7 +2224,7 @@ hard_regno_mode_ok (regno, mode)
{
switch (mode)
{
- case SFmode: case DFmode: case XFmode:
+ case SFmode: case DFmode: case TFmode:
case SCmode: case DCmode:
return 1;
@@ -2358,14 +2402,7 @@ i960_arg_size_and_align (mode, type, size_out, align_out)
size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (type == 0)
- {
- /* ??? This is a hack to properly correct the alignment of XFmode
- values without affecting anything else. */
- if (size == 3)
- align = 4;
- else
- align = size;
- }
+ align = size;
else if (TYPE_ALIGN (type) >= BITS_PER_WORD)
align = TYPE_ALIGN (type) / BITS_PER_WORD;
else
@@ -2464,11 +2501,18 @@ i960_object_bytes_bitalign (n)
MIN (pragma align, structure size alignment)). */
int
-i960_round_align (align, tsize)
+i960_round_align (align, type)
int align;
- tree tsize;
+ tree type;
{
int new_align;
+ tree tsize;
+
+ if (TARGET_OLD_ALIGN || TYPE_PACKED (type))
+ return align;
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return align;
+ tsize = TYPE_SIZE (type);
if (! tsize || TREE_CODE (tsize) != INTEGER_CST)
return align;
@@ -2513,16 +2557,20 @@ i960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
if (cum->ca_nstackparms == 0 && first_reg < NPARM_REGS && !no_rtl)
{
rtx label = gen_label_rtx ();
- rtx regblock;
+ rtx regblock, fake_arg_pointer_rtx;
- /* If arg_pointer_rtx == 0, no arguments were passed on the stack
+ /* Use a different rtx than arg_pointer_rtx so that cse and friends
+ can go on believing that the argument pointer can never be zero. */
+ fake_arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);
+
+ /* If the argument pointer is 0, no arguments were passed on the stack
and we need to allocate a chunk to save the registers (if any
arguments were passed on the stack the caller would allocate the
48 bytes as well). We must allocate all 48 bytes (12*4) because
va_start assumes it. */
- emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx));
+ emit_insn (gen_cmpsi (fake_arg_pointer_rtx, const0_rtx));
emit_jump_insn (gen_bne (label));
- emit_insn (gen_rtx_SET (VOIDmode, arg_pointer_rtx,
+ emit_insn (gen_rtx_SET (VOIDmode, fake_arg_pointer_rtx,
stack_pointer_rtx));
emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
memory_address (SImode,
@@ -2559,6 +2607,7 @@ i960_va_start (valist, nextarg)
rtx nextarg ATTRIBUTE_UNUSED;
{
tree s, t, base, num;
+ rtx fake_arg_pointer_rtx;
/* The array type always decays to a pointer before we get here, so we
can't use ARRAY_REF. */
@@ -2567,7 +2616,10 @@ i960_va_start (valist, nextarg)
build (PLUS_EXPR, unsigned_type_node, valist,
TYPE_SIZE_UNIT (TREE_TYPE (valist))));
- s = make_tree (unsigned_type_node, arg_pointer_rtx);
+ /* Use a different rtx than arg_pointer_rtx so that cse and friends
+ can go on believing that the argument pointer can never be zero. */
+ fake_arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);
+ s = make_tree (unsigned_type_node, fake_arg_pointer_rtx);
t = build (MODIFY_EXPR, unsigned_type_node, base, s);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -2779,3 +2831,26 @@ i960_scan_opcode (p)
break;
}
}
+
+static void
+i960_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
+ tree function;
+{
+ int d = delta;
+ if (d < 0 && d > -32)
+ fprintf (file, "\tsubo %d,g0,g0\n", -d);
+ else if (d > 0 && d < 32)
+ fprintf (file, "\taddo %d,g0,g0\n", d);
+ else
+ {
+ fprintf (file, "\tldconst %d,r5\n", d);
+ fprintf (file, "\taddo r5,g0,g0\n");
+ }
+ fprintf (file, "\tbx ");
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ fprintf (file, "\n");
+}