--- gcc/config/arm/arm.h 2018/04/24 18:22:23 1.1.1.3 +++ gcc/config/arm/arm.h 2018/04/24 18:30:05 1.1.1.4 @@ -1,7 +1,7 @@ /* Definitions of target machine for GNU compiler, for Acorn RISC Machine. - Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) - and Martin Simmons (@harleqn.co.uk). + and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk) This file is part of GNU CC. @@ -18,7 +18,8 @@ GNU General Public License for more deta 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Sometimes the directive `riscos' is checked. This does not imply that this tm file can be used unchanged to build a GCC for RISC OS. @@ -92,14 +93,17 @@ extern int target_flags; for the arm processor chip, but it is needed for some MMU chips. */ #define TARGET_SHORT_BY_BYTES (target_flags & 0x200) -/* ARM_EXTRA_TARGET_SWITCHES is used in riscix.h to define some options which - are passed to the preprocessor and the assembler post-processor. They - aren't needed in the main pass of the compiler, but if we don't define - them in target switches cc1 complains about them. For the sake of - argument lets allocate bit 31 of target flags for such options. */ - -#ifndef ARM_EXTRA_TARGET_SWITCHES -#define ARM_EXTRA_TARGET_SWITCHES +/* Nonzero if GCC should use a floating point library. + GCC will assume the fp regs don't exist and will not emit any fp insns. + Note that this is different than fp emulation which still uses fp regs + and insns - the kernel catches the trap and performs the operation. */ +#define TARGET_SOFT_FLOAT (target_flags & 0x400) +#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT) + +/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. + Bit 31 is reserved. See riscix.h. */ +#ifndef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES #endif #define TARGET_SWITCHES \ @@ -114,7 +118,9 @@ extern int target_flags; {"no-short-load-bytes", -(0x200)}, \ {"short-load-words", -(0x200)}, \ {"no-short-load-words", (0x200)}, \ - ARM_EXTRA_TARGET_SWITCHES \ + {"soft-float", (0x400)}, \ + {"hard-float", -(0x400)}, \ + SUBTARGET_SWITCHES \ {"", TARGET_DEFAULT } \ } @@ -221,12 +227,10 @@ extern enum floating_point_type arm_fpu; #define BITS_BIG_ENDIAN 0 /* Define this if most significant byte of a word is the lowest numbered. - Most ARM processors are run in little endian mode, but it should now be - possible to build the compiler to support big endian code. (Note: This - is currently a compiler-build-time option, not a run-time one. */ -#ifndef BYTES_BIG_ENDIAN + Most ARM processors are run in little endian mode, so that is the default. + If you want to have it run-time selectable, change the definition in a + cover file to be TARGET_BIG_ENDIAN. */ #define BYTES_BIG_ENDIAN 0 -#endif /* Define this if most significant word of a multiword number is the lowest numbered. */ @@ -364,9 +368,15 @@ extern enum floating_point_type arm_fpu; XXX It is a hack, I know. XXX Is this still needed? */ #define CONDITIONAL_REGISTER_USAGE \ -{ \ - if (obey_regdecls) \ - fixed_regs[0] = 1; \ +{ \ + if (obey_regdecls) \ + fixed_regs[0] = 1; \ + if (TARGET_SOFT_FLOAT) \ + { \ + int regno; \ + for (regno = 16; regno < 24; ++regno) \ + fixed_regs[regno] = call_used_regs[regno] = 1; \ + } \ } /* Return number of consecutive hard regs needed starting at reg REGNO @@ -556,7 +566,8 @@ enum reg_class NO_REGS is returned. */ #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \ (((MODE) == DFmode && (CLASS) == GENERAL_REGS \ - && true_regnum (X) == -1) ? GENERAL_REGS \ + && true_regnum (X) == -1 && TARGET_HARD_FLOAT) \ + ? GENERAL_REGS \ : ((MODE) == HImode && true_regnum (X) == -1) ? GENERAL_REGS : NO_REGS) /* If we need to load shorts byte-at-a-time, then we need a scratch. */ @@ -604,34 +615,35 @@ enum reg_class /* Value is the number of byte of arguments automatically popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), FUNTYPE is the data type of the function (as a tree), or for a library call it is an identifier node for the subroutine name. SIZE is the number of bytes of arguments passed on the stack. On the ARM, the caller does not pop any of its arguments that were passed on the stack. */ -#define RETURN_POPS_ARGS(FUNTYPE, SIZE) 0 +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 /* Define how to find the value returned by a function. VALTYPE is the data type of the value (as a tree). If the precise function being called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT \ - ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \ + (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT && TARGET_HARD_FLOAT \ + ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0)) /* Define how to find the value returned by a library function assuming the value has mode MODE. */ #define LIBCALL_VALUE(MODE) \ - (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - ? gen_rtx (REG, MODE, 16) \ + (GET_MODE_CLASS (MODE) == MODE_FLOAT && TARGET_HARD_FLOAT \ + ? gen_rtx (REG, MODE, 16) \ : gen_rtx (REG, MODE, 0)) /* 1 if N is a possible register number for a function value. On the ARM, only r0 and f0 can return results. */ #define FUNCTION_VALUE_REGNO_P(REGNO) \ - ((REGNO) == 0 || (REGNO) == 16) + ((REGNO) == 0 || ((REGNO) == 16) && TARGET_HARD_FLOAT) /* Define where to put the arguments to a function. Value is zero to push the argument on the stack, @@ -723,7 +735,7 @@ enum reg_class to mind about this! */ #define FUNCTION_PROFILER(STREAM,LABELNO) \ { \ - fprintf(STREAM, "\tmov\t%sip, %slr\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ + fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \ fprintf(STREAM, "\tbl\tmcount\n"); \ fprintf(STREAM, "\t.word\tLP%d\n", (LABELNO)); \ } @@ -768,7 +780,7 @@ enum reg_class Frame pointer elimination is automatically handled. All eliminations are permissible. Note that ARG_POINTER_REGNUM and - HARD_FRAME_POINTER_REGNUM are infact the same thing. If we need a frame + HARD_FRAME_POINTER_REGNUM are in fact the same thing. If we need a frame pointer, we must eliminate FRAME_POINTER_REGNUM into HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */ #define CAN_ELIMINATE(FROM, TO) \ @@ -822,10 +834,10 @@ enum reg_class .word function's address */ #define TRAMPOLINE_TEMPLATE(FILE) \ { \ - fprintf ((FILE), "\tldr\t%sr8, [%spc, #0]\n", ARM_REG_PREFIX, \ - ARM_REG_PREFIX); \ - fprintf ((FILE), "\tldr\t%spc, [%spc, #0]\n", ARM_REG_PREFIX, \ - ARM_REG_PREFIX); \ + fprintf ((FILE), "\tldr\t%sr8, [%spc, #0]\n", \ + REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf ((FILE), "\tldr\t%spc, [%spc, #0]\n", \ + REGISTER_PREFIX, REGISTER_PREFIX); \ fprintf ((FILE), "\t.word\t0\n"); \ fprintf ((FILE), "\t.word\t0\n"); \ } @@ -1267,7 +1279,7 @@ do \ #define MEMORY_MOVE_COST(MODE) 10 /* All address computations that can be done are free, but rtx cost returns - the same for practically all of them. So we weight the differnt types + the same for practically all of them. So we weight the different types of address here in the order (most pref first): PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */ #define ADDRESS_COST(X) \ @@ -1295,9 +1307,9 @@ do \ /* Condition code information. */ /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, return the mode to be used for the comparison. - CCFPEmode should be used with floating inequalites, + CCFPEmode should be used with floating inequalities, CCFPmode should be used with floating equalities. - CC_NOOVmode should be used with SImode integer equalites + CC_NOOVmode should be used with SImode integer equalities. CCmode should be used otherwise. */ #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode @@ -1342,6 +1354,7 @@ extern int arm_compare_fp; {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \ {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \ {"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \ + {"soft_df_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \ {"load_multiple_operation", {PARALLEL}}, \ {"store_multiple_operation", {PARALLEL}}, \ {"equality_operator", {EQ, NE}}, \ @@ -1364,15 +1377,15 @@ extern int arm_compare_fp; #define ASM_FILE_START(STREAM) \ { \ extern char *version_string; \ - fprintf (STREAM,"%c Generated by gcc %s for ARM/%s\n", \ - ARM_COMMENT_CHAR, version_string, ARM_OS_NAME); \ - fprintf (STREAM,"%srfp\t.req\t%sr9\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%ssl\t.req\t%sr10\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%sfp\t.req\t%sr11\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%sip\t.req\t%sr12\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%ssp\t.req\t%sr13\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%slr\t.req\t%sr14\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ - fprintf (STREAM,"%spc\t.req\t%sr15\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ + fprintf (STREAM,"%s Generated by gcc %s for ARM/%s\n", \ + ASM_COMMENT_START, version_string, ARM_OS_NAME); \ + fprintf (STREAM,"%srfp\t.req\t%sr9\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%ssl\t.req\t%sr10\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%sfp\t.req\t%sr11\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%sip\t.req\t%sr12\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%ssp\t.req\t%sr13\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%slr\t.req\t%sr14\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%spc\t.req\t%sr15\n", REGISTER_PREFIX, REGISTER_PREFIX); \ } #define ASM_APP_ON "" @@ -1382,6 +1395,10 @@ extern int arm_compare_fp; #define TEXT_SECTION_ASM_OP ".text" #define DATA_SECTION_ASM_OP ".data" +#define REGISTER_PREFIX "" +#define USER_LABEL_PREFIX "_" +#define LOCAL_LABEL_PREFIX "" + /* The assembler's names for the registers. */ #ifndef REGISTER_NAMES #define REGISTER_NAMES \ @@ -1461,7 +1478,7 @@ do { \ /* Output a reference to a label. */ #define ASM_OUTPUT_LABELREF(STREAM,NAME) \ - fprintf (STREAM, "_%s", NAME) + fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, NAME) /* Make an internal label into a string. */ #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \ @@ -1496,13 +1513,13 @@ do { \ sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER))) /* Output a push or a pop instruction (only used when profiling). */ -#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \ - fprintf(STREAM,"\tstmfd\t%ssp!,{%s%s}\n", ARM_REG_PREFIX, ARM_REG_PREFIX, \ - reg_names[REGNO]) - -#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \ - fprintf(STREAM,"\tldmfd\t%ssp!,{%s%s}\n", ARM_REG_PREFIX, ARM_REG_PREFIX, \ - reg_names[REGNO]) +#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \ + fprintf(STREAM,"\tstmfd\t%ssp!,{%s%s}\n", \ + REGISTER_PREFIX, REGISTER_PREFIX, reg_names[REGNO]) + +#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \ + fprintf(STREAM,"\tldmfd\t%ssp!,{%s%s}\n", \ + REGISTER_PREFIX, REGISTER_PREFIX, reg_names[REGNO]) /* Output a relative address. Not needed since jump tables are absolute but we must define it anyway. */ @@ -1525,11 +1542,11 @@ do { char dstr[30]; \ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \ if (sizeof (int) == sizeof (long)) \ - fprintf (STREAM, "\t.long 0x%x,0x%x,0x%x\t%c long double %s\n", \ - l[2], l[1], l[0], ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.long 0x%x,0x%x,0x%x\t%s long double %s\n", \ + l[2], l[1], l[0], ASM_COMMENT_START, dstr); \ else \ - fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%c long double %s\n",\ - l[0], l[1], l[2], ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n",\ + l[0], l[1], l[2], ASM_COMMENT_START, dstr); \ } while (0) @@ -1540,11 +1557,11 @@ do { char dstr[30]; \ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \ if (sizeof (int) == sizeof (long)) \ - fprintf (STREAM, "\t.long 0x%x, 0x%x\t%c double %s\n", l[0], \ - l[1], ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.long 0x%x, 0x%x\t%s double %s\n", l[0], \ + l[1], ASM_COMMENT_START, dstr); \ else \ - fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%c double %s\n", l[0], \ - l[1], ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \ + l[1], ASM_COMMENT_START, dstr); \ } while (0) #define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ @@ -1554,11 +1571,11 @@ do { char dstr[30]; \ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \ if (sizeof (int) == sizeof (long)) \ - fprintf (STREAM, "\t.word 0x%x\t%c float %s\n", l, \ - ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.word 0x%x\t%s float %s\n", l, \ + ASM_COMMENT_START, dstr); \ else \ - fprintf (STREAM, "\t.word 0x%lx\t%c float %s\n", l, \ - ARM_COMMENT_CHAR, dstr); \ + fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \ + ASM_COMMENT_START, dstr); \ } while (0); #define ASM_OUTPUT_INT(STREAM, EXP) \ @@ -1612,7 +1629,7 @@ do { char dstr[30]; \ #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ (fprintf (STREAM, "\t.comm\t"), \ assemble_name ((STREAM), (NAME)), \ - fprintf(STREAM, ", %d\t%c%d\n", ROUNDED, ARM_COMMENT_CHAR, SIZE)) + fprintf(STREAM, ", %d\t%s %d\n", ROUNDED, ASM_COMMENT_START, SIZE)) /* Output a local common block. /bin/as can't do this, so hack a `.space' into the bss segment. Note that this is *bad* practice. */ @@ -1645,13 +1662,8 @@ do { char dstr[30]; \ if (optimize) \ final_prescan_insn (INSN, OPVEC, NOPERANDS) -#ifndef ARM_COMMENT_CHAR -#define ARM_COMMENT_CHAR '@' -#endif - -/* Default is for register names not to have a prefix. */ -#ifndef ARM_REG_PREFIX -#define ARM_REG_PREFIX "" +#ifndef ASM_COMMENT_START +#define ASM_COMMENT_START "@" #endif #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ @@ -1674,7 +1686,7 @@ do { char dstr[30]; \ int is_minus = GET_CODE (X) == MINUS; \ \ if (GET_CODE (X) == REG) \ - fprintf (STREAM, "[%s%s, #0]", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s, #0]", REGISTER_PREFIX, \ reg_names[REGNO (X)]); \ else if (GET_CODE (X) == PLUS || is_minus) \ { \ @@ -1696,14 +1708,14 @@ do { char dstr[30]; \ offset = INTVAL (index); \ if (is_minus) \ offset = -offset; \ - fprintf (STREAM, "[%s%s, #%d]", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s, #%d]", REGISTER_PREFIX, \ base_reg_name, offset); \ break; \ \ case REG: \ - fprintf (STREAM, "[%s%s, %s%s%s]", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s, %s%s%s]", REGISTER_PREFIX, \ base_reg_name, is_minus ? "-" : "", \ - ARM_REG_PREFIX, reg_names[REGNO (index)] ); \ + REGISTER_PREFIX, reg_names[REGNO (index)] ); \ break; \ \ case MULT: \ @@ -1712,8 +1724,8 @@ do { char dstr[30]; \ case ASHIFT: \ case ROTATERT: \ { \ - fprintf (STREAM, "[%s%s, %s%s%s", ARM_REG_PREFIX, \ - base_reg_name, is_minus ? "-" : "", ARM_REG_PREFIX,\ + fprintf (STREAM, "[%s%s, %s%s%s", REGISTER_PREFIX, \ + base_reg_name, is_minus ? "-" : "", REGISTER_PREFIX,\ reg_names[REGNO (XEXP (index, 0))]); \ arm_print_operand (STREAM, index, 'S'); \ fputs ("]", STREAM); \ @@ -1733,12 +1745,12 @@ do { char dstr[30]; \ abort (); \ \ if (GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \ - fprintf (STREAM, "[%s%s, #%s%d]!", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s, #%s%d]!", REGISTER_PREFIX, \ reg_names[REGNO (XEXP (X, 0))], \ GET_CODE (X) == PRE_DEC ? "-" : "", \ GET_MODE_SIZE (output_memory_reference_mode)); \ else \ - fprintf (STREAM, "[%s%s], #%s%d", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s], #%s%d", REGISTER_PREFIX, \ reg_names[REGNO (XEXP (X, 0))], \ GET_CODE (X) == POST_DEC ? "-" : "", \ GET_MODE_SIZE (output_memory_reference_mode)); \