1  /* Xstormy16 cpu description.
       2     Copyright (C) 1997-2023 Free Software Foundation, Inc.
       3     Contributed by Red Hat, Inc.
       4  
       5     This file is part of GCC.
       6  
       7     GCC is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3, or (at your option)
      10     any later version.
      11  
      12     GCC is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with GCC; see the file COPYING3.  If not see
      19     <http://www.gnu.org/licenses/>.  */
      20  
      21  
      22  /* Driver configuration.  */
      23  
      24  #undef  ASM_SPEC
      25  #define ASM_SPEC ""
      26  
      27  #undef  LINK_SPEC
      28  #define LINK_SPEC "%{h*} %{v:-V} \
      29  		   %{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic}"
      30  
      31  /* For xstormy16:
      32     - If -msim is specified, everything is built and linked as for the sim.
      33     - If -T is specified, that linker script is used, and it should provide
      34       appropriate libraries.
      35     - If neither is specified, everything is built as for the sim, but no
      36       I/O support is assumed.  */
      37  #undef  LIB_SPEC
      38  #define LIB_SPEC "-( -lc %{msim:-lsim}%{!msim:%{!T*:-lnosys}} -)"
      39  
      40  #undef  STARTFILE_SPEC
      41  #define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
      42  
      43  #undef  ENDFILE_SPEC
      44  #define ENDFILE_SPEC "crtend.o%s crtn.o%s"
      45  
      46  
      47  /* Run-time target specifications.  */
      48  
      49  #define TARGET_CPU_CPP_BUILTINS()		\
      50    do						\
      51      {						\
      52        builtin_define_std ("xstormy16");		\
      53        builtin_assert ("machine=xstormy16");	\
      54        builtin_assert ("cpu=xstormy16");		\
      55      }						\
      56    while (0)
      57  
      58  /* Storage Layout.  */
      59  
      60  #define BITS_BIG_ENDIAN 1
      61  
      62  #define BYTES_BIG_ENDIAN 0
      63  
      64  #define WORDS_BIG_ENDIAN 0
      65  
      66  #define UNITS_PER_WORD 2
      67  
      68  #define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE)	\
      69    do						\
      70      {						\
      71        if (GET_MODE_CLASS (MODE) == MODE_INT	\
      72  	  && GET_MODE_SIZE (MODE) < 2)		\
      73  	(MODE) = HImode;			\
      74      }						\
      75    while (0)
      76  
      77  #define PARM_BOUNDARY 16
      78  
      79  #define STACK_BOUNDARY 16
      80  
      81  #define FUNCTION_BOUNDARY 16
      82  
      83  #define BIGGEST_ALIGNMENT 16
      84  
      85  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
      86    (TREE_CODE (TYPE) == ARRAY_TYPE		\
      87     && TYPE_MODE (TREE_TYPE (TYPE)) == QImode	\
      88     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
      89  
      90  #define STRICT_ALIGNMENT 1
      91  
      92  #define PCC_BITFIELD_TYPE_MATTERS 1
      93  
      94  /* Layout of Source Language Data Types.  */
      95  
      96  #define INT_TYPE_SIZE 16
      97  
      98  #define SHORT_TYPE_SIZE 16
      99  
     100  #define LONG_TYPE_SIZE 32
     101  
     102  #define LONG_LONG_TYPE_SIZE 64
     103  
     104  #define FLOAT_TYPE_SIZE 32
     105  
     106  #define DOUBLE_TYPE_SIZE 64
     107  
     108  #define LONG_DOUBLE_TYPE_SIZE 64
     109  
     110  #define DEFAULT_SIGNED_CHAR 0
     111  
     112  #define SIZE_TYPE "unsigned int"
     113  
     114  #define PTRDIFF_TYPE "int"
     115  
     116  #undef  WCHAR_TYPE
     117  #define WCHAR_TYPE "long int"
     118  
     119  #undef  WCHAR_TYPE_SIZE
     120  #define WCHAR_TYPE_SIZE 32
     121  
     122  
     123  /* Register Basics.  */
     124  
     125  #define FIRST_PSEUDO_REGISTER 19
     126  
     127  #define FIXED_REGISTERS \
     128    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1 }
     129  
     130  #define CALL_USED_REGISTERS \
     131    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }
     132  
     133  
     134  /* Order of allocation of registers.  */
     135  
     136  #define REG_ALLOC_ORDER { 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 10, 11, 12, 13, 14, 15, 16 }
     137  
     138  
     139  /* Register Classes.  */
     140  
     141  enum reg_class
     142  {
     143    NO_REGS,
     144    R0_REGS,
     145    R1_REGS,
     146    TWO_REGS,
     147    R2_REGS,
     148    EIGHT_REGS,
     149    R8_REGS,
     150    ICALL_REGS,
     151    GENERAL_REGS,
     152    ALL_REGS,
     153    LIM_REG_CLASSES
     154  };
     155  
     156  #define N_REG_CLASSES ((int) LIM_REG_CLASSES)
     157  
     158  #define REG_CLASS_NAMES				\
     159  {						\
     160    "NO_REGS", 					\
     161    "R0_REGS", 					\
     162    "R1_REGS",					\
     163    "TWO_REGS",					\
     164    "R2_REGS",					\
     165    "EIGHT_REGS",					\
     166    "R8_REGS",					\
     167    "ICALL_REGS",					\
     168    "GENERAL_REGS",				\
     169    "ALL_REGS"					\
     170  }
     171  
     172  #define REG_CLASS_CONTENTS			\
     173  {						\
     174    { 0x00000 },					\
     175    { 0x00001 },					\
     176    { 0x00002 },					\
     177    { 0x00003 },					\
     178    { 0x00004 },					\
     179    { 0x000FF },					\
     180    { 0x00100 },					\
     181    { 0x00300 },					\
     182    { 0x6FFFF },					\
     183    { (1 << FIRST_PSEUDO_REGISTER) - 1 }		\
     184  }
     185  
     186  #define REGNO_REG_CLASS(REGNO) 			\
     187    (  (REGNO) ==  0 ? R0_REGS			\
     188     : (REGNO) ==  1 ? R1_REGS			\
     189     : (REGNO) ==  2 ? R2_REGS			\
     190     : (REGNO) <   8 ? EIGHT_REGS			\
     191     : (REGNO) ==  8 ? R8_REGS			\
     192     : (REGNO) <= 18 ? GENERAL_REGS		\
     193     : ALL_REGS)
     194  
     195  #define BASE_REG_CLASS GENERAL_REGS
     196  
     197  #define INDEX_REG_CLASS GENERAL_REGS
     198  
     199  #define REGNO_OK_FOR_BASE_P(NUM) 1
     200  
     201  #define REGNO_OK_FOR_INDEX_P(NUM) REGNO_OK_FOR_BASE_P (NUM)
     202  
     203  /* This chip has the interesting property that only the first eight
     204     registers can be moved to/from memory.  */
     205  #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X)			\
     206    xstormy16_secondary_reload_class (CLASS, MODE, X)
     207  
     208  
     209  /* Basic Stack Layout.  */
     210  
     211  /* We want to use post-increment instructions to push things on the stack,
     212     because we don't have any pre-increment ones.  */
     213  #define STACK_PUSH_CODE POST_INC
     214  
     215  #define FRAME_GROWS_DOWNWARD 0
     216  
     217  #define ARGS_GROW_DOWNWARD 1
     218  
     219  #define FIRST_PARM_OFFSET(FUNDECL) 0
     220  
     221  #define RETURN_ADDR_RTX(COUNT, FRAMEADDR)	\
     222    ((COUNT) == 0					\
     223     ? gen_rtx_MEM (Pmode, arg_pointer_rtx)	\
     224     : NULL_RTX)
     225  
     226  #define INCOMING_RETURN_ADDR_RTX  \
     227     gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-4)))
     228  
     229  #define INCOMING_FRAME_SP_OFFSET (xstormy16_interrupt_function_p () ? -6 : -4)
     230  
     231  #define DEFAULT_INCOMING_FRAME_SP_OFFSET -4
     232  
     233  /* Register That Address the Stack Frame.  */
     234  
     235  #define STATIC_CHAIN_REGNUM	 1
     236  #define HARD_FRAME_POINTER_REGNUM 13
     237  #define STACK_POINTER_REGNUM	15
     238  #define CARRY_REGNUM		16
     239  #define FRAME_POINTER_REGNUM	17
     240  #define ARG_POINTER_REGNUM	18
     241  
     242  
     243  /* Eliminating the Frame Pointer and the Arg Pointer.  */
     244  
     245  #define ELIMINABLE_REGS					\
     246  {							\
     247    {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},		\
     248    {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},	\
     249    {ARG_POINTER_REGNUM,	 STACK_POINTER_REGNUM},		\
     250    {ARG_POINTER_REGNUM,	 HARD_FRAME_POINTER_REGNUM},	\
     251  }
     252  
     253  #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
     254    (OFFSET) = xstormy16_initial_elimination_offset (FROM, TO)
     255  
     256  
     257  /* Passing Function Arguments on the Stack.  */
     258  
     259  #define PUSH_ROUNDING(BYTES) xstormy16_push_rounding (BYTES)
     260  
     261  
     262  /* Function Arguments in Registers.  */
     263  
     264  #define NUM_ARGUMENT_REGISTERS  6
     265  #define FIRST_ARGUMENT_REGISTER 2
     266  
     267  #define XSTORMY16_WORD_SIZE(TYPE, MODE)				\
     268    ((((TYPE) ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE))	\
     269      + 1) 							\
     270     / 2)
     271  
     272  /* For this platform, the value of CUMULATIVE_ARGS is the number of words
     273     of arguments that have been passed in registers so far.  */
     274  #define CUMULATIVE_ARGS int
     275  
     276  #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
     277    (CUM) = 0
     278  
     279  #define FUNCTION_ARG_REGNO_P(REGNO)					\
     280    ((REGNO) >= FIRST_ARGUMENT_REGISTER 					\
     281     && (REGNO) < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS)
     282  
     283  
     284  /* How Scalar Function Values are Returned.  */
     285  
     286  /* The number of the hard register that is used to return a scalar value from a
     287     function call.  */
     288  #define RETURN_VALUE_REGNUM	FIRST_ARGUMENT_REGISTER
     289  
     290  
     291  /* Function Entry and Exit.  */
     292  
     293  #define EPILOGUE_USES(REGNO) \
     294    xstormy16_epilogue_uses (REGNO)
     295  
     296  
     297  /* Generating Code for Profiling.  */
     298  
     299  /* This declaration must be present, but it can be an abort if profiling is
     300     not implemented.  */
     301       
     302  #define FUNCTION_PROFILER(FILE, LABELNO) xstormy16_function_profiler ()
     303  
     304  
     305  /* Trampolines for Nested Functions.  */
     306  
     307  #define TRAMPOLINE_SIZE 8
     308  #define TRAMPOLINE_ALIGNMENT 16
     309  
     310  
     311  /* Addressing Modes.  */
     312  
     313  #define HAVE_POST_INCREMENT 1
     314  
     315  #define HAVE_PRE_DECREMENT 1
     316  
     317  #define MAX_REGS_PER_ADDRESS 1
     318  
     319  
     320  /* Describing Relative Costs of Operations.  */
     321  
     322  #define BRANCH_COST(speed_p, predictable_p) 5
     323  
     324  #define SLOW_BYTE_ACCESS 0
     325  
     326  #define NO_FUNCTION_CSE 1
     327  
     328  
     329  /* Dividing the output into sections.  */
     330  
     331  #define TEXT_SECTION_ASM_OP ".text"
     332  
     333  #define DATA_SECTION_ASM_OP ".data"
     334  
     335  #define BSS_SECTION_ASM_OP "\t.section\t.bss"
     336  
     337  /* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
     338     There are no shared libraries on this target so these sections need
     339     not be writable.
     340  
     341     Defined in elfos.h.  */
     342  
     343  #undef CTORS_SECTION_ASM_OP
     344  #undef DTORS_SECTION_ASM_OP
     345  #define CTORS_SECTION_ASM_OP	"\t.section\t.ctors,\"a\""
     346  #define DTORS_SECTION_ASM_OP	"\t.section\t.dtors,\"a\""
     347  
     348  #define TARGET_ASM_INIT_SECTIONS xstormy16_asm_init_sections
     349  
     350  #define JUMP_TABLES_IN_TEXT_SECTION 1
     351  
     352  /* The Overall Framework of an Assembler File.  */
     353  
     354  #define ASM_COMMENT_START ";"
     355  
     356  #define ASM_APP_ON "#APP\n"
     357  
     358  #define ASM_APP_OFF "#NO_APP\n"
     359  
     360  /* Output of Data.  */
     361  
     362  #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '|')
     363  
     364  #define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
     365    xstormy16_asm_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 1)
     366  #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
     367    xstormy16_asm_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
     368  
     369  
     370  /* Output and Generation of Labels.  */
     371  #define SYMBOL_FLAG_XSTORMY16_BELOW100	(SYMBOL_FLAG_MACH_DEP << 0)
     372  
     373  #define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL)	\
     374    do						\
     375      {						\
     376        const char *rn = XSTR (SYMBOL, 0);	\
     377  						\
     378        if (SYMBOL_REF_FUNCTION_P (SYMBOL))	\
     379  	ASM_OUTPUT_LABEL_REF ((STREAM), rn);	\
     380        else					\
     381  	assemble_name (STREAM, rn);		\
     382      }						\
     383    while (0)
     384  
     385  #define ASM_OUTPUT_LABEL_REF(STREAM, NAME)	\
     386    do						\
     387      {						\
     388        fputs ("@fptr(", STREAM);			\
     389        assemble_name (STREAM, NAME);		\
     390        fputc (')', STREAM);			\
     391      }						\
     392    while (0)
     393  
     394  /* Globalizing directive for a label.  */
     395  #define GLOBAL_ASM_OP "\t.globl "
     396  
     397  
     398  /* Output of Assembler Instructions.  */
     399  
     400  #define REGISTER_NAMES							\
     401  { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",	\
     402    "r11", "r12", "r13", "psw", "sp", "carry", "fp", "ap" }
     403  
     404  #define ADDITIONAL_REGISTER_NAMES		\
     405    { { "r14", 14 },				\
     406      { "r15", 15 } }
     407  
     408  #define REGISTER_PREFIX ""
     409  #define LOCAL_LABEL_PREFIX "."
     410  #define USER_LABEL_PREFIX ""
     411  #define IMMEDIATE_PREFIX "#"
     412  
     413  #define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
     414    fprintf (STREAM, "\tpush %d\n", REGNO)
     415  
     416  #define ASM_OUTPUT_REG_POP(STREAM, REGNO) \
     417    fprintf (STREAM, "\tpop %d\n", REGNO)
     418  
     419  
     420  /* Output of dispatch tables.  */
     421  
     422  /* This port does not use the ASM_OUTPUT_ADDR_VEC_ELT macro, because
     423     this could cause label alignment to appear between the 'br' and the table,
     424     which would be bad.  Instead, it controls the output of the table
     425     itself.  */
     426  #define ASM_OUTPUT_ADDR_VEC(LABEL, BODY) \
     427    xstormy16_output_addr_vec (file, LABEL, BODY)
     428  
     429  /* Alignment for ADDR_VECs is the same as for code.  */
     430  #define ADDR_VEC_ALIGN(ADDR_VEC) 1
     431  
     432  
     433  /* Assembler Commands for Exception Regions.  */
     434  
     435  #define DWARF2_UNWIND_INFO 		0
     436  #define DWARF_CIE_DATA_ALIGNMENT	1
     437  
     438  /* Assembler Commands for Alignment.  */
     439  
     440  #define ASM_OUTPUT_ALIGN(STREAM, POWER) \
     441    fprintf ((STREAM), "\t.p2align %d\n", (POWER))
     442  
     443  
     444  /* Macros Affecting all Debug Formats.  */
     445  
     446  #undef  PREFERRED_DEBUGGING_TYPE
     447  #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
     448  
     449  
     450  /* Macros for Dwarf Output.  */
     451  
     452  /* Define this macro if addresses in Dwarf 2 debugging info should not
     453     be the same size as pointers on the target architecture.  The
     454     macro's value should be the size, in bytes, to use for addresses in
     455     the debugging info.
     456  
     457     Some architectures use word addresses to refer to code locations,
     458     but Dwarf 2 info always uses byte addresses.  On such machines,
     459     Dwarf 2 addresses need to be larger than the architecture's
     460     pointers.  */
     461  #define DWARF2_ADDR_SIZE 4
     462  
     463  
     464  /* Miscellaneous Parameters.  */
     465  
     466  #define CASE_VECTOR_MODE SImode
     467  
     468  #define WORD_REGISTER_OPERATIONS 1
     469  
     470  #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
     471  
     472  #define MOVE_MAX 2
     473  
     474  #define SHIFT_COUNT_TRUNCATED 1
     475  
     476  #define Pmode HImode
     477  
     478  #define FUNCTION_MODE HImode