Commit 9b6b54e2 by Nick Clifton Committed by Nick Clifton

Add support for Cirrus EP9312, an ARM variant.

From-SVN: r62625
parent 949824fe
2003-02-10 Nick Clifton <nickc@redhat.com>
* Contributed support for the Cirrus EP9312 "Maverick"
floating point co-processor. Written by Aldy Hernandez
<aldyh@redhat.com>.
(config/arm/arm.c): Add Cirrus support.
(config/arm/arm.h): Likewise.
(config/arm/aout.h): Likewise.
(config/arm/arm.md): Likewise.
(config/arm/arm-protos.h): Likewise.
(config.gcc): Likewise.
(doc/invoke.texi): Describe new -mcpu value and new
-mcirrus-fix-invalid-insns switch,
(cirrus.md): New file.
Mon Feb 10 11:40:18 CET 2003 Jan Hubicka <jh@suse.cz> Mon Feb 10 11:40:18 CET 2003 Jan Hubicka <jh@suse.cz>
* combine.c (combine_simplify_rtx): Simplify using * combine.c (combine_simplify_rtx): Simplify using
......
...@@ -259,6 +259,9 @@ strongarm*-*-*) ...@@ -259,6 +259,9 @@ strongarm*-*-*)
arm*-*-*) arm*-*-*)
cpu_type=arm cpu_type=arm
;; ;;
ep9312*-*-*)
cpu_type=arm
;;
xscale-*-*) xscale-*-*)
cpu_type=arm cpu_type=arm
;; ;;
...@@ -700,7 +703,7 @@ arm*-*-rtems*) ...@@ -700,7 +703,7 @@ arm*-*-rtems*)
thread_file='rtems' thread_file='rtems'
fi fi
;; ;;
arm*-*-elf) arm*-*-elf | ep9312-*-elf)
tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h" tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h"
tmake_file=arm/t-arm-elf tmake_file=arm/t-arm-elf
;; ;;
...@@ -2789,6 +2792,7 @@ arm*-*-*) ...@@ -2789,6 +2792,7 @@ arm*-*-*)
| xarm7m | xarm7dm | xarm7dmi | xarm[79]tdmi \ | xarm7m | xarm7dm | xarm7dmi | xarm[79]tdmi \
| xarm7100 | xarm7500 | xarm7500fe | xarm810 \ | xarm7100 | xarm7500 | xarm7500fe | xarm810 \
| xxscale \ | xxscale \
| xep9312 \
| xstrongarm | xstrongarm110 | xstrongarm1100) | xstrongarm | xstrongarm110 | xstrongarm1100)
target_cpu_default2="TARGET_CPU_$with_cpu" target_cpu_default2="TARGET_CPU_$with_cpu"
;; ;;
...@@ -2806,6 +2810,11 @@ arm*-*-*) ...@@ -2806,6 +2810,11 @@ arm*-*-*)
fi fi
;; ;;
esac esac
case $machine in
9ep9312-*-*)
target_cpu_default2="TARGET_CPU_9ep9312"
;;
esac
;; ;;
hppa*-*-* | parisc*-*-*) hppa*-*-* | parisc*-*-*)
......
...@@ -73,7 +73,10 @@ Boston, MA 02111-1307, USA. */ ...@@ -73,7 +73,10 @@ Boston, MA 02111-1307, USA. */
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \ "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"cc", "sfp", "afp" \ "cc", "sfp", "afp", \
"mv0", "mv1", "mv2", "mv3", "mv4", "mv5", \
"mv6", "mv7", "mv8", "mv9", "mv10", "mv11",\
"mv12", "mv13", "mv14", "mv15" \
} }
#endif #endif
...@@ -98,7 +101,71 @@ Boston, MA 02111-1307, USA. */ ...@@ -98,7 +101,71 @@ Boston, MA 02111-1307, USA. */
{"r12", 12}, /* ip */ \ {"r12", 12}, /* ip */ \
{"r13", 13}, /* sp */ \ {"r13", 13}, /* sp */ \
{"r14", 14}, /* lr */ \ {"r14", 14}, /* lr */ \
{"r15", 15} /* pc */ \ {"r15", 15}, /* pc */ \
{"mvf0", 27}, \
{"mvf1", 28}, \
{"mvf2", 29}, \
{"mvf3", 30}, \
{"mvf4", 31}, \
{"mvf5", 32}, \
{"mvf6", 33}, \
{"mvf7", 34}, \
{"mvf8", 35}, \
{"mvf9", 36}, \
{"mvf10", 37}, \
{"mvf11", 38}, \
{"mvf12", 39}, \
{"mvf13", 40}, \
{"mvf14", 41}, \
{"mvf15", 42}, \
{"mvd0", 27}, \
{"mvd1", 28}, \
{"mvd2", 29}, \
{"mvd3", 30}, \
{"mvd4", 31}, \
{"mvd5", 32}, \
{"mvd6", 33}, \
{"mvd7", 34}, \
{"mvd8", 35}, \
{"mvd9", 36}, \
{"mvd10", 37}, \
{"mvd11", 38}, \
{"mvd12", 39}, \
{"mvd13", 40}, \
{"mvd14", 41}, \
{"mvd15", 42}, \
{"mvfx0", 27}, \
{"mvfx1", 28}, \
{"mvfx2", 29}, \
{"mvfx3", 30}, \
{"mvfx4", 31}, \
{"mvfx5", 32}, \
{"mvfx6", 33}, \
{"mvfx7", 34}, \
{"mvfx8", 35}, \
{"mvfx9", 36}, \
{"mvfx10", 37}, \
{"mvfx11", 38}, \
{"mvfx12", 39}, \
{"mvfx13", 40}, \
{"mvfx14", 41}, \
{"mvfx15", 42}, \
{"mvdx0", 27}, \
{"mvdx1", 28}, \
{"mvdx2", 29}, \
{"mvdx3", 30}, \
{"mvdx4", 31}, \
{"mvdx5", 32}, \
{"mvdx6", 33}, \
{"mvdx7", 34}, \
{"mvdx8", 35}, \
{"mvdx9", 36}, \
{"mvdx10", 37}, \
{"mvdx11", 38}, \
{"mvdx12", 39}, \
{"mvdx13", 40}, \
{"mvdx14", 41}, \
{"mvdx15", 42} \
} }
#endif #endif
......
...@@ -94,6 +94,11 @@ extern int logical_binary_operator PARAMS ((rtx, enum machine_mode)); ...@@ -94,6 +94,11 @@ extern int logical_binary_operator PARAMS ((rtx, enum machine_mode));
extern int multi_register_push PARAMS ((rtx, enum machine_mode)); extern int multi_register_push PARAMS ((rtx, enum machine_mode));
extern int load_multiple_operation PARAMS ((rtx, enum machine_mode)); extern int load_multiple_operation PARAMS ((rtx, enum machine_mode));
extern int store_multiple_operation PARAMS ((rtx, enum machine_mode)); extern int store_multiple_operation PARAMS ((rtx, enum machine_mode));
extern int cirrus_fp_register PARAMS ((rtx, enum machine_mode));
extern int cirrus_general_operand PARAMS ((rtx, enum machine_mode));
extern int cirrus_register_operand PARAMS ((rtx, enum machine_mode));
extern int cirrus_shift_const PARAMS ((rtx, enum machine_mode));
extern int cirrus_memory_offset PARAMS ((rtx));
extern int symbol_mentioned_p PARAMS ((rtx)); extern int symbol_mentioned_p PARAMS ((rtx));
extern int label_mentioned_p PARAMS ((rtx)); extern int label_mentioned_p PARAMS ((rtx));
...@@ -149,7 +154,6 @@ extern rtx arm_va_arg PARAMS ((tree, tree)); ...@@ -149,7 +154,6 @@ extern rtx arm_va_arg PARAMS ((tree, tree));
extern int arm_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *, extern int arm_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode, enum machine_mode,
tree, int)); tree, int));
#endif #endif
#if defined AOF_ASSEMBLER #if defined AOF_ASSEMBLER
......
...@@ -62,6 +62,12 @@ typedef struct minipool_fixup Mfix; ...@@ -62,6 +62,12 @@ typedef struct minipool_fixup Mfix;
#define Ulong unsigned long #define Ulong unsigned long
#define Ccstar const char * #define Ccstar const char *
const char extra_reg_names1[][16] =
{ "mv0", "mv1", "mv2", "mv3", "mv4", "mv5", "mv6", "mv7",
"mv8", "mv9", "mv10", "mv11", "mv12", "mv13", "mv14", "mv15"
};
#define extra_reg_names1 bogus1_regnames
const struct attribute_spec arm_attribute_table[]; const struct attribute_spec arm_attribute_table[];
/* Forward function declarations. */ /* Forward function declarations. */
...@@ -144,6 +150,9 @@ static int arm_rtx_costs_1 PARAMS ((rtx, enum rtx_code, ...@@ -144,6 +150,9 @@ static int arm_rtx_costs_1 PARAMS ((rtx, enum rtx_code,
enum rtx_code)); enum rtx_code));
static bool arm_rtx_costs PARAMS ((rtx, int, int, int*)); static bool arm_rtx_costs PARAMS ((rtx, int, int, int*));
static int arm_address_cost PARAMS ((rtx)); static int arm_address_cost PARAMS ((rtx));
static int is_load_address PARAMS ((rtx));
static int is_cirrus_insn PARAMS ((rtx));
static void cirrus_reorg PARAMS ((rtx));
#undef Hint #undef Hint
#undef Mmode #undef Mmode
...@@ -263,6 +272,7 @@ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY; ...@@ -263,6 +272,7 @@ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
#define FL_STRONG (1 << 8) /* StrongARM */ #define FL_STRONG (1 << 8) /* StrongARM */
#define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */ #define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */
#define FL_XSCALE (1 << 10) /* XScale */ #define FL_XSCALE (1 << 10) /* XScale */
#define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */
/* The bits in this mask specify which /* The bits in this mask specify which
instructions we are allowed to generate. */ instructions we are allowed to generate. */
...@@ -301,6 +311,9 @@ int arm_is_xscale = 0; ...@@ -301,6 +311,9 @@ int arm_is_xscale = 0;
/* Nonzero if this chip is an ARM6 or an ARM7. */ /* Nonzero if this chip is an ARM6 or an ARM7. */
int arm_is_6_or_7 = 0; int arm_is_6_or_7 = 0;
/* Nonzero if this chip is a Cirrus/DSP. */
int arm_is_cirrus = 0;
/* Nonzero if generating Thumb instructions. */ /* Nonzero if generating Thumb instructions. */
int thumb_code = 0; int thumb_code = 0;
...@@ -391,6 +404,7 @@ static const struct processors all_cores[] = ...@@ -391,6 +404,7 @@ static const struct processors all_cores[] =
{"arm940t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED }, {"arm940t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
{"arm9tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED }, {"arm9tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
{"arm9e", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED }, {"arm9e", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED },
{"ep9312", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_CIRRUS },
{"strongarm", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG }, {"strongarm", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
{"strongarm110", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG }, {"strongarm110", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
{"strongarm1100", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG }, {"strongarm1100", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
...@@ -417,6 +431,7 @@ static const struct processors all_architectures[] = ...@@ -417,6 +431,7 @@ static const struct processors all_architectures[] =
{ "armv5", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 }, { "armv5", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
{ "armv5t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 }, { "armv5t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
{ "armv5te", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E }, { "armv5te", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
{ "ep9312", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_CIRRUS },
{ NULL, 0 } { NULL, 0 }
}; };
...@@ -514,6 +529,7 @@ arm_override_options () ...@@ -514,6 +529,7 @@ arm_override_options ()
{ TARGET_CPU_arm9, "arm9" }, { TARGET_CPU_arm9, "arm9" },
{ TARGET_CPU_strongarm, "strongarm" }, { TARGET_CPU_strongarm, "strongarm" },
{ TARGET_CPU_xscale, "xscale" }, { TARGET_CPU_xscale, "xscale" },
{ TARGET_CPU_ep9312, "ep9312" },
{ TARGET_CPU_generic, "arm" }, { TARGET_CPU_generic, "arm" },
{ 0, 0 } { 0, 0 }
}; };
...@@ -712,13 +728,23 @@ arm_override_options () ...@@ -712,13 +728,23 @@ arm_override_options ()
thumb_code = (TARGET_ARM == 0); thumb_code = (TARGET_ARM == 0);
arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32)) arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32))
&& !(tune_flags & FL_ARCH4))) != 0; && !(tune_flags & FL_ARCH4))) != 0;
arm_is_cirrus = (tune_flags & FL_CIRRUS) != 0;
/* Default value for floating point code... if no co-processor if (arm_is_cirrus)
bus, then schedule for emulated floating point. Otherwise, {
assume the user has an FPA. arm_fpu = FP_CIRRUS;
Note: this does not prevent use of floating point instructions,
-msoft-float does that. */ /* Ignore -mhard-float if -mcpu=ep9312. */
arm_fpu = (tune_flags & FL_CO_PROC) ? FP_HARD : FP_SOFT3; if (TARGET_HARD_FLOAT)
target_flags ^= ARM_FLAG_SOFT_FLOAT;
}
else
/* Default value for floating point code... if no co-processor
bus, then schedule for emulated floating point. Otherwise,
assume the user has an FPA.
Note: this does not prevent use of floating point instructions,
-msoft-float does that. */
arm_fpu = (tune_flags & FL_CO_PROC) ? FP_HARD : FP_SOFT3;
if (target_fp_name) if (target_fp_name)
{ {
...@@ -733,8 +759,15 @@ arm_override_options () ...@@ -733,8 +759,15 @@ arm_override_options ()
else else
arm_fpu_arch = FP_DEFAULT; arm_fpu_arch = FP_DEFAULT;
if (TARGET_FPE && arm_fpu != FP_HARD) if (TARGET_FPE)
{
if (arm_fpu == FP_SOFT3)
arm_fpu = FP_SOFT2;
else if (arm_fpu == FP_CIRRUS)
warning ("-mpfpe switch not supported by ep9312 target cpu - ignored.");
else if (arm_fpu != FP_HARD)
arm_fpu = FP_SOFT2; arm_fpu = FP_SOFT2;
}
/* For arm2/3 there is no need to do any scheduling if there is only /* For arm2/3 there is no need to do any scheduling if there is only
a floating point emulator, or we are doing software floating-point. */ a floating point emulator, or we are doing software floating-point. */
...@@ -1902,6 +1935,8 @@ arm_return_in_memory (type) ...@@ -1902,6 +1935,8 @@ arm_return_in_memory (type)
int int
arm_float_words_big_endian () arm_float_words_big_endian ()
{ {
if (TARGET_CIRRUS)
return 0;
/* For FPA, float words are always big-endian. For VFP, floats words /* For FPA, float words are always big-endian. For VFP, floats words
follow the memory system mode. */ follow the memory system mode. */
...@@ -2688,6 +2723,12 @@ arm_legitimate_index_p (mode, index, strict_p) ...@@ -2688,6 +2723,12 @@ arm_legitimate_index_p (mode, index, strict_p)
&& INTVAL (index) > -1024 && INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0); && (INTVAL (index) & 3) == 0);
if (TARGET_CIRRUS
&& (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode))
return (code == CONST_INT
&& INTVAL (index) < 255
&& INTVAL (index) > -255);
if (arm_address_register_rtx_p (index, strict_p) if (arm_address_register_rtx_p (index, strict_p)
&& GET_MODE_SIZE (mode) <= 4) && GET_MODE_SIZE (mode) <= 4)
return 1; return 1;
...@@ -3856,6 +3897,262 @@ fpu_add_operand (op, mode) ...@@ -3856,6 +3897,262 @@ fpu_add_operand (op, mode)
return FALSE; return FALSE;
} }
/* Return nonzero if OP is a valid Cirrus memory address pattern. */
int
cirrus_memory_offset (op)
rtx op;
{
/* Reject eliminable registers. */
if (! (reload_in_progress || reload_completed)
&& ( reg_mentioned_p (frame_pointer_rtx, op)
|| reg_mentioned_p (arg_pointer_rtx, op)
|| reg_mentioned_p (virtual_incoming_args_rtx, op)
|| reg_mentioned_p (virtual_outgoing_args_rtx, op)
|| reg_mentioned_p (virtual_stack_dynamic_rtx, op)
|| reg_mentioned_p (virtual_stack_vars_rtx, op)))
return 0;
if (GET_CODE (op) == MEM)
{
rtx ind;
ind = XEXP (op, 0);
/* Match: (mem (reg)). */
if (GET_CODE (ind) == REG)
return 1;
/* Match:
(mem (plus (reg)
(const))). */
if (GET_CODE (ind) == PLUS
&& GET_CODE (XEXP (ind, 0)) == REG
&& REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
&& GET_CODE (XEXP (ind, 1)) == CONST_INT)
return 1;
}
return 0;
}
/* Return nonzero if OP is a Cirrus or general register. */
int
cirrus_register_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
|| REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
}
/* Return nonzero if OP is a cirrus FP register. */
int
cirrus_fp_register (op, mode)
rtx op;
enum machine_mode mode;
{
if (GET_MODE (op) != mode && mode != VOIDmode)
return FALSE;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (GET_CODE (op) == REG
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
}
/* Return nonzero if OP is a 6bit constant (0..63). */
int
cirrus_shift_const (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
return (GET_CODE (op) == CONST_INT
&& INTVAL (op) >= 0
&& INTVAL (op) < 64);
}
/* Return nonzero if INSN is an LDR R0,ADDR instruction. */
static int
is_load_address (insn)
rtx insn;
{
rtx body, lhs, rhs;;
if (!insn)
return 0;
if (GET_CODE (insn) != INSN)
return 0;
body = PATTERN (insn);
if (GET_CODE (body) != SET)
return 0;
lhs = XEXP (body, 0);
rhs = XEXP (body, 1);
return (GET_CODE (lhs) == REG
&& REGNO_REG_CLASS (REGNO (lhs)) == GENERAL_REGS
&& (GET_CODE (rhs) == MEM
|| GET_CODE (rhs) == SYMBOL_REF));
}
/* Return nonzero if INSN is a Cirrus instruction. */
static int
is_cirrus_insn (insn)
rtx insn;
{
enum attr_cirrus attr;
/* get_attr aborts on USE and CLOBBER. */
if (!insn
|| GET_CODE (insn) != INSN
|| GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER)
return 0;
attr = get_attr_cirrus (insn);
return attr != CIRRUS_NO;
}
/* Cirrus reorg for invalid instruction combinations. */
static void
cirrus_reorg (first)
rtx first;
{
enum attr_cirrus attr;
rtx body = PATTERN (first);
rtx t;
int nops;
/* Any branch must be followed by 2 non Cirrus instructions. */
if (GET_CODE (first) == JUMP_INSN && GET_CODE (body) != RETURN)
{
nops = 0;
t = next_nonnote_insn (first);
if (is_cirrus_insn (t))
++ nops;
if (is_cirrus_insn (next_nonnote_insn (t)))
++ nops;
while (nops --)
emit_insn_after (gen_nop (), first);
return;
}
/* (float (blah)) is in parallel with a clobber. */
if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
body = XVECEXP (body, 0, 0);
if (GET_CODE (body) == SET)
{
rtx lhs = XEXP (body, 0), rhs = XEXP (body, 1);
/* cfldrd, cfldr64, cfstrd, cfstr64 must
be followed by a non Cirrus insn. */
if (get_attr_cirrus (first) == CIRRUS_DOUBLE)
{
if (is_cirrus_insn (next_nonnote_insn (first)))
emit_insn_after (gen_nop (), first);
return;
}
else if (is_load_address (first))
{
unsigned int arm_regno;
/* Any ldr/cfmvdlr, ldr/cfmvdhr, ldr/cfmvsr, ldr/cfmv64lr,
ldr/cfmv64hr combination where the Rd field is the same
in both instructions must be split with a non Cirrus
insn. Example:
ldr r0, blah
nop
cfmvsr mvf0, r0. */
/* Get Arm register number for ldr insn. */
if (GET_CODE (lhs) == REG)
arm_regno = REGNO (lhs);
else if (GET_CODE (rhs) == REG)
arm_regno = REGNO (rhs);
else
abort ();
/* Next insn. */
first = next_nonnote_insn (first);
if (!is_cirrus_insn (first))
return;
body = PATTERN (first);
/* (float (blah)) is in parallel with a clobber. */
if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0))
body = XVECEXP (body, 0, 0);
if (GET_CODE (body) == FLOAT)
body = XEXP (body, 0);
if (get_attr_cirrus (first) == CIRRUS_MOVE
&& GET_CODE (XEXP (body, 1)) == REG
&& arm_regno == REGNO (XEXP (body, 1)))
emit_insn_after (gen_nop (), first);
return;
}
}
/* get_attr aborts on USE and CLOBBER. */
if (!first
|| GET_CODE (first) != INSN
|| GET_CODE (PATTERN (first)) == USE
|| GET_CODE (PATTERN (first)) == CLOBBER)
return;
attr = get_attr_cirrus (first);
/* Any coprocessor compare instruction (cfcmps, cfcmpd, ...)
must be followed by a non-coprocessor instruction. */
if (attr == CIRRUS_COMPARE)
{
nops = 0;
t = next_nonnote_insn (first);
if (is_cirrus_insn (t))
++ nops;
if (is_cirrus_insn (next_nonnote_insn (t)))
++ nops;
while (nops --)
emit_insn_after (gen_nop (), first);
return;
}
}
/* Return nonzero if OP is a constant power of two. */ /* Return nonzero if OP is a constant power of two. */
int int
...@@ -5355,6 +5652,8 @@ arm_select_cc_mode (op, x, y) ...@@ -5355,6 +5652,8 @@ arm_select_cc_mode (op, x, y)
case LE: case LE:
case GT: case GT:
case GE: case GE:
if (TARGET_CIRRUS)
return CCFPmode;
return CCFPEmode; return CCFPEmode;
default: default:
...@@ -6678,6 +6977,12 @@ arm_reorg (first) ...@@ -6678,6 +6977,12 @@ arm_reorg (first)
/* Scan all the insns and record the operands that will need fixing. */ /* Scan all the insns and record the operands that will need fixing. */
for (insn = next_nonnote_insn (first); insn; insn = next_nonnote_insn (insn)) for (insn = next_nonnote_insn (first); insn; insn = next_nonnote_insn (insn))
{ {
if (TARGET_CIRRUS_FIX_INVALID_INSNS
&& (is_cirrus_insn (insn)
|| GET_CODE (insn) == JUMP_INSN
|| is_load_address (insn)))
cirrus_reorg (insn);
if (GET_CODE (insn) == BARRIER) if (GET_CODE (insn) == BARRIER)
push_minipool_barrier (insn, address); push_minipool_barrier (insn, address);
else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
...@@ -9168,6 +9473,16 @@ arm_print_operand (stream, x, code) ...@@ -9168,6 +9473,16 @@ arm_print_operand (stream, x, code)
fprintf (stream, "%s", arithmetic_instr (x, 1)); fprintf (stream, "%s", arithmetic_instr (x, 1));
return; return;
/* Truncate Cirrus shift counts. */
case 's':
if (GET_CODE (x) == CONST_INT)
{
fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f);
return;
}
arm_print_operand (stream, x, 0);
return;
case 'I': case 'I':
fprintf (stream, "%s", arithmetic_instr (x, 0)); fprintf (stream, "%s", arithmetic_instr (x, 0));
return; return;
...@@ -9274,6 +9589,43 @@ arm_print_operand (stream, x, code) ...@@ -9274,6 +9589,43 @@ arm_print_operand (stream, x, code)
fputs (thumb_condition_code (x, 1), stream); fputs (thumb_condition_code (x, 1), stream);
return; return;
/* Cirrus registers can be accessed in a variety of ways:
single floating point (f)
double floating point (d)
32bit integer (fx)
64bit integer (dx). */
case 'W': /* Cirrus register in F mode. */
case 'X': /* Cirrus register in D mode. */
case 'Y': /* Cirrus register in FX mode. */
case 'Z': /* Cirrus register in DX mode. */
if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
abort ();
fprintf (stream, "mv%s%s",
code == 'W' ? "f"
: code == 'X' ? "d"
: code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2);
return;
/* Print cirrus register in the mode specified by the register's mode. */
case 'V':
{
int mode = GET_MODE (x);
if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
abort ();
fprintf (stream, "mv%s%s",
mode == DFmode ? "d"
: mode == SImode ? "fx"
: mode == DImode ? "dx"
: "f", reg_names[REGNO (x)] + 2);
return;
}
default: default:
if (x == 0) if (x == 0)
abort (); abort ();
...@@ -9765,6 +10117,18 @@ arm_final_prescan_insn (insn) ...@@ -9765,6 +10117,18 @@ arm_final_prescan_insn (insn)
|| GET_CODE (scanbody) == PARALLEL) || GET_CODE (scanbody) == PARALLEL)
|| get_attr_conds (this_insn) != CONDS_NOCOND) || get_attr_conds (this_insn) != CONDS_NOCOND)
fail = TRUE; fail = TRUE;
/* A conditional cirrus instruction must be followed by
a non Cirrus instruction. However, since we
conditionalize instructions in this function and by
the time we get here we can't add instructions
(nops), because shorten_branches() has already been
called, we will disable conditionalizing Cirrus
instructions to be safe. */
if (GET_CODE (scanbody) != USE
&& GET_CODE (scanbody) != CLOBBER
&& get_attr_cirrus (this_insn) != CIRRUS_NO)
fail = TRUE;
break; break;
default: default:
...@@ -9848,6 +10212,14 @@ arm_hard_regno_mode_ok (regno, mode) ...@@ -9848,6 +10212,14 @@ arm_hard_regno_mode_ok (regno, mode)
start of an even numbered register pair. */ start of an even numbered register pair. */
return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM); return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
if (IS_CIRRUS_REGNUM (regno))
/* We have outlawed SI values in Cirrus registers because they
reside in the lower 32 bits, but SF values reside in the
upper 32 bits. This causes gcc all sorts of grief. We can't
even split the registers into pairs because Cirrus SI values
get sign extended to 64bits-- aldyh. */
return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode);
if (regno <= LAST_ARM_REGNUM) if (regno <= LAST_ARM_REGNUM)
/* We allow any value to be stored in the general regisetrs. */ /* We allow any value to be stored in the general regisetrs. */
return 1; return 1;
...@@ -9887,6 +10259,9 @@ arm_regno_class (regno) ...@@ -9887,6 +10259,9 @@ arm_regno_class (regno)
if (regno == CC_REGNUM) if (regno == CC_REGNUM)
return NO_REGS; return NO_REGS;
if (IS_CIRRUS_REGNUM (regno))
return CIRRUS_REGS;
return FPU_REGS; return FPU_REGS;
} }
......
...@@ -96,6 +96,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -96,6 +96,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_CPU_arm9 0x0080 #define TARGET_CPU_arm9 0x0080
#define TARGET_CPU_arm9tdmi 0x0080 #define TARGET_CPU_arm9tdmi 0x0080
#define TARGET_CPU_xscale 0x0100 #define TARGET_CPU_xscale 0x0100
#define TARGET_CPU_ep9312 0x0200
/* Configure didn't specify. */ /* Configure didn't specify. */
#define TARGET_CPU_generic 0x8000 #define TARGET_CPU_generic 0x8000
...@@ -164,6 +165,14 @@ extern GTY(()) rtx aof_pic_label; ...@@ -164,6 +165,14 @@ extern GTY(()) rtx aof_pic_label;
#if TARGET_CPU_DEFAULT == TARGET_CPU_xscale #if TARGET_CPU_DEFAULT == TARGET_CPU_xscale
#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__" #define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__"
#else #else
#if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__ -D__MAVERICK__"
/* Set TARGET_DEFAULT to the default, but without soft-float. */
#ifdef TARGET_DEFAULT
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME)
#endif /* TARGET_CPU_DEFAULT */
#else
Unrecognized value in TARGET_CPU_DEFAULT. Unrecognized value in TARGET_CPU_DEFAULT.
#endif #endif
#endif #endif
...@@ -171,6 +180,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -171,6 +180,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#endif #endif
#endif #endif
#endif #endif
#endif
#undef CPP_SPEC #undef CPP_SPEC
#define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec) \ #define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec) \
...@@ -212,6 +222,8 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -212,6 +222,8 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{march=strongarm1100:-D__ARM_ARCH_4__} \ %{march=strongarm1100:-D__ARM_ARCH_4__} \
%{march=xscale:-D__ARM_ARCH_5TE__} \ %{march=xscale:-D__ARM_ARCH_5TE__} \
%{march=xscale:-D__XSCALE__} \ %{march=xscale:-D__XSCALE__} \
%{march=ep9312:-D__ARM_ARCH_4T__} \
%{march=ep9312:-D__MAVERICK__} \
%{march=armv2:-D__ARM_ARCH_2__} \ %{march=armv2:-D__ARM_ARCH_2__} \
%{march=armv2a:-D__ARM_ARCH_2__} \ %{march=armv2a:-D__ARM_ARCH_2__} \
%{march=armv3:-D__ARM_ARCH_3__} \ %{march=armv3:-D__ARM_ARCH_3__} \
...@@ -251,6 +263,8 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -251,6 +263,8 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{mcpu=strongarm1100:-D__ARM_ARCH_4__} \ %{mcpu=strongarm1100:-D__ARM_ARCH_4__} \
%{mcpu=xscale:-D__ARM_ARCH_5TE__} \ %{mcpu=xscale:-D__ARM_ARCH_5TE__} \
%{mcpu=xscale:-D__XSCALE__} \ %{mcpu=xscale:-D__XSCALE__} \
%{mcpu=ep9312:-D__ARM_ARCH_4T__} \
%{mcpu=ep9312:-D__MAVERICK__} \
%{!mcpu*:%(cpp_cpu_arch_default)}} \ %{!mcpu*:%(cpp_cpu_arch_default)}} \
" "
...@@ -376,6 +390,9 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -376,6 +390,9 @@ Unrecognized value in TARGET_CPU_DEFAULT.
/* Nonzero means to use ARM/Thumb Procedure Call Standard conventions. */ /* Nonzero means to use ARM/Thumb Procedure Call Standard conventions. */
#define ARM_FLAG_ATPCS (1 << 22) #define ARM_FLAG_ATPCS (1 << 22)
/* Fix invalid Cirrus instruction combinations by inserting NOPs. */
#define CIRRUS_FIX_INVALID_INSNS (1 << 23)
#define TARGET_APCS_FRAME (target_flags & ARM_FLAG_APCS_FRAME) #define TARGET_APCS_FRAME (target_flags & ARM_FLAG_APCS_FRAME)
#define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE) #define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE)
#define TARGET_FPE (target_flags & ARM_FLAG_FPE) #define TARGET_FPE (target_flags & ARM_FLAG_FPE)
...@@ -387,6 +404,8 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -387,6 +404,8 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#define TARGET_MMU_TRAPS (target_flags & ARM_FLAG_MMU_TRAPS) #define TARGET_MMU_TRAPS (target_flags & ARM_FLAG_MMU_TRAPS)
#define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT) #define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT) #define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
#define TARGET_CIRRUS (arm_is_cirrus)
#define TARGET_ANY_HARD_FLOAT (TARGET_HARD_FLOAT || TARGET_CIRRUS)
#define TARGET_VFP (target_flags & ARM_FLAG_VFP) #define TARGET_VFP (target_flags & ARM_FLAG_VFP)
#define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END) #define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END)
#define TARGET_INTERWORK (target_flags & ARM_FLAG_INTERWORK) #define TARGET_INTERWORK (target_flags & ARM_FLAG_INTERWORK)
...@@ -403,6 +422,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -403,6 +422,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#define TARGET_BACKTRACE (leaf_function_p () \ #define TARGET_BACKTRACE (leaf_function_p () \
? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \ ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
: (target_flags & THUMB_FLAG_BACKTRACE)) : (target_flags & THUMB_FLAG_BACKTRACE))
#define TARGET_CIRRUS_FIX_INVALID_INSNS (target_flags & CIRRUS_FIX_INVALID_INSNS)
/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */ /* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
#ifndef SUBTARGET_SWITCHES #ifndef SUBTARGET_SWITCHES
...@@ -481,6 +501,10 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -481,6 +501,10 @@ Unrecognized value in TARGET_CPU_DEFAULT.
N_("Thumb: Assume function pointers may go to non-Thumb aware code") }, \ N_("Thumb: Assume function pointers may go to non-Thumb aware code") }, \
{"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING, \ {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING, \
"" }, \ "" }, \
{"cirrus-fix-invalid-insns", CIRRUS_FIX_INVALID_INSNS, \
N_("Cirrus: Place NOPs to avoid invalid instruction combinations") }, \
{"no-cirrus-fix-invalid-insns", -CIRRUS_FIX_INVALID_INSNS, \
N_("Cirrus: Do not break up invalid instruction combinations with NOPs") },\
SUBTARGET_SWITCHES \ SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT, "" } \ {"", TARGET_DEFAULT, "" } \
} }
...@@ -530,7 +554,8 @@ enum floating_point_type ...@@ -530,7 +554,8 @@ enum floating_point_type
{ {
FP_HARD, FP_HARD,
FP_SOFT2, FP_SOFT2,
FP_SOFT3 FP_SOFT3,
FP_CIRRUS
}; };
/* Recast the floating point class to be the floating point attribute. */ /* Recast the floating point class to be the floating point attribute. */
...@@ -548,6 +573,11 @@ extern enum floating_point_type arm_fpu_arch; ...@@ -548,6 +573,11 @@ extern enum floating_point_type arm_fpu_arch;
#define FP_DEFAULT FP_SOFT2 #define FP_DEFAULT FP_SOFT2
#endif #endif
#if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
#undef FP_DEFAULT
#define FP_DEFAULT FP_CIRRUS
#endif
/* Nonzero if the processor has a fast multiply insn, and one that does /* Nonzero if the processor has a fast multiply insn, and one that does
a 64-bit multiply of two 32-bit values. */ a 64-bit multiply of two 32-bit values. */
extern int arm_fast_multiply; extern int arm_fast_multiply;
...@@ -570,6 +600,9 @@ extern int thumb_code; ...@@ -570,6 +600,9 @@ extern int thumb_code;
/* Nonzero if this chip is a StrongARM. */ /* Nonzero if this chip is a StrongARM. */
extern int arm_is_strong; extern int arm_is_strong;
/* Nonzero if this chip is a Cirrus variant. */
extern int arm_is_cirrus;
/* Nonzero if this chip is an XScale. */ /* Nonzero if this chip is an XScale. */
extern int arm_is_xscale; extern int arm_is_xscale;
...@@ -756,6 +789,11 @@ extern const char * structure_size_string; ...@@ -756,6 +789,11 @@ extern const char * structure_size_string;
*: See CONDITIONAL_REGISTER_USAGE */ *: See CONDITIONAL_REGISTER_USAGE */
/*
mvf0 Cirrus floating point result
mvf1-mvf3 Cirrus floating point scratch
mvf4-mvf15 S Cirrus floating point variable. */
/* The stack backtrace structure is as follows: /* The stack backtrace structure is as follows:
fp points to here: | save code pointer | [fp] fp points to here: | save code pointer | [fp]
| return link value | [fp, #-4] | return link value | [fp, #-4]
...@@ -785,7 +823,9 @@ extern const char * structure_size_string; ...@@ -785,7 +823,9 @@ extern const char * structure_size_string;
0,0,0,0,0,0,0,0, \ 0,0,0,0,0,0,0,0, \
0,0,0,0,0,1,0,1, \ 0,0,0,0,0,1,0,1, \
0,0,0,0,0,0,0,0, \ 0,0,0,0,0,0,0,0, \
1,1,1 \ 1,1,1, \
1,1,1,1,1,1,1,1, \
1,1,1,1,1,1,1,1 \
} }
/* 1 for registers not available across function calls. /* 1 for registers not available across function calls.
...@@ -801,7 +841,9 @@ extern const char * structure_size_string; ...@@ -801,7 +841,9 @@ extern const char * structure_size_string;
1,1,1,1,0,0,0,0, \ 1,1,1,1,0,0,0,0, \
0,0,0,0,1,1,1,1, \ 0,0,0,0,1,1,1,1, \
1,1,1,1,0,0,0,0, \ 1,1,1,1,0,0,0,0, \
1,1,1 \ 1,1,1, \
1,1,1,1,1,1,1,1, \
1,1,1,1,1,1,1,1 \
} }
#ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
...@@ -818,6 +860,20 @@ extern const char * structure_size_string; ...@@ -818,6 +860,20 @@ extern const char * structure_size_string;
regno <= LAST_ARM_FP_REGNUM; ++regno) \ regno <= LAST_ARM_FP_REGNUM; ++regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \ fixed_regs[regno] = call_used_regs[regno] = 1; \
} \ } \
\
if (TARGET_CIRRUS) \
{ \
for (regno = FIRST_ARM_FP_REGNUM; \
regno <= LAST_ARM_FP_REGNUM; ++ regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
for (regno = FIRST_CIRRUS_FP_REGNUM; \
regno <= LAST_CIRRUS_FP_REGNUM; ++ regno) \
{ \
fixed_regs[regno] = 0; \
call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; \
} \
} \
\
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \ if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \
{ \ { \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
...@@ -941,8 +997,14 @@ extern const char * structure_size_string; ...@@ -941,8 +997,14 @@ extern const char * structure_size_string;
/* Base register for access to arguments of the function. */ /* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM 26 #define ARG_POINTER_REGNUM 26
#define FIRST_CIRRUS_FP_REGNUM 27
#define LAST_CIRRUS_FP_REGNUM 42
#define IS_CIRRUS_REGNUM(REGNUM) \
(((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
/* The number of hard registers is 16 ARM + 8 FPU + 1 CC + 1 SFP. */ /* The number of hard registers is 16 ARM + 8 FPU + 1 CC + 1 SFP. */
#define FIRST_PSEUDO_REGISTER 27 /* Cirrus registers take us up to 43... */
#define FIRST_PSEUDO_REGISTER 43
/* Value should be nonzero if functions must have frame pointers. /* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may be accessed Zero means the frame pointer need not be set up (and parms may be accessed
...@@ -990,6 +1052,8 @@ extern const char * structure_size_string; ...@@ -990,6 +1052,8 @@ extern const char * structure_size_string;
3, 2, 1, 0, 12, 14, 4, 5, \ 3, 2, 1, 0, 12, 14, 4, 5, \
6, 7, 8, 10, 9, 11, 13, 15, \ 6, 7, 8, 10, 9, 11, 13, 15, \
16, 17, 18, 19, 20, 21, 22, 23, \ 16, 17, 18, 19, 20, 21, 22, 23, \
27, 28, 29, 30, 31, 32, 33, 34, \
35, 36, 37, 38, 39, 40, 41, 42, \
24, 25, 26 \ 24, 25, 26 \
} }
...@@ -1008,6 +1072,7 @@ enum reg_class ...@@ -1008,6 +1072,7 @@ enum reg_class
{ {
NO_REGS, NO_REGS,
FPU_REGS, FPU_REGS,
CIRRUS_REGS,
LO_REGS, LO_REGS,
STACK_REG, STACK_REG,
BASE_REGS, BASE_REGS,
...@@ -1025,6 +1090,7 @@ enum reg_class ...@@ -1025,6 +1090,7 @@ enum reg_class
{ \ { \
"NO_REGS", \ "NO_REGS", \
"FPU_REGS", \ "FPU_REGS", \
"CIRRUS_REGS", \
"LO_REGS", \ "LO_REGS", \
"STACK_REG", \ "STACK_REG", \
"BASE_REGS", \ "BASE_REGS", \
...@@ -1039,15 +1105,16 @@ enum reg_class ...@@ -1039,15 +1105,16 @@ enum reg_class
of length N_REG_CLASSES. */ of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \ #define REG_CLASS_CONTENTS \
{ \ { \
{ 0x0000000 }, /* NO_REGS */ \ { 0x00000000, 0x0 }, /* NO_REGS */ \
{ 0x0FF0000 }, /* FPU_REGS */ \ { 0x00FF0000, 0x0 }, /* FPU_REGS */ \
{ 0x00000FF }, /* LO_REGS */ \ { 0xF8000000, 0x000007FF }, /* CIRRUS_REGS */ \
{ 0x0002000 }, /* STACK_REG */ \ { 0x000000FF, 0x0 }, /* LO_REGS */ \
{ 0x00020FF }, /* BASE_REGS */ \ { 0x00002000, 0x0 }, /* STACK_REG */ \
{ 0x000FF00 }, /* HI_REGS */ \ { 0x000020FF, 0x0 }, /* BASE_REGS */ \
{ 0x1000000 }, /* CC_REG */ \ { 0x0000FF00, 0x0 }, /* HI_REGS */ \
{ 0x200FFFF }, /* GENERAL_REGS */ \ { 0x01000000, 0x0 }, /* CC_REG */ \
{ 0x2FFFFFF } /* ALL_REGS */ \ { 0x0200FFFF, 0x0 }, /* GENERAL_REGS */\
{ 0xFAFFFFFF, 0x000007FF } /* ALL_REGS */ \
} }
/* The same information, inverted: /* The same information, inverted:
...@@ -1080,6 +1147,7 @@ enum reg_class ...@@ -1080,6 +1147,7 @@ enum reg_class
ARM, but several more letters for the Thumb. */ ARM, but several more letters for the Thumb. */
#define REG_CLASS_FROM_LETTER(C) \ #define REG_CLASS_FROM_LETTER(C) \
( (C) == 'f' ? FPU_REGS \ ( (C) == 'f' ? FPU_REGS \
: (C) == 'v' ? CIRRUS_REGS \
: (C) == 'l' ? (TARGET_ARM ? GENERAL_REGS : LO_REGS) \ : (C) == 'l' ? (TARGET_ARM ? GENERAL_REGS : LO_REGS) \
: TARGET_ARM ? NO_REGS \ : TARGET_ARM ? NO_REGS \
: (C) == 'h' ? HI_REGS \ : (C) == 'h' ? HI_REGS \
...@@ -1143,8 +1211,9 @@ enum reg_class ...@@ -1143,8 +1211,9 @@ enum reg_class
(C) == 'R' ? (GET_CODE (OP) == MEM \ (C) == 'R' ? (GET_CODE (OP) == MEM \
&& GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \ && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) : \ && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) : \
(C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) \ (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) : \
: 0) (C) == 'T' ? cirrus_memory_offset (OP) : \
0)
#define EXTRA_CONSTRAINT_THUMB(X, C) \ #define EXTRA_CONSTRAINT_THUMB(X, C) \
((C) == 'Q' ? (GET_CODE (X) == MEM \ ((C) == 'Q' ? (GET_CODE (X) == MEM \
...@@ -1188,13 +1257,18 @@ enum reg_class ...@@ -1188,13 +1257,18 @@ enum reg_class
/* If we need to load shorts byte-at-a-time, then we need a scratch. */ /* If we need to load shorts byte-at-a-time, then we need a scratch. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
/* Cannot load constants into Cirrus registers. */ \
((TARGET_CIRRUS \
&& (CLASS) == CIRRUS_REGS \
&& (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF)) \
? GENERAL_REGS : \
(TARGET_ARM ? \ (TARGET_ARM ? \
(((MODE) == HImode && ! arm_arch4 && TARGET_MMU_TRAPS \ (((MODE) == HImode && ! arm_arch4 && TARGET_MMU_TRAPS \
&& (GET_CODE (X) == MEM \ && (GET_CODE (X) == MEM \
|| ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG) \ || ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG) \
&& true_regnum (X) == -1))) \ && true_regnum (X) == -1))) \
? GENERAL_REGS : NO_REGS) \ ? GENERAL_REGS : NO_REGS) \
: THUMB_SECONDARY_INPUT_RELOAD_CLASS (CLASS, MODE, X)) : THUMB_SECONDARY_INPUT_RELOAD_CLASS (CLASS, MODE, X)))
/* Try a machine-dependent way of reloading an illegitimate address /* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and jump to WIN. This operand. If we find one, push the reload and jump to WIN. This
...@@ -1217,6 +1291,9 @@ enum reg_class ...@@ -1217,6 +1291,9 @@ enum reg_class
\ \
if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \ if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \
low = ((val & 0xf) ^ 0x8) - 0x8; \ low = ((val & 0xf) ^ 0x8) - 0x8; \
else if (TARGET_CIRRUS) \
/* Need to be careful, -256 is not a valid offset. */ \
low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
else if (MODE == SImode \ else if (MODE == SImode \
|| (MODE == SFmode && TARGET_SOFT_FLOAT) \ || (MODE == SFmode && TARGET_SOFT_FLOAT) \
|| ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \ || ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \
...@@ -1289,13 +1366,19 @@ enum reg_class ...@@ -1289,13 +1366,19 @@ enum reg_class
needed to represent mode MODE in a register of class CLASS. needed to represent mode MODE in a register of class CLASS.
ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */ ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
#define CLASS_MAX_NREGS(CLASS, MODE) \ #define CLASS_MAX_NREGS(CLASS, MODE) \
((CLASS) == FPU_REGS ? 1 : ARM_NUM_REGS (MODE)) (((CLASS) == FPU_REGS || (CLASS) == CIRRUS_REGS) ? 1 : ARM_NUM_REGS (MODE))
/* If defined, gives a class of registers that cannot be used as the
operand of a SUBREG that changes the mode of the object illegally. */
/* Moves between FPU_REGS and GENERAL_REGS are two memory insns. */ /* Moves between FPU_REGS and GENERAL_REGS are two memory insns. */
#define REGISTER_MOVE_COST(MODE, FROM, TO) \ #define REGISTER_MOVE_COST(MODE, FROM, TO) \
(TARGET_ARM ? \ (TARGET_ARM ? \
((FROM) == FPU_REGS && (TO) != FPU_REGS ? 20 : \ ((FROM) == FPU_REGS && (TO) != FPU_REGS ? 20 : \
(FROM) != FPU_REGS && (TO) == FPU_REGS ? 20 : 2) \ (FROM) != FPU_REGS && (TO) == FPU_REGS ? 20 : \
(FROM) == CIRRUS_REGS && (TO) != CIRRUS_REGS ? 20 : \
(FROM) != CIRRUS_REGS && (TO) == CIRRUS_REGS ? 20 : \
2) \
: \ : \
((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2) ((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
...@@ -1347,6 +1430,8 @@ enum reg_class ...@@ -1347,6 +1430,8 @@ enum reg_class
#define LIBCALL_VALUE(MODE) \ #define LIBCALL_VALUE(MODE) \
(TARGET_ARM && TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT \ (TARGET_ARM && TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT \
? gen_rtx_REG (MODE, FIRST_ARM_FP_REGNUM) \ ? gen_rtx_REG (MODE, FIRST_ARM_FP_REGNUM) \
: TARGET_ARM && TARGET_CIRRUS && GET_MODE_CLASS (MODE) == MODE_FLOAT \
? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM) \
: gen_rtx_REG (MODE, ARG_REGISTER (1))) : gen_rtx_REG (MODE, ARG_REGISTER (1)))
/* Define how to find the value returned by a function. /* Define how to find the value returned by a function.
...@@ -1358,8 +1443,10 @@ enum reg_class ...@@ -1358,8 +1443,10 @@ enum reg_class
/* 1 if N is a possible register number for a function value. /* 1 if N is a possible register number for a function value.
On the ARM, only r0 and f0 can return results. */ On the ARM, only r0 and f0 can return results. */
/* On a Cirrus chip, mvf0 can return results. */
#define FUNCTION_VALUE_REGNO_P(REGNO) \ #define FUNCTION_VALUE_REGNO_P(REGNO) \
((REGNO) == ARG_REGISTER (1) \ ((REGNO) == ARG_REGISTER (1) \
|| (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) && TARGET_CIRRUS) \
|| (TARGET_ARM && ((REGNO) == FIRST_ARM_FP_REGNUM) && TARGET_HARD_FLOAT)) || (TARGET_ARM && ((REGNO) == FIRST_ARM_FP_REGNUM) && TARGET_HARD_FLOAT))
/* How large values are returned */ /* How large values are returned */
...@@ -2449,6 +2536,9 @@ extern int making_const_table; ...@@ -2449,6 +2536,9 @@ extern int making_const_table;
{"multi_register_push", {PARALLEL}}, \ {"multi_register_push", {PARALLEL}}, \
{"cc_register", {REG}}, \ {"cc_register", {REG}}, \
{"logical_binary_operator", {AND, IOR, XOR}}, \ {"logical_binary_operator", {AND, IOR, XOR}}, \
{"cirrus_register_operand", {REG}}, \
{"cirrus_fp_register", {REG}}, \
{"cirrus_shift_const", {CONST_INT}}, \
{"dominant_cc_register", {REG}}, {"dominant_cc_register", {REG}},
/* Define this if you have special predicates that know special things /* Define this if you have special predicates that know special things
......
...@@ -386,6 +386,8 @@ ...@@ -386,6 +386,8 @@
(and (eq_attr "core_cycles" "multi") (and (eq_attr "core_cycles" "multi")
(eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32) (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
(include "cirrus.md")
;;--------------------------------------------------------------------------- ;;---------------------------------------------------------------------------
;; Insn patterns ;; Insn patterns
;; ;;
...@@ -394,6 +396,8 @@ ...@@ -394,6 +396,8 @@
;; Note: For DImode insns, there is normally no reason why operands should ;; Note: For DImode insns, there is normally no reason why operands should
;; not be in the same register, what we don't want is for something being ;; not be in the same register, what we don't want is for something being
;; written to partially overlap something that is an input. ;; written to partially overlap something that is an input.
;; Cirrus 64bit additions should not be split because we have a native
;; 64bit addition instructions.
(define_expand "adddi3" (define_expand "adddi3"
[(parallel [(parallel
...@@ -403,6 +407,16 @@ ...@@ -403,6 +407,16 @@
(clobber (reg:CC CC_REGNUM))])] (clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER" "TARGET_EITHER"
" "
if (TARGET_CIRRUS)
{
if (!cirrus_fp_register (operands[0], DImode))
operands[0] = force_reg (DImode, operands[0]);
if (!cirrus_fp_register (operands[1], DImode))
operands[1] = force_reg (DImode, operands[1]);
emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
DONE;
}
if (TARGET_THUMB) if (TARGET_THUMB)
{ {
if (GET_CODE (operands[1]) != REG) if (GET_CODE (operands[1]) != REG)
...@@ -429,7 +443,7 @@ ...@@ -429,7 +443,7 @@
(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
(match_operand:DI 2 "s_register_operand" "r, 0"))) (match_operand:DI 2 "s_register_operand" "r, 0")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ARM" "TARGET_ARM && !TARGET_CIRRUS"
"#" "#"
"TARGET_ARM && reload_completed" "TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM) [(parallel [(set (reg:CC_C CC_REGNUM)
...@@ -457,7 +471,7 @@ ...@@ -457,7 +471,7 @@
(match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0"))) (match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ARM" "TARGET_ARM && !TARGET_CIRRUS"
"#" "#"
"TARGET_ARM && reload_completed" "TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM) [(parallel [(set (reg:CC_C CC_REGNUM)
...@@ -486,7 +500,7 @@ ...@@ -486,7 +500,7 @@
(match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0"))) (match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ARM" "TARGET_ARM && !TARGET_CIRRUS"
"#" "#"
"TARGET_ARM && reload_completed" "TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM) [(parallel [(set (reg:CC_C CC_REGNUM)
...@@ -789,7 +803,7 @@ ...@@ -789,7 +803,7 @@
(set_attr "length" "4,8")] (set_attr "length" "4,8")]
) )
(define_insn "addsf3" (define_insn "*arm_addsf3"
[(set (match_operand:SF 0 "s_register_operand" "=f,f") [(set (match_operand:SF 0 "s_register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f") (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
(match_operand:SF 2 "fpu_add_operand" "fG,H")))] (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
...@@ -801,7 +815,7 @@ ...@@ -801,7 +815,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "adddf3" (define_insn "*arm_adddf3"
[(set (match_operand:DF 0 "s_register_operand" "=f,f") [(set (match_operand:DF 0 "s_register_operand" "=f,f")
(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f") (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
(match_operand:DF 2 "fpu_add_operand" "fG,H")))] (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
...@@ -857,6 +871,15 @@ ...@@ -857,6 +871,15 @@
(clobber (reg:CC CC_REGNUM))])] (clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER" "TARGET_EITHER"
" "
if (TARGET_CIRRUS
&& TARGET_ARM
&& cirrus_fp_register (operands[0], DImode)
&& cirrus_fp_register (operands[1], DImode))
{
emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
DONE;
}
if (TARGET_THUMB) if (TARGET_THUMB)
{ {
if (GET_CODE (operands[1]) != REG) if (GET_CODE (operands[1]) != REG)
...@@ -1042,7 +1065,7 @@ ...@@ -1042,7 +1065,7 @@
(set_attr "length" "*,8")] (set_attr "length" "*,8")]
) )
(define_insn "subsf3" (define_insn "*arm_subsf3"
[(set (match_operand:SF 0 "s_register_operand" "=f,f") [(set (match_operand:SF 0 "s_register_operand" "=f,f")
(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
(match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
...@@ -1053,7 +1076,7 @@ ...@@ -1053,7 +1076,7 @@
[(set_attr "type" "farith")] [(set_attr "type" "farith")]
) )
(define_insn "subdf3" (define_insn "*arm_subdf3"
[(set (match_operand:DF 0 "s_register_operand" "=f,f") [(set (match_operand:DF 0 "s_register_operand" "=f,f")
(minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
(match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
...@@ -1332,7 +1355,7 @@ ...@@ -1332,7 +1355,7 @@
"smlalbb%?\\t%Q0, %R0, %2, %3" "smlalbb%?\\t%Q0, %R0, %2, %3"
[(set_attr "type" "mult")]) [(set_attr "type" "mult")])
(define_insn "mulsf3" (define_insn "*arm_mulsf3"
[(set (match_operand:SF 0 "s_register_operand" "=f") [(set (match_operand:SF 0 "s_register_operand" "=f")
(mult:SF (match_operand:SF 1 "s_register_operand" "f") (mult:SF (match_operand:SF 1 "s_register_operand" "f")
(match_operand:SF 2 "fpu_rhs_operand" "fG")))] (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
...@@ -1342,7 +1365,7 @@ ...@@ -1342,7 +1365,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "muldf3" (define_insn "*arm_muldf3"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
(mult:DF (match_operand:DF 1 "s_register_operand" "f") (mult:DF (match_operand:DF 1 "s_register_operand" "f")
(match_operand:DF 2 "fpu_rhs_operand" "fG")))] (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
...@@ -2529,6 +2552,19 @@ ...@@ -2529,6 +2552,19 @@
[(set_attr "length" "2")] [(set_attr "length" "2")]
) )
(define_expand "ashldi3"
[(set (match_operand:DI 0 "s_register_operand" "")
(ashift:DI (match_operand:DI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
"TARGET_ARM && (TARGET_CIRRUS)"
"
if (! s_register_operand (operands[1], DImode))
operands[1] = copy_to_mode_reg (DImode, operands[1]);
if (! s_register_operand (operands[2], SImode))
operands[2] = copy_to_mode_reg (SImode, operands[2]);
"
)
(define_insn "*arm_shiftsi3" (define_insn "*arm_shiftsi3"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r")
(match_operator:SI 3 "shift_operator" (match_operator:SI 3 "shift_operator"
...@@ -2702,7 +2738,7 @@ ...@@ -2702,7 +2738,7 @@
[(set_attr "length" "2")] [(set_attr "length" "2")]
) )
(define_insn "negsf2" (define_insn "*arm_negsf2"
[(set (match_operand:SF 0 "s_register_operand" "=f") [(set (match_operand:SF 0 "s_register_operand" "=f")
(neg:SF (match_operand:SF 1 "s_register_operand" "f")))] (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2711,7 +2747,7 @@ ...@@ -2711,7 +2747,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "negdf2" (define_insn "*arm_negdf2"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
(neg:DF (match_operand:DF 1 "s_register_operand" "f")))] (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2735,7 +2771,7 @@ ...@@ -2735,7 +2771,7 @@
;; it does, but tell the final scan operator the truth. Similarly for ;; it does, but tell the final scan operator the truth. Similarly for
;; (neg (abs...)) ;; (neg (abs...))
(define_insn "abssi2" (define_insn "*arm_abssi2"
[(set (match_operand:SI 0 "s_register_operand" "=r,&r") [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
(abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
...@@ -2763,7 +2799,7 @@ ...@@ -2763,7 +2799,7 @@
(set_attr "length" "8")] (set_attr "length" "8")]
) )
(define_insn "abssf2" (define_insn "*arm_abssf2"
[(set (match_operand:SF 0 "s_register_operand" "=f") [(set (match_operand:SF 0 "s_register_operand" "=f")
(abs:SF (match_operand:SF 1 "s_register_operand" "f")))] (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2772,7 +2808,7 @@ ...@@ -2772,7 +2808,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "absdf2" (define_insn "*arm_absdf2"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
(abs:DF (match_operand:DF 1 "s_register_operand" "f")))] (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2884,7 +2920,7 @@ ...@@ -2884,7 +2920,7 @@
;; Fixed <--> Floating conversion insns ;; Fixed <--> Floating conversion insns
(define_insn "floatsisf2" (define_insn "*arm_floatsisf2"
[(set (match_operand:SF 0 "s_register_operand" "=f") [(set (match_operand:SF 0 "s_register_operand" "=f")
(float:SF (match_operand:SI 1 "s_register_operand" "r")))] (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2893,7 +2929,7 @@ ...@@ -2893,7 +2929,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "floatsidf2" (define_insn "*arm_floatsidf2"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
(float:DF (match_operand:SI 1 "s_register_operand" "r")))] (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2902,7 +2938,7 @@ ...@@ -2902,7 +2938,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "fix_truncsfsi2" (define_insn "*arm_fix_truncsfsi2"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (match_operand:SF 1 "s_register_operand" "f")))] (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2911,7 +2947,7 @@ ...@@ -2911,7 +2947,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
(define_insn "fix_truncdfsi2" (define_insn "*arm_fix_truncdfsi2"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (match_operand:DF 1 "s_register_operand" "f")))] (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -2922,7 +2958,7 @@ ...@@ -2922,7 +2958,7 @@
;; Truncation insns ;; Truncation insns
(define_insn "truncdfsf2" (define_insn "*arm_truncdfsf2"
[(set (match_operand:SF 0 "s_register_operand" "=f") [(set (match_operand:SF 0 "s_register_operand" "=f")
(float_truncate:SF (float_truncate:SF
(match_operand:DF 1 "s_register_operand" "f")))] (match_operand:DF 1 "s_register_operand" "f")))]
...@@ -3654,7 +3690,7 @@ ...@@ -3654,7 +3690,7 @@
(set_attr "pool_range" "32,32")] (set_attr "pool_range" "32,32")]
) )
(define_insn "extendsfdf2" (define_insn "*arm_extendsfdf2"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
(float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))] (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_HARD_FLOAT"
...@@ -3743,7 +3779,7 @@ ...@@ -3743,7 +3779,7 @@
(define_insn "*arm_movdi" (define_insn "*arm_movdi"
[(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>") [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
(match_operand:DI 1 "di_operand" "rIK,mi,r"))] (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
"TARGET_ARM" "TARGET_ARM && !TARGET_CIRRUS"
"* "*
return (output_move_double (operands)); return (output_move_double (operands));
" "
...@@ -3761,6 +3797,7 @@ ...@@ -3761,6 +3797,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r") [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
(match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))] (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
"TARGET_THUMB "TARGET_THUMB
&& !TARGET_CIRRUS
&& ( register_operand (operands[0], DImode) && ( register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))" || register_operand (operands[1], DImode))"
"* "*
...@@ -4769,6 +4806,7 @@ ...@@ -4769,6 +4806,7 @@
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
(match_operand:SF 1 "general_operand" "r,mE,r"))] (match_operand:SF 1 "general_operand" "r,mE,r"))]
"TARGET_ARM "TARGET_ARM
&& !TARGET_CIRRUS
&& TARGET_SOFT_FLOAT && TARGET_SOFT_FLOAT
&& (GET_CODE (operands[0]) != MEM && (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], SFmode))" || register_operand (operands[1], SFmode))"
...@@ -4909,6 +4947,7 @@ ...@@ -4909,6 +4947,7 @@
[(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m") [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
(match_operand:DF 1 "soft_df_operand" "r,mF,r"))] (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
"TARGET_ARM && TARGET_SOFT_FLOAT "TARGET_ARM && TARGET_SOFT_FLOAT
&& !TARGET_CIRRUS
" "
"* return output_move_double (operands);" "* return output_move_double (operands);"
[(set_attr "length" "8,8,8") [(set_attr "length" "8,8,8")
...@@ -5414,8 +5453,11 @@ ...@@ -5414,8 +5453,11 @@
(define_expand "cmpsf" (define_expand "cmpsf"
[(match_operand:SF 0 "s_register_operand" "") [(match_operand:SF 0 "s_register_operand" "")
(match_operand:SF 1 "fpu_rhs_operand" "")] (match_operand:SF 1 "fpu_rhs_operand" "")]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
" "
if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
arm_compare_op0 = operands[0]; arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1]; arm_compare_op1 = operands[1];
DONE; DONE;
...@@ -5425,8 +5467,11 @@ ...@@ -5425,8 +5467,11 @@
(define_expand "cmpdf" (define_expand "cmpdf"
[(match_operand:DF 0 "s_register_operand" "") [(match_operand:DF 0 "s_register_operand" "")
(match_operand:DF 1 "fpu_rhs_operand" "")] (match_operand:DF 1 "fpu_rhs_operand" "")]
"TARGET_ARM && TARGET_HARD_FLOAT" "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
" "
if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
arm_compare_op0 = operands[0]; arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1]; arm_compare_op1 = operands[1];
DONE; DONE;
...@@ -5531,6 +5576,65 @@ ...@@ -5531,6 +5576,65 @@
(set_attr "type" "f_2_r")] (set_attr "type" "f_2_r")]
) )
;; There is no CCFPE or CCFP modes in the code below so we can have
;; one pattern to match either one. Besides, we're pretty sure we
;; have either CCFPE or CCFP because we made the patterns
;; (arm_gen_compare_reg).
;; Cirrus SF compare instruction
(define_insn "*cirrus_cmpsf"
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
(match_operand:SF 1 "cirrus_fp_register" "v")))]
"TARGET_ARM && TARGET_CIRRUS"
"cfcmps%?\\tr15, %V0, %V1"
[(set_attr "cirrus_type" "farith")
(set_attr "cirrus" "compare")]
)
;; Cirrus DF compare instruction
(define_insn "*cirrus_cmpdf"
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
(match_operand:DF 1 "cirrus_fp_register" "v")))]
"TARGET_ARM && TARGET_CIRRUS"
"cfcmpd%?\\tr15, %V0, %V1"
[(set_attr "cirrus_type" "farith")
(set_attr "cirrus" "compare")]
)
;; Cirrus DI compare instruction
(define_expand "cmpdi"
[(match_operand:DI 0 "cirrus_fp_register" "")
(match_operand:DI 1 "cirrus_fp_register" "")]
"TARGET_ARM && TARGET_CIRRUS"
"{
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
DONE;
}")
(define_insn "*cirrus_cmpdi"
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
(match_operand:DI 1 "cirrus_fp_register" "v")))]
"TARGET_ARM && TARGET_CIRRUS"
"cfcmp64%?\\tr15, %V0, %V1"
[(set_attr "cirrus_type" "farith")
(set_attr "cirrus" "compare")]
)
;; Cirrus SI compare instruction
(define_insn "*cirrus_cmpsi_1"
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:SI 0 "cirrus_fp_register" "v")
(match_operand:SI 1 "cirrus_fp_register" "v")))]
"TARGET_ARM && TARGET_CIRRUS && 0"
"cfcmp32%?\\tr15, %V0, %V1"
[(set_attr "cirrus_type" "farith")
(set_attr "cirrus" "compare")]
)
(define_insn "*cmpsf_trap" (define_insn "*cmpsf_trap"
[(set (reg:CCFPE CC_REGNUM) [(set (reg:CCFPE CC_REGNUM)
(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f") (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
...@@ -6347,8 +6451,8 @@ ...@@ -6347,8 +6451,8 @@
) )
(define_insn "*call_value_reg" (define_insn "*call_value_reg"
[(set (match_operand 0 "" "=r,f") [(set (match_operand 0 "" "=r,f,v")
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r")) (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
...@@ -6361,8 +6465,8 @@ ...@@ -6361,8 +6465,8 @@
) )
(define_insn "*call_value_mem" (define_insn "*call_value_mem"
[(set (match_operand 0 "" "=r,f") [(set (match_operand 0 "" "=r,f,v")
(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m")) (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
...@@ -6393,8 +6497,8 @@ ...@@ -6393,8 +6497,8 @@
) )
(define_insn "*call_value_symbol" (define_insn "*call_value_symbol"
[(set (match_operand 0 "s_register_operand" "=r,f") [(set (match_operand 0 "s_register_operand" "=r,f,v")
(call (mem:SI (match_operand:SI 1 "" "X,X")) (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
(match_operand:SI 2 "" ""))) (match_operand:SI 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
...@@ -6476,8 +6580,8 @@ ...@@ -6476,8 +6580,8 @@
) )
(define_insn "*sibcall_value_insn" (define_insn "*sibcall_value_insn"
[(set (match_operand 0 "s_register_operand" "=r,f") [(set (match_operand 0 "s_register_operand" "=r,f,v")
(call (mem:SI (match_operand:SI 1 "" "X,X")) (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(return) (return)
(use (match_operand 3 "" ""))] (use (match_operand 3 "" ""))]
...@@ -8274,6 +8378,9 @@ ...@@ -8274,6 +8378,9 @@
(set (reg:CC CC_REGNUM) (set (reg:CC CC_REGNUM)
(compare:CC (match_dup 1) (const_int 0)))] (compare:CC (match_dup 1) (const_int 0)))]
"TARGET_ARM "TARGET_ARM
&& (!TARGET_CIRRUS
|| (!cirrus_fp_register (operands[0], SImode)
&& !cirrus_fp_register (operands[1], SImode)))
" "
[(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])] (set (match_dup 0) (match_dup 1))])]
......
...@@ -24,6 +24,10 @@ dp-bit.c: $(srcdir)/config/fp-bit.c ...@@ -24,6 +24,10 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
MULTILIB_OPTIONS = marm/mthumb MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb MULTILIB_DIRNAMES = arm thumb
MULTILIB_EXCEPTIONS = MULTILIB_EXCEPTIONS =
# MULTILIB_OPTIONS += mcpu=ep9312
# MULTILIB_DIRNAMES += ep9312
# MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312*
# MULTILIB_OPTIONS += mlittle-endian/mbig-endian # MULTILIB_OPTIONS += mlittle-endian/mbig-endian
# MULTILIB_DIRNAMES += le be # MULTILIB_DIRNAMES += le be
......
...@@ -386,6 +386,7 @@ in the following sections. ...@@ -386,6 +386,7 @@ in the following sections.
-msingle-pic-base -mno-single-pic-base @gol -msingle-pic-base -mno-single-pic-base @gol
-mpic-register=@var{reg} @gol -mpic-register=@var{reg} @gol
-mnop-fun-dllimport @gol -mnop-fun-dllimport @gol
-mcirrus-fix-invalid-insns -mno-cirrus-fix-invalid-insns @gol
-mpoke-function-name @gol -mpoke-function-name @gol
-mthumb -marm @gol -mthumb -marm @gol
-mtpcs-frame -mtpcs-leaf-frame @gol -mtpcs-frame -mtpcs-leaf-frame @gol
...@@ -6132,7 +6133,7 @@ assembly code. Permissible names are: @samp{arm2}, @samp{arm250}, ...@@ -6132,7 +6133,7 @@ assembly code. Permissible names are: @samp{arm2}, @samp{arm250},
@samp{strongarm}, @samp{strongarm110}, @samp{strongarm1100}, @samp{strongarm}, @samp{strongarm110}, @samp{strongarm1100},
@samp{arm8}, @samp{arm810}, @samp{arm9}, @samp{arm9e}, @samp{arm920}, @samp{arm8}, @samp{arm810}, @samp{arm9}, @samp{arm9e}, @samp{arm920},
@samp{arm920t}, @samp{arm940t}, @samp{arm9tdmi}, @samp{arm10tdmi}, @samp{arm920t}, @samp{arm940t}, @samp{arm9tdmi}, @samp{arm10tdmi},
@samp{arm1020t}, @samp{xscale}. @samp{arm1020t}, @samp{xscale}, @samp{ep9312}.
@itemx -mtune=@var{name} @itemx -mtune=@var{name}
@opindex mtune @opindex mtune
...@@ -6152,7 +6153,7 @@ name to determine what kind of instructions it can emit when generating ...@@ -6152,7 +6153,7 @@ name to determine what kind of instructions it can emit when generating
assembly code. This option can be used in conjunction with or instead assembly code. This option can be used in conjunction with or instead
of the @option{-mcpu=} option. Permissible names are: @samp{armv2}, of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t}, @samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t},
@samp{armv5}, @samp{armv5t}, @samp{armv5te}. @samp{armv5}, @samp{armv5t}, @samp{armv5te}, @samp{ep9312}.
@item -mfpe=@var{number} @item -mfpe=@var{number}
@itemx -mfp=@var{number} @itemx -mfp=@var{number}
...@@ -6224,6 +6225,18 @@ before execution begins. ...@@ -6224,6 +6225,18 @@ before execution begins.
Specify the register to be used for PIC addressing. The default is R10 Specify the register to be used for PIC addressing. The default is R10
unless stack-checking is enabled, when R9 is used. unless stack-checking is enabled, when R9 is used.
@item -mcirrus-fix-invalid-insns
@opindex -mcirrus-fix-invalid-insns
@opindex -mno-cirrus-fix-invalid-insns
Insert NOPs into the instruction stream to in order to work around
problems with invalid Maverick instruction combinations. This option
is only valid if the @option{-mcpu=ep9312} option has been used to
enable generation of instructions for the Cirrus Maverick floating
point co-processor. This option is not enabled by default, since the
problem is only present in older Maverick implemenations. The default
can be re-enabled by use of the @option{-mno-cirrus-fix-invalid-insns}
switch.
@item -mpoke-function-name @item -mpoke-function-name
@opindex mpoke-function-name @opindex mpoke-function-name
Write the name of each function into the text section, directly Write the name of each function into the text section, directly
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment