--- gcc/config/1750a/1750a.h 2018/04/24 18:22:37 1.1.1.1 +++ gcc/config/1750a/1750a.h 2018/04/24 18:30:21 1.1.1.2 @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler. - Copyright (C) 1994 Free Software Foundation, Inc. - Contributed by O.M.Kellogg, DASA (okellogg@salyko.cube.net). + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de) This file is part of GNU CC. @@ -16,7 +16,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. */ /* Names to predefine in the preprocessor for this target machine. */ @@ -199,6 +200,15 @@ extern char *strdup(), *float_label(); { 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1 } +/* Order in which to allocate registers. Each register must be + listed once, even those in FIXED_REGISTERS. List frame pointer + late and fixed registers last. Note that, in general, we prefer + registers listed in CALL_USED_REGISTERS, keeping the others + available for storage of persistent values. */ + +#define REG_ALLOC_ORDER \ + { 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } + /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. This is ordinarily the length in words of a value of mode MODE @@ -250,7 +260,7 @@ extern char *strdup(), *float_label(); #define STRUCT_VALUE_REGNUM 12 /* Define this to be 1 if all structure return values must be in memory. */ -#define DEFAUT_PCC_STRUCT_RETURN 0 +#define DEFAULT_PCC_STRUCT_RETURN 0 /*****************************************************************************/ @@ -285,7 +295,7 @@ extern char *strdup(), *float_label(); This naming inversion is due to the GCC defined capabilities of "Base" vs. "Index" regs. */ -enum reg_class { NO_REGS, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLASSES }; +enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES @@ -296,7 +306,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA /* Give names of register classes as strings for dump file. */ #define REG_CLASS_NAMES \ - { "NO_REGS", "INDEX_REGS", "BASE_REGS", "ALL_REGS" } + { "NO_REGS", "R2", "R0_1", "INDEX_REGS", "BASE_REGS", "ALL_REGS" } /* Define which registers fit in which classes. This is an initializer for a vector of HARD_REG_SET @@ -304,14 +314,14 @@ enum reg_class { NO_REGS, INDEX_REGS, BA 1750 "index" (remember, in the *GCC* sense!) regs are R12 through R15. The only 1750 register not usable as BASE_REG is R0. */ -#define REG_CLASS_CONTENTS {0, 0xf000, 0xfffe, 0xffff} +#define REG_CLASS_CONTENTS {0, 0x0004, 0x0003, 0xf000, 0xfffe, 0xffff} /* The same information, inverted: Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression or could index an array. */ -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) >= 12 ? INDEX_REGS : (REGNO) > 0 ? BASE_REGS : ALL_REGS) +#define REGNO_REG_CLASS(REGNO) ((REGNO) == 2 ? R2 : (REGNO) == 0 ? R0_1 : \ + (REGNO) >= 12 ? INDEX_REGS : (REGNO) > 0 ? BASE_REGS : ALL_REGS) /* The class value for index registers, and the one for base regs. */ @@ -319,9 +329,12 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define INDEX_REG_CLASS INDEX_REGS /* Get reg_class from a letter such as appears in the machine description. - For the 1750, we have 'b' for gcc Base regs and 'x' for gcc Index regs. */ + For the 1750, we have 'z' for R0_1, 't' for R2, 'b' for gcc Base regs + and 'x' for gcc Index regs. */ -#define REG_CLASS_FROM_LETTER(C) ((C) == 'b' ? BASE_REGS : \ +#define REG_CLASS_FROM_LETTER(C) ((C) == 't' ? R2 : \ + (C) == 'z' ? R0_1 : \ + (C) == 'b' ? BASE_REGS : \ (C) == 'x' ? INDEX_REGS : NO_REGS) /* The letters I,J,K,.. to P in a register constraint string @@ -351,11 +364,22 @@ enum reg_class { NO_REGS, INDEX_REGS, BA Here VALUE is the CONST_DOUBLE rtx itself. */ #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 +/* Optional extra constraints for this machine. + + For the 1750, `Q' means that this is a memory operand consisting + of the sum of an Index Register (in the GCC sense, i.e. R12..R15) + and a constant in the range 0..255. This constraint is used for + the Base Register with Offset address mode instructions (LB,STB,AB,..) */ + +#define EXTRA_CONSTRAINT(OP, C) \ + ((C) == 'Q' && b_mode_operand (OP)) + /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines in some cases it is preferable to use a more restrictive class. For the 1750A, we force an immediate CONST_DOUBLE value to memory. */ + #define PREFERRED_RELOAD_CLASS(X,CLASS) \ (GET_CODE(X) == CONST_DOUBLE ? NO_REGS : CLASS) @@ -422,11 +446,12 @@ enum reg_class { NO_REGS, INDEX_REGS, BA /* Value is 1 if returning from a function call automatically pops the arguments described by the number-of-args field in the 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. */ -#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). @@ -517,7 +542,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA /* Define the following macro if function calls on the target machine do not preserve any registers; in other words, if `CALL_USED_REGISTERS' has 1 for all registers. This macro enables `-fcaller-saves' by - default. Eventually that option will be nabled by default on all + default. Eventually that option will be enabled by default on all machines and both the option and this macro will be eliminated. */ #define DEFAULT_CALLER_SAVES @@ -587,11 +612,11 @@ enum reg_class { NO_REGS, INDEX_REGS, BA before returning. */ #define FUNCTION_EPILOGUE(FILE, SIZE) { \ + fprintf(FILE,"\tlr\tr15,r14 ; set stack ptr to frame ptr\n"); \ + fprintf(FILE,"\tpopm\tr14,r14 ; restore previous frame ptr\n"); \ if (SIZE > 0) \ - fprintf(FILE,"\t%s\tr14,%d ; free up local-var space\n", \ + fprintf(FILE,"\t%s\tr15,%d ; free up local-var space\n", \ (SIZE <= 16 ? "aisp" : "aim"),SIZE); \ - fprintf(FILE,"\tlr\tr15,r14 ; set stack to return addr\n"); \ - fprintf(FILE,"\tpopm\tr14,r14 ; restore prev. frame ptr\n"); \ fprintf(FILE,"\turs\tr15\n"); } /* If the memory address ADDR is relative to the frame pointer, @@ -661,13 +686,13 @@ enum reg_class { NO_REGS, INDEX_REGS, BA Since they use reg_renumber, they are safe only once reg_renumber has been allocated, which happens in local-alloc.c. 1750 note: The words BASE and INDEX are used in their GCC senses: - The "Index Registers", R12 through R15, can have an address displacement - int the range 0..255 words. + The "Index Registers", R12 through R15, are used in the 1750 + instructions LB,STB,AB,SBB,MB,DB,LBX,STBX,... */ #define REGNO_OK_FOR_BASE_P(REGNO) \ ((REGNO) > 0 && (REGNO) <= 15 || \ - reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 15) + reg_renumber[REGNO] > 0 && reg_renumber[REGNO] <= 15) #define REGNO_OK_FOR_INDEX_P(REGNO) \ ((REGNO) >= 12 && (REGNO) <= 15 || \ reg_renumber[REGNO] >= 12 && reg_renumber[REGNO] <= 15) @@ -707,9 +732,9 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #ifdef REG_OK_STRICT /* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +#define REG_OK_FOR_INDEX_P(X) (REGNO (X) >= 12 && REGNO (X) <= 15) /* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#define REG_OK_FOR_BASE_P(X) (REGNO (X) > 0 && REGNO (X) <= 15) #else @@ -788,7 +813,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define EASY_DIV_EXPR TRUNC_DIV_EXPR /* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 0 +#define DEFAULT_SIGNED_CHAR 1 /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ @@ -836,7 +861,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ case CONST_INT: \ - if (INTVAL(RTX) >= -16 && INTVAL(RTX) <= 16) return 1; \ + return (INTVAL(RTX) >= -16 && INTVAL(RTX) <= 16) ? 1 : 3; \ case CONST: \ case LABEL_REF: \ case SYMBOL_REF: \ @@ -844,7 +869,11 @@ enum reg_class { NO_REGS, INDEX_REGS, BA case CONST_DOUBLE: \ return 7; -#define ADDRESS_COST(ADDRESS) (memop_valid(ADDRESS) ? 3 : 1000) +#define ADDRESS_COST(ADDRESS) (memop_valid(ADDRESS) ? 3 : 1000) + +#define REGISTER_MOVE_COST(FROM,TO) 2 + +#define MEMORY_MOVE_COST(M) 5 /* Tell final.c how to eliminate redundant test instructions. */ @@ -931,29 +960,30 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define EXTRA_SECTIONS in_readonly_data #define EXTRA_SECTION_FUNCTIONS \ - void const_section() \ - { \ - fprintf(asm_out_file,"\tkonst\n"); \ + void const_section() \ + { \ + fprintf(asm_out_file,"\tkonst\n"); \ current_section = Konst; \ - } \ - check_section(enum section sect) \ - { \ - if (current_section != sect) { \ + } \ + check_section(sect) \ + enum section sect; \ + { \ + if (current_section != sect) { \ fprintf(asm_out_file,"\t%s\n",sectname[(int)sect]); \ - current_section = sect; \ - } \ - switch (sect) { \ - case Init: \ - case Normal: \ - in_section = in_text; \ - break; \ - case Static: \ - in_section = in_data; \ - break; \ - case Konst: \ - in_section = in_readonly_data; \ - break; \ - } \ + current_section = sect; \ + } \ + switch (sect) { \ + case Init: \ + case Normal: \ + in_section = in_text; \ + break; \ + case Static: \ + in_section = in_data; \ + break; \ + case Konst: \ + in_section = in_readonly_data; \ + break; \ + } \ } @@ -966,8 +996,11 @@ enum reg_class { NO_REGS, INDEX_REGS, BA /* Output before program text section */ #define TEXT_SECTION_ASM_OP "\n\tnormal ; text_section\n" -/* Output before writable data. */ -#define DATA_SECTION_ASM_OP "\n\tstatic ; data_section\n" +/* Output before writable data. + 1750 Note: This is actually read-only data. The copying from read-only + to writable memory is done elsewhere (in ASM_FILE_END.) + */ +#define DATA_SECTION_ASM_OP "\n\tkonst ; data_section\n" /* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */ @@ -1020,7 +1053,9 @@ enum reg_class { NO_REGS, INDEX_REGS, BA else { \ check_section(Konst); \ fprintf(FILE,"K%s\n",NAME); \ + fflush(FILE); \ datalbl[++datalbl_ndx].name = (char *)strdup (NAME); \ + datalbl[datalbl_ndx].size = 0; \ label_pending = 1; \ } \ } while (0) @@ -1048,6 +1083,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA label_pending = 1; \ datalbl[++datalbl_ndx].name = (char *) malloc (9); \ sprintf(datalbl[datalbl_ndx].name,"LC%d",NUM); \ + datalbl[datalbl_ndx].size = 0; \ check_section(Konst); \ fprintf(FILE,"K%s%d\n",PREFIX,NUM); \ } \ @@ -1056,6 +1092,7 @@ enum reg_class { NO_REGS, INDEX_REGS, BA jmplbl[jmplbl_ndx].pc = program_counter; \ fprintf(FILE, "%s%d\n", PREFIX, NUM); \ } \ + fflush(FILE); \ } while (0) @@ -1067,17 +1104,34 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ sprintf (LABEL, "%s%d", PREFIX, NUM) +/* Output at the end of a jump table. + 1750: To be uncommented when we can put jump tables in Konst. + #define ASM_OUTPUT_CASE_END(FILE,NUM,INSN) \ + fprintf (FILE, "\tnormal\t; case_end\n") + */ + +/* Currently, it is not possible to put jump tables in section Konst. + This is because there is a one-to-one relation between sections Konst + and Static (i.e., all Konst data are copied to Static, and the order + of data is the same between the two sections.) However, jump tables are + not copied to Static, which destroys the equivalence between Konst and + Static. When a more intelligent Konst-to-Static copying mechanism is + implemented (i.e. one that excludes the copying of jumptables), then + ASM_OUTPUT_CASE_END shall be defined, and JUMP_LABELS_IN_TEXT_SECTION + shall be undefined. */ + +#define JUMP_TABLES_IN_TEXT_SECTION 1 + /* This is how to output an assembler line defining a 1750A `float' constant. */ #define ASM_OUTPUT_SHORT_FLOAT(FILE,VALUE) \ do { \ - if (label_pending) \ + if (label_pending) { \ label_pending = 0; \ - else \ - datalbl[++datalbl_ndx].name = float_label('D',VALUE); \ - sprintf (datalbl[datalbl_ndx].value, "%lf", (double) VALUE); \ - datalbl[datalbl_ndx].size = 2; \ + sprintf (datalbl[datalbl_ndx].value, "%lf", (double) VALUE); \ + } \ + datalbl[datalbl_ndx].size += 2; \ fprintf (FILE, "\tdataf\t%lf\n",VALUE); \ } while(0) @@ -1086,12 +1140,11 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define ASM_OUTPUT_THREE_QUARTER_FLOAT(FILE,VALUE) \ do { \ - if (label_pending) \ + if (label_pending) { \ label_pending = 0; \ - else \ - datalbl[++datalbl_ndx].name = float_label('E',VALUE); \ - sprintf (datalbl[datalbl_ndx].value, "%lf", VALUE); \ - datalbl[datalbl_ndx].size = 3; \ + sprintf (datalbl[datalbl_ndx].value, "%lf", VALUE); \ + } \ + datalbl[datalbl_ndx].size += 3; \ fprintf(FILE,"\tdataef\t%lf\n",VALUE); \ } while (0) @@ -1099,55 +1152,64 @@ enum reg_class { NO_REGS, INDEX_REGS, BA #define ASM_OUTPUT_ASCII(FILE, PTR, LEN) do { \ int i; \ - if (! label_pending) \ - fprintf(FILE,";in ASM_OUTPUT_ASCII without label_pending\n");\ - else { \ + if (label_pending) \ label_pending = 0; \ - datalbl[datalbl_ndx].size = LEN; \ - } \ - for (i = 0; i < LEN; i++) \ + datalbl[datalbl_ndx].size += LEN; \ + for (i = 0; i < LEN; i++) { \ + if ((i % 15) == 0) { \ + if (i != 0) \ + fprintf(FILE,"\n"); \ + fprintf(FILE,"\tdata\t"); \ + } \ + else \ + fprintf(FILE,","); \ if (PTR[i] >= 32 && PTR[i] < 127) \ - fprintf(FILE,"\tdata\t%d\t; '%c'\n",PTR[i],PTR[i]); \ + fprintf(FILE,"'%c'",PTR[i]); \ else \ - fprintf(FILE,"\tdata\t%d\t; (ascii)\n",PTR[i]); \ + fprintf(FILE,"%d",PTR[i]); \ + } \ + fprintf(FILE,"\n"); \ } while (0) -/* This is how to output an assembler line defining an `int' constant. */ +/* This is how to output an assembler line defining a `char', `short', or + `int' constant. + 1750 NOTE: The reason why this macro also outputs `short' and `int' + constants is that for the 1750, BITS_PER_UNIT is 16 (as opposed to the + usual 8.) This behavior is different from the usual, where + ASM_OUTPUT_CHAR only outputs character constants. The name + of this macro should perhaps be `ASM_OUTPUT_QUARTER_INT' or so. + */ -#define ASM_OUTPUT_INT(FILE,VALUE) do { \ - if (! label_pending) \ - fprintf(FILE,";in ASM_OUTPUT_INT without label_pending\n"); \ - else { \ +#define ASM_OUTPUT_CHAR(FILE,VALUE) do { \ + if (label_pending) \ label_pending = 0; \ - datalbl[datalbl_ndx].size = 1; \ - } \ - fprintf(FILE, "\tdata\t"); output_addr_const(FILE,VALUE); \ - fprintf(FILE, "\n"); } while (0) + datalbl[datalbl_ndx].size++; \ + fprintf(FILE, "\tdata\t"); \ + output_addr_const(FILE, VALUE); \ + fprintf(FILE, "\n"); \ + } while (0) -/* This is how to output an assembler line defining a `long int' constant. */ +/* This is how to output an assembler line defining a `long int' constant. + 1750 NOTE: The reason why this macro outputs `long' instead of `short' + constants is that for the 1750, BITS_PER_UNIT is 16 (as opposed to the + usual 8.) The name of this macro should perhaps be `ASM_OUTPUT_HALF_INT'. + */ -#define ASM_OUTPUT_LONG_INT(FILE,VALUE) do { \ - if (! label_pending) \ - fprintf(FILE,";in ASM_OUTPUT_LONG_INT without label_pending\n");\ - else { \ +#define ASM_OUTPUT_SHORT(FILE,VALUE) do { \ + if (label_pending) \ label_pending = 0; \ - datalbl[datalbl_ndx].size = 2; \ - } \ - fprintf(FILE, "\tdatal\t"); output_addr_const(FILE,VALUE); \ - fprintf(FILE, "\n"); } while (0) - -/* Likewise for `short' and `char' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) ASM_OUTPUT_INT(FILE,VALUE) - -/* For 1750, we treat char same as word. Tektronix 1750 - Assembler does a better (packing) job with strings. */ -#define ASM_OUTPUT_CHAR(FILE,VALUE) ASM_OUTPUT_INT(FILE,VALUE) + datalbl[datalbl_ndx].size += 2; \ + fprintf(FILE, "\tdatal\t%d\n",INTVAL(VALUE)); \ + } while (0) /* This is how to output an assembler line for a numeric constant byte. */ -/* 1750: For the time being, treating this same as word. Tektronix 1750 - Assembler does a better (packing) job with strings. */ -#define ASM_OUTPUT_BYTE(FILE,VALUE) ASM_OUTPUT_INT(FILE,VALUE) + +#define ASM_OUTPUT_BYTE(FILE,VALUE) do { \ + if (label_pending) \ + label_pending = 0; \ + datalbl[datalbl_ndx].size++; \ + fprintf(FILE, "\tdata\t#%x\n", VALUE); \ + } while (0) /* This is how to output an insn to push a register on the stack. It need not be very fast code. */ @@ -1185,7 +1247,8 @@ enum reg_class { NO_REGS, INDEX_REGS, BA to define a global common symbol. */ #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) do { \ - fprintf (FILE, "\tcommon %s,%d\n", NAME, SIZE); \ + check_section(Static); \ + fprintf (FILE, "\tcommon %s,%d\n", NAME, SIZE); \ } while (0) #define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) do { \ @@ -1209,12 +1272,12 @@ enum reg_class { NO_REGS, INDEX_REGS, BA sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) #define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) do { \ - fprintf(FILE, "\tinit\n\t"); assemble_name(NAME); \ - fprintf(FILE," ;constructor"); } while (0) + fprintf(FILE, "\tinit\n\t"); assemble_name(FILE, NAME); \ + fprintf(FILE," ;constructor\n"); } while (0) #define ASM_OUTPUT_DESTRUCTOR(FILE, NAME) do { \ - fprintf(FILE, "\tinit\n\t"); assemble_name(NAME); \ - fprintf(FILE," ;destructor"); } while (0) + fprintf(FILE, "\tinit\n\t"); assemble_name(FILE, NAME); \ + fprintf(FILE," ;destructor\n"); } while (0) /* Define the parentheses used to group arithmetic operations in assembler code. */ @@ -1240,7 +1303,9 @@ enum reg_class { NO_REGS, INDEX_REGS, BA E=single precision) label name 'F': print a label defining a floating-point constant value 'J': print the absolute value of a negative INT_CONST - (this is used in LISN/CISN/MISN/SISP and others) */ + (this is used in LISN/CISN/MISN/SISP and others) + 'Q': print a 1750 Base-Register-with-offset instruction's operands + */ /* 1750A: see file aux-output.c */ #define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE)