]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/pdp11/pdp11.h
Update copyright years.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.h
index f995bc8672b37d979935726ebc93da861142014d..2446fea0b58f06c3ddbe2b82cc3b50c21ba4afb3 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler, for the pdp-11
-   Copyright (C) 1994-2018 Free Software Foundation, Inc.
+   Copyright (C) 1994-2024 Free Software Foundation, Inc.
    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
 This file is part of GCC.
@@ -32,19 +32,35 @@ along with GCC; see the file COPYING3.  If not see
   do                                           \
     {                                          \
       builtin_define_std ("pdp11");            \
+      if (TARGET_INT16)                                        \
+       builtin_define_with_int_value ("__pdp11_int", 16);      \
+      else                                                     \
+       builtin_define_with_int_value ("__pdp11_int", 32);      \
+      if (TARGET_40)                                           \
+       builtin_define_with_int_value ("__pdp11_model", 40);    \
+      else if (TARGET_45)                                      \
+       builtin_define_with_int_value ("__pdp11_model", 45);    \
+      else                                                     \
+       builtin_define_with_int_value ("__pdp11_model", 10);    \
+      if (TARGET_FPU)                                          \
+       builtin_define ("__pdp11_fpu");                         \
+      if (TARGET_AC0)                                          \
+       builtin_define ("__pdp11_ac0");                         \
     }                                          \
   while (0)
 
-
-/* Generate DBX debugging information.  */
-
-#define DBX_DEBUGGING_INFO
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
 
 #define TARGET_40_PLUS         (TARGET_40 || TARGET_45)
 #define TARGET_10              (! TARGET_40_PLUS)
 
 #define TARGET_UNIX_ASM_DEFAULT        0
 
+/* "Dialect" just distinguishes between standard DEC mnemonics, which
+   are also used by the GNU assembler, vs. Unix mnemonics and float
+   register names.  So it is tied to the -munit-asm option, and treats
+   -mgnu-asm and -mdec-asm as equivalent (both are dialect zero).  */
 #define ASSEMBLER_DIALECT      (TARGET_UNIX_ASM ? 1 : 0)
 
 \f
@@ -55,12 +71,14 @@ along with GCC; see the file COPYING3.  If not see
 #define LONG_TYPE_SIZE         32
 #define LONG_LONG_TYPE_SIZE    64     
 
-/* if we set FLOAT_TYPE_SIZE to 32, we could have the benefit 
-   of saving core for huge arrays - the definitions are 
-   already in md - but floats can never reside in 
-   an FPU register - we keep the FPU in double float mode 
-   all the time !! */
-#define FLOAT_TYPE_SIZE                (TARGET_FLOAT32 ? 32 : 64)
+/* In earlier versions, FLOAT_TYPE_SIZE was selectable as 32 or 64,
+   but that conflicts with Fortran language rules.  Since there is no
+   obvious reason why we should have that feature -- other targets
+   generally don't have float and double the same size -- I've removed
+   it.  Note that it continues to be true (for now) that arithmetic is
+   always done with 64-bit values, i.e., the FPU is always in "double"
+   mode.  */
+#define FLOAT_TYPE_SIZE                32
 #define DOUBLE_TYPE_SIZE       64
 #define LONG_DOUBLE_TYPE_SIZE  64
 
@@ -124,21 +142,10 @@ extern const struct real_format pdp11_d_format;
    when given unaligned data.  */
 #define STRICT_ALIGNMENT 1
 
-/* Adjust the length of shifts by small constant amounts.  The base
-   value (in "length" on input) is the length of a shift by one, not
-   including the CLC in logical shifts.  */
-#define ADJUST_INSN_LENGTH(insn, length) \
-  if ((GET_CODE (insn) == ASHIFT ||     \
-       GET_CODE (insn) == ASHIFTRT || \
-       GET_CODE (insn) == LSHIFTRT) && \
-      GET_CODE (XEXP (insn, 2)) == CONST_INT && \
-      pdp11_small_shift (XINT (insn, 2))) \
-    {                                    \
-      if (GET_CODE (insn) == LSHIFTRT)   \
-       length = (length * XINT (insn, 2)) + 2; \
-      else \
-       length *= XINT (insn, 2); \
-    }
+/* "HW_DIVIDE" actually means 64 by 32 bit divide.  While some PDP11
+   models have hardware divide, it is for 32 by 16 bits only, so we
+   call this platform "no hardware divide".  */
+#define TARGET_HAS_NO_HW_DIVIDE 1
 \f
 /* Standard register usage.  */
 
@@ -163,7 +170,7 @@ extern const struct real_format pdp11_d_format;
 #define FIXED_REGISTERS  \
 {0, 0, 0, 0, 0, 0, 1, 1, \
  0, 0, 0, 0, 0, 0, 1, 1, \
- 1, 1 }
+ 1 }
 
 
 
@@ -178,7 +185,7 @@ extern const struct real_format pdp11_d_format;
 #define CALL_USED_REGISTERS  \
 {1, 1, 0, 0, 0, 0, 1, 1, \
  0, 0, 0, 0, 0, 0, 1, 1, \
- 1, 1 }
+ 1 }
 
 
 /* Specify the registers used for certain standard purposes.
@@ -212,16 +219,22 @@ extern const struct real_format pdp11_d_format;
 
 MUL_REGS are used for odd numbered regs, to use in 16-bit multiplication
          (even numbered do 32-bit multiply)
-LMUL_REGS long multiply registers (even numbered regs )
-         (don't need them, all 32-bit regs are even numbered!)
 GENERAL_REGS is all cpu
 LOAD_FPU_REGS is the first four cpu regs, they are easier to load
 NO_LOAD_FPU_REGS is ac4 and ac5, currently - difficult to load them
 FPU_REGS is all fpu regs 
+CC_REGS is the condition codes (CPU and FPU)
 */
 
 enum reg_class
   { NO_REGS,
+    NOTR0_REG,
+    NOTR1_REG,
+    NOTR2_REG,
+    NOTR3_REG,
+    NOTR4_REG,
+    NOTR5_REG,
+    NOTSP_REG,
     MUL_REGS,
     GENERAL_REGS,
     LOAD_FPU_REGS,
@@ -240,6 +253,13 @@ enum reg_class
 
 #define REG_CLASS_NAMES  \
   { "NO_REGS",          \
+    "NOTR0_REG",        \
+    "NOTR1_REG",        \
+    "NOTR2_REG",        \
+    "NOTR3_REG",        \
+    "NOTR4_REG",        \
+    "NOTR5_REG",        \
+    "SP_REG",           \
     "MUL_REGS",         \
     "GENERAL_REGS",     \
     "LOAD_FPU_REGS",    \
@@ -254,13 +274,20 @@ enum reg_class
 
 #define REG_CLASS_CONTENTS \
   { {0x00000}, /* NO_REGS */           \
-    {0x000aa}, /* MUL_REGS */          \
-    {0x0c0ff}, /* GENERAL_REGS */      \
+    {0x000fe}, /* NOTR0_REG */         \
+    {0x000fd}, /* NOTR1_REG */         \
+    {0x000fb}, /* NOTR2_REG */         \
+    {0x000f7}, /* NOTR3_REG */         \
+    {0x000ef}, /* NOTR4_REG */         \
+    {0x000df}, /* NOTR5_REG */         \
+    {0x000bf}, /* NOTSP_REG */         \
+    {0x0002a}, /* MUL_REGS */          \
+    {0x040ff}, /* GENERAL_REGS */      \
     {0x00f00}, /* LOAD_FPU_REGS */     \
     {0x03000}, /* NO_LOAD_FPU_REGS */  \
     {0x03f00}, /* FPU_REGS */          \
-    {0x30000}, /* CC_REGS */           \
-    {0x3ffff}} /* ALL_REGS */
+    {0x18000}, /* CC_REGS */           \
+    {0x1ffff}} /* ALL_REGS */
 
 /* The same information, inverted:
    Return the class number of the smallest class containing
@@ -273,13 +300,17 @@ enum reg_class
 #define INDEX_REG_CLASS GENERAL_REGS
 #define BASE_REG_CLASS GENERAL_REGS
 
+/* Return TRUE if the class is a CPU register.  */
+#define CPU_REG_CLASS(CLASS) \
+  (CLASS >= NOTR0_REG && CLASS <= GENERAL_REGS)
+  
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)   \
-((CLASS == GENERAL_REGS || CLASS == MUL_REGS)?                         \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD):      \
-                                                                     \
-)
+  (CPU_REG_CLASS (CLASS) ?     \
+   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD):     \
+   1                                                                   \
+  )
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -339,16 +370,13 @@ extern int current_first_parm_offset;
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
-#define FUNCTION_PROFILER(FILE, LABELNO)  \
-   gcc_unreachable ();
+#define FUNCTION_PROFILER(FILE, LABELNO)
 
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
    functions that have frame pointers.
    No definition is equivalent to always zero.  */
 
-extern int may_call_alloca;
-
 #define EXIT_IGNORE_STACK      1
 
 /* Definitions for register eliminations.
@@ -358,17 +386,14 @@ extern int may_call_alloca;
    followed by "to".  Eliminations of the same "from" register are listed
    in order of preference.
 
-   There are two registers that can always be eliminated on the pdp11.
-   The frame pointer and the arg pointer can be replaced by either the
-   hard frame pointer or to the stack pointer, depending upon the
-   circumstances.  The hard frame pointer is not used before reload and
-   so it is not eligible for elimination.  */
+   There are two registers that can be eliminated on the pdp11.  The
+   arg pointer can be replaced by the frame pointer; the frame pointer
+   can often be replaced by the stack pointer.  */
 
 #define ELIMINABLE_REGS                                        \
 {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},          \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},     \
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},          \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
 
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
   ((OFFSET) = pdp11_initial_elimination_offset ((FROM), (TO)))
@@ -386,7 +411,7 @@ extern int may_call_alloca;
    They give nonzero only if REGNO is a hard reg of the suitable class
    or a pseudo reg currently allocated to a suitable hard reg.
    Since they use reg_renumber, they are safe only once reg_renumber
-   has been allocated, which happens in reginfo.c during register
+   has been allocated, which happens in reginfo.cc during register
    allocation.  */
 
 #define REGNO_OK_FOR_BASE_P(REGNO)  \
@@ -450,23 +475,21 @@ extern int may_call_alloca;
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  
 */
-
 #define MOVE_MAX 2
 
-/* Nonzero if access to memory by byte is slow and undesirable. -
-*/
-#define SLOW_BYTE_ACCESS 0
+/* Max number of insns to use for inline move rather than library
+   call.  */
+#define MOVE_RATIO(speed) 6
 
-/* Do not break .stabs pseudos into continuations.  */
-#define DBX_CONTIN_LENGTH 0
+/* Nonzero if access to memory by byte is no faster than by word.  */
+#define SLOW_BYTE_ACCESS 1
 
 /* Give a comparison code (EQ, NE etc) and the first operand of a COMPARE,
    return the mode to be used for the comparison.  */
 
 #define SELECT_CC_MODE(OP,X,Y) pdp11_cc_mode (OP, X, Y)
 
-/* Enable compare elimination pass.
-   FIXME: how can this be enabled for two registers?  */
+/* Enable compare elimination pass.  */
 #undef TARGET_FLAGS_REGNUM
 #define TARGET_FLAGS_REGNUM CC_REGNUM
 
@@ -505,97 +528,120 @@ extern int may_call_alloca;
 
 /* Output before read-only data.  */
 
-#define TEXT_SECTION_ASM_OP "\t.text\n"
+#define TEXT_SECTION_ASM_OP \
+  ((TARGET_DEC_ASM) ? "\t.psect\tcode,i,ro,con" : "\t.text")
 
 /* Output before writable data.  */
 
-#define DATA_SECTION_ASM_OP "\t.data\n"
+#define DATA_SECTION_ASM_OP \
+  ((TARGET_DEC_ASM) ? "\t.psect\tdata,d,rw,con" : "\t.data")
+
+/* Output before read-only data.  Same as read-write data for non-DEC
+   assemblers because they don't know about .rodata.  */
+
+#define READONLY_DATA_SECTION_ASM_OP \
+  ((TARGET_DEC_ASM) ? "\t.psect\trodata,d,ro,con" : "\t.data")
 
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
 
 #define REGISTER_NAMES \
 {"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc",     \
- "ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "fp", "ap", \
- "cc", "fcc" }
+ "ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "ap", "cc", \
+ "fcc" }
 
 /* Globalizing directive for a label.  */
-#define GLOBAL_ASM_OP "\t.globl "
+#define GLOBAL_ASM_OP "\t.globl\t"
 
-/* The prefix to add to user-visible assembler symbols.  */
+/* The prefix to add to user-visible assembler symbols.  For the DEC
+   assembler case, this is not used.  */
 
 #define USER_LABEL_PREFIX "_"
 
+/* Line separators.  */
+
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) \
+  ((C) == '\n' || (!TARGET_DEC_ASM && (C) == ';'))
+
 /* This is how to store into the string LABEL
    the symbol_ref name of an internal numbered label where
    PREFIX is the class of label and NUM is the number within the class.
    This is suitable for output with `assemble_name'.  */
 
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
-  sprintf (LABEL, "*%s_%lu", PREFIX, (unsigned long)(NUM))
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+  pdp11_gen_int_label ((LABEL), (PREFIX), (NUM))
+
+/* Emit a string.  */
 
 #define ASM_OUTPUT_ASCII(FILE, P, SIZE)  \
   output_ascii (FILE, P, SIZE)
 
-/* This is how to output an element of a case-vector that is absolute.  */
+/* Print a label reference, with _ prefix if not DEC.  */
 
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
-  fprintf (FILE, "\t%sL_%d\n", TARGET_UNIX_ASM ? "" : ".word ", VALUE)
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+  pdp11_output_labelref ((STREAM), (NAME))
+
+/* Equate a symbol to an expression.  */
 
-/* This is how to output an element of a case-vector that is relative.
-   Don't define this if it is not supported.  */
+#define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) \
+  pdp11_output_def (STREAM, NAME, VALUE)
 
-/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */
+/* Mark a reference to an external symbol.  Needed for DEC assembler.  */
 
-/* This is how to output an assembler line
-   that says to advance the location counter
-   to a multiple of 2**LOG bytes. 
+#define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) \
+  if (TARGET_DEC_ASM) \
+    fprintf ((STREAM), "\t.globl\t%s\n", (NAME))
 
-   who needs this????
+#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \
+  if (TARGET_DEC_ASM) \
+    fprintf ((STREAM), ".title\t%s\n", (NAME))
+
+/* This is how to output an element of a case-vector that is absolute.  */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
+  pdp11_output_addr_vec_elt (FILE, VALUE)
+
+/* This is how to output an assembler line that says to advance the
+   location counter to a multiple of 2**LOG bytes.  Only values 0 and
+   1 should appear, but due to PR87795 larger values (which are not
+   supported) can also appear.  So we treat all alignment of LOG >= 1
+   as word (2 byte) alignment.
 */
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)     \
-  switch (LOG)                         \
-    {                                  \
-      case 0:                          \
-       break;                          \
-      case 1:                          \
-       fprintf (FILE, "\t.even\n");    \
-       break;                          \
-      default:                         \
-       gcc_unreachable ();             \
-    }
+  if (LOG != 0)                                \
+    fprintf (FILE, "\t.even\n")
 
 #define ASM_OUTPUT_SKIP(FILE,SIZE)  \
-  fprintf (FILE, "\t.=.+ %#ho\n", (unsigned short)(SIZE))
+  do {                                                         \
+    if (TARGET_DEC_ASM)                                                \
+      fprintf (FILE, "\t.blkb\t%o\n", (int) ((SIZE) & 0xffff));        \
+    else                                                       \
+      fprintf (FILE, "\t.=.+ %#o\n", (int) ((SIZE) & 0xffff)); \
+  } while (0)
 
 /* This says how to output an assembler line
    to define a global common symbol.  */
 
 #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)  \
-    pdp11_asm_output_var (FILE, NAME, SIZE, ALIGN, true)
-
+  pdp11_asm_output_var (FILE, NAME, SIZE, ALIGN, true)
 
 /* This says how to output an assembler line
    to define a local common symbol.  */
 
 #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
-    pdp11_asm_output_var (FILE, NAME, SIZE, ALIGN, false)
+  pdp11_asm_output_var (FILE, NAME, SIZE, ALIGN, false)
 
 /* Print a memory address as an operand to reference that memory location.  */
 
 #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
- print_operand_address (FILE, ADDR)
 print_operand_address (FILE, ADDR)
 
-#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)                        \
-(                                                      \
-  fprintf (FILE, "\tmov %s, -(sp)\n", reg_names[REGNO])        \
-)
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)        \
+  fprintf (FILE, "\tmov\t%s,-(sp)\n", reg_names[REGNO])
 
-#define ASM_OUTPUT_REG_POP(FILE,REGNO)                                 \
-(                                                              \
-  fprintf (FILE, "\tmov (sp)+, %s\n", reg_names[REGNO])        \
-)
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+  fprintf (FILE, "\tmov\t(sp)+,%s\n", reg_names[REGNO])
 
 #define TRAMPOLINE_SIZE 8
 #define TRAMPOLINE_ALIGNMENT 16
@@ -604,6 +650,7 @@ extern int may_call_alloca;
 
 #define COMPARE_FLAG_MODE HImode
 
+/* May be overridden by command option processing.  */
 #define TARGET_HAVE_NAMED_SECTIONS false
 
 /* pdp11-unknown-aout target has no support of C99 runtime */