]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/vax/vax.h
Update copyright years.
[thirdparty/gcc.git] / gcc / config / vax / vax.h
index dae115aa1c4a058ec0b659b43a3b7dcec02f3f88..c1d0171d94da15750225aeaf766b00d492cf080f 100644 (file)
@@ -1,12 +1,11 @@
 /* Definitions of target machine for GNU compiler.  VAX version.
-   Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* Target CPU builtins.  */
@@ -35,8 +33,6 @@ Boston, MA 02110-1301, USA.  */
     }                                          \
   while (0)
 
-#define VMS_TARGET 0
-
 /* Use -J option for long branch support with Unix assembler.  */
 
 #define ASM_SPEC "-J"
@@ -51,26 +47,20 @@ Boston, MA 02110-1301, USA.  */
   %{pg:%eprofiling not supported with -mg\n}}\
  %{!mg:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
 
-/* Print subsidiary information on the compiler version in use.  */
-
-#ifndef TARGET_NAME    /* A more specific value might be supplied via -D.  */
-#define TARGET_NAME "vax"
-#endif
-#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME)
-
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
 /* Nonzero if ELF.  Redefined by vax/elf.h.  */
 #define TARGET_ELF 0
 
+/* Use BSD names for udiv and umod libgcc calls.  */
+#define TARGET_BSD_DIVMOD 1
+
 /* Default target_flags if no switches specified.  */
 
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT (MASK_UNIX_ASM)
 #endif
 
-#define OVERRIDE_OPTIONS override_options ()
-
 \f
 /* Target machine storage layout */
 
@@ -145,24 +135,6 @@ Boston, MA 02110-1301, USA.  */
    Aside from that, you can include as many other registers as you like.  */
 #define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
 
-/* 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
-   but can be less for certain modes in special long registers.
-   On the VAX, all registers are one word long.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)  \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-   On the VAX, all registers can hold all modes.  */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
-
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
-   for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)  1
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
@@ -175,11 +147,8 @@ Boston, MA 02110-1301, USA.  */
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM VAX_FP_REGNUM
 
-/* 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 via the stack pointer) in functions that seem suitable.
-   This is computed in `reload', in reload1.c.  */
-#define FRAME_POINTER_REQUIRED 1
+/* Offset from the frame pointer register value to the top of stack.  */
+#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
 
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM VAX_AP_REGNUM
@@ -239,80 +208,19 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 
-#define REGNO_REG_CLASS(REGNO) ALL_REGS
+#define REGNO_REG_CLASS(REGNO) ((void)(REGNO), ALL_REGS)
 
 /* The class value for index registers, and the one for base regs.  */
 
 #define INDEX_REG_CLASS ALL_REGS
 #define BASE_REG_CLASS ALL_REGS
 
-/* Get reg_class from a letter such as appears in the machine description.  */
-
-#define REG_CLASS_FROM_LETTER(C) NO_REGS
-
-/* The letters I, J, K, L, M, N, and O in a register constraint string
-   can be used to stand for particular ranges of immediate operands.
-   This macro defines what the ranges are.
-   C is the letter, and VALUE is a constant value.
-   Return 1 if VALUE is in the range specified by C.
-
-   `I' is the constant zero.
-   `J' is a value between 0 .. 63 (inclusive)
-   `K' is a value between -128 and 127 (inclusive)
-   'L' is a value between -32768 and 32767 (inclusive)
-   `M' is a value between 0 and 255 (inclusive)
-   'N' is a value between 0 and 65535 (inclusive)
-   `O' is a value between -63 and -1 (inclusive)  */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C)                                \
-  (  (C) == 'I' ?      (VALUE) == 0                            \
-   : (C) == 'J' ?      0 <= (VALUE) && (VALUE) < 64            \
-   : (C) == 'O' ?      -63 <= (VALUE) && (VALUE) < 0           \
-   : (C) == 'K' ?      -128 <= (VALUE) && (VALUE) < 128        \
-   : (C) == 'M' ?      0 <= (VALUE) && (VALUE) < 256           \
-   : (C) == 'L' ?      -32768 <= (VALUE) && (VALUE) < 32768    \
-   : (C) == 'N' ?      0 <= (VALUE) && (VALUE) < 65536         \
-   : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-   Here VALUE is the CONST_DOUBLE rtx itself.
-
-   `G' is a floating-point zero.  */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)         \
-  ((C) == 'G' ? ((VALUE) == CONST0_RTX (DFmode)                \
-                || (VALUE) == CONST0_RTX (SFmode))     \
-   : 0)
-
-/* Optional extra constraints for this machine.
-
-   For the VAX, `Q' means that OP is a MEM that does not have a mode-dependent
-   address.  */
-
-#define EXTRA_CONSTRAINT(OP, C)                                                \
-  ((C) == 'Q'                                                          \
-   ? MEM_P (OP) && ! mode_dependent_address_p (XEXP (OP, 0))   \
-   : 0)
-
-/* 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.  */
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS)  (CLASS)
-
-/* Return the maximum number of consecutive registers
-   needed to represent mode MODE in a register of class CLASS.  */
-/* On the VAX, this is always the size of MODE in words,
-   since all registers are the same size.  */
-#define CLASS_MAX_NREGS(CLASS, MODE)   \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
 /* Define this if pushing a word on the stack
    makes the stack pointer a smaller address.  */
-#define STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
 
 /* Define this to nonzero if the nominal address of the stack frame
    is at the high-address end of the local variables;
@@ -320,16 +228,10 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    goes at a more negative offset in the frame.  */
 #define FRAME_GROWS_DOWNWARD 1
 
-/* Offset within stack frame to start allocating local variables at.
-   If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
-   first local allocated.  Otherwise, it is the offset to the BEGINNING
-   of the first local allocated.  */
-#define STARTING_FRAME_OFFSET 0
-
 /* Given an rtx for the address of a frame,
    return an rtx for the address of the word in the frame
    that holds the dynamic chain--the previous frame's address.  */
-#define DYNAMIC_CHAIN_ADDRESS(FRAME) plus_constant ((FRAME), 12)
+#define DYNAMIC_CHAIN_ADDRESS(FRAME) plus_constant (Pmode, (FRAME), 12)
 
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by.
@@ -339,18 +241,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 /* Offset of first parameter from the argument pointer register value.  */
 #define FIRST_PARM_OFFSET(FNDECL) 4
 
-/* Value is the number of bytes 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 VAX, the RET insn pops a maximum of 255 args for any function.  */
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
-  ((SIZE) > 255 * 4 ? 0 : (SIZE))
-
 /* 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;
@@ -381,7 +271,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 /* 1 if N is a possible register number for function argument passing.
    On the VAX, no registers are used in this way.  */
 
-#define FUNCTION_ARG_REGNO_P(N) 0
+#define FUNCTION_ARG_REGNO_P(N) ((void) (N), 0)
 \f
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should
@@ -403,32 +293,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
  ((CUM) = 0)
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
-  ((CUM) += ((MODE) != BLKmode                         \
-            ? (GET_MODE_SIZE (MODE) + 3) & ~3          \
-            : (int_size_in_bytes (TYPE) + 3) & ~3))
-
-/* Define where to put the arguments to a function.
-   Value is zero to push the argument on the stack,
-   or a hard register in which to store the argument.
-
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
-   CUM is a variable of type CUMULATIVE_ARGS which gives info about
-    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
-
-/* On the VAX all args are pushed.  */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
-
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
@@ -445,6 +309,16 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
     }                                                          \
   while (0)
 
+/* This macro specifies a table of register pairs used to eliminate
+   unneeded registers that point into the stack frame.  */
+#define ELIMINABLE_REGS {{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+
+/* On the VAX, FRAME_POINTER_REQUIRED is always 1, so the definition of this
+   macro doesn't matter for register eliminations, but it should still
+   give realistic data for rtx_addr_can_trap_p.  */
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+  ((OFFSET) = get_frame_size ())
+
 /* 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.
@@ -452,54 +326,10 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 #define EXIT_IGNORE_STACK 1
 
-/* Store in the variable DEPTH the initial difference between the
-   frame pointer reg contents and the stack pointer reg contents,
-   as of the start of the function body.  This depends on the layout
-   of the fixed parts of the stack frame and on how registers are saved.
-
-   On the VAX, FRAME_POINTER_REQUIRED is always 1, so the definition of this
-   macro doesn't matter.  But it must be defined.  */
-
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0;
-
-/* Output assembler code for a block containing the constant parts
-   of a trampoline, leaving space for the variable parts.  */
-
-/* On the VAX, the trampoline contains an entry mask and two instructions:
-     .word NN
-     movl $STATIC,r0   (store the functions static chain)
-     jmp  *$FUNCTION   (jump to function code at address FUNCTION)  */
-
-#define TRAMPOLINE_TEMPLATE(FILE)                                      \
-{                                                                      \
-  assemble_aligned_integer (2, const0_rtx);                            \
-  assemble_aligned_integer (2, GEN_INT (0x8fd0));                      \
-  assemble_aligned_integer (4, const0_rtx);                            \
-  assemble_aligned_integer (1, GEN_INT (0x50 + STATIC_CHAIN_REGNUM));  \
-  assemble_aligned_integer (2, GEN_INT (0x9f17));                      \
-  assemble_aligned_integer (4, const0_rtx);                            \
-}
-
 /* Length in units of the trampoline for entering a nested function.  */
 
 #define TRAMPOLINE_SIZE 15
 
-/* Emit RTL insns to initialize the variable parts of a trampoline.
-   FNADDR is an RTX for the address of the function's pure code.
-   CXT is an RTX for the static chain value for the function.  */
-
-/* We copy the register-mask from the function's pure code
-   to the start of the trampoline.  */
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                      \
-{                                                                      \
-  emit_move_insn (gen_rtx_MEM (HImode, TRAMP),                         \
-                 gen_rtx_MEM (HImode, FNADDR));                        \
-  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 4)), CXT);        \
-  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 11)),     \
-                 plus_constant (FNADDR, 2));                           \
-  emit_insn (gen_sync_istream ());                                     \
-}
-
 /* Byte offset of return address in a stack frame.  The "saved PC" field
    is in element [4] when treating the frame as an array of longwords.  */
 
@@ -512,7 +342,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 #define RETURN_ADDR_RTX(COUNT, FRAME)                                  \
   ((COUNT == 0)                                                                \
-   ? gen_rtx_MEM (Pmode, plus_constant (FRAME, RETURN_ADDRESS_OFFSET)) \
+   ? gen_rtx_MEM (Pmode, plus_constant (Pmode, FRAME,                  \
+                                       RETURN_ADDRESS_OFFSET))         \
    : (rtx) 0)
 
 \f
@@ -528,7 +359,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    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 local-alloc.c.  */
+   has been allocated, which happens in reginfo.c during register
+   allocation.  */
 
 #define REGNO_OK_FOR_INDEX_P(regno)    \
   ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
@@ -543,11 +375,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 #define CONSTANT_ADDRESS_P(X) legitimate_constant_address_p (X)
 
-/* Nonzero if the constant value X is a legitimate general operand.
-   It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
-
-#define LEGITIMATE_CONSTANT_P(X) legitimate_constant_p (X)
-
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
    We have two alternate definitions for each of them.
@@ -571,11 +398,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) 1
 
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-   that is a valid memory address for an instruction.  */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-  { if (legitimate_address_p ((MODE), (X), 0)) goto ADDR; }
-
 #else
 
 /* Nonzero if X is a hard reg that can be used as an index.  */
@@ -584,17 +406,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 /* 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))
 
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-   that is a valid memory address for an instruction.  */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-  { if (legitimate_address_p ((MODE), (X), 1)) goto ADDR; }
-
 #endif
-
-/* Go to LABEL if ADDR (a legitimate address expression)
-   has an effect that depends on the machine mode it is used for.  */
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
-  { if (vax_mode_dependent_address_p (ADDR)) goto LABEL; }
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
@@ -613,14 +425,15 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 1
 
-/* This flag, if defined, says the same insns that convert to a signed fixnum
-   also convert validly to an unsigned one.  */
-#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
-
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
 #define MOVE_MAX 8
 
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+   move-instruction pairs, we will do a cpymem or libcall instead.  */
+#define MOVE_RATIO(speed) ((speed) ? 6 : 3)
+#define CLEAR_RATIO(speed) ((speed) ? 6 : 2)
+
 /* Nonzero if access to memory by bytes is slow and undesirable.  */
 #define SLOW_BYTE_ACCESS 0
 
@@ -629,10 +442,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    of a shift count.  */
 /* #define SHIFT_COUNT_TRUNCATED */
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
@@ -643,17 +452,13 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    so give the MEM rtx a byte's mode.  */
 #define FUNCTION_MODE QImode
 
-/* This machine doesn't use IEEE floats.  */
-
-#define TARGET_FLOAT_FORMAT VAX_FLOAT_FORMAT
-
 /* Specify the cost of a branch insn; roughly the number of extra insns that
    should be added to avoid a branch.
 
    Branches are extremely cheap on the VAX while the shift insns often
    used to replace branches can be expensive.  */
 
-#define BRANCH_COST 0
+#define BRANCH_COST(speed_p, predictable_p) 0
 \f
 /* Tell final.c how to eliminate redundant test instructions.  */
 
@@ -825,14 +630,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
     assemble_name ((FILE), (NAME)),                    \
     fprintf ((FILE), ",%u\n", (int)(ROUNDED)))
 
-/* Store in OUTPUT a string (made with alloca) containing
-   an assembler-name for a local static variable named NAME.
-   LABELNO is an integer which is different for each call.  */
-
-#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
-  ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
-    sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-
 /* Print an instruction operand X on file FILE.
    CODE is the code from the %-spec that requested printing this operand;
    if `%z3' was used to print operand 3, then CODE is 'z'.
@@ -840,6 +637,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 VAX operand formatting codes:
 
  letter           print
+   c   direct branch condition
    C   reverse branch condition
    D   64-bit immediate operand
    B   the low 8 bits of the complement of a constant operand
@@ -863,49 +661,11 @@ VAX operand formatting codes:
 #  define NEG_HWI_PRINT_HEX16 "0xffffffff%08lx"
 #endif
 
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE)                              \
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)  \
   ((CODE) == '#' || (CODE) == '|')
 
-#define PRINT_OPERAND(FILE, X, CODE)                                   \
-{ if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE);                      \
-  else if (CODE == '|')                                                        \
-    fputs (REGISTER_PREFIX, FILE);                                     \
-  else if (CODE == 'C')                                                        \
-    fputs (rev_cond_name (X), FILE);                                   \
-  else if (CODE == 'D' && GET_CODE (X) == CONST_INT && INTVAL (X) < 0) \
-    fprintf (FILE, "$" NEG_HWI_PRINT_HEX16, INTVAL (X));               \
-  else if (CODE == 'P' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, INTVAL (X) + 1);       \
-  else if (CODE == 'N' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (X));         \
-  /* rotl instruction cannot deal with negative arguments.  */         \
-  else if (CODE == 'R' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (X));      \
-  else if (CODE == 'H' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$%d", (int) (0xffff & ~ INTVAL (X)));              \
-  else if (CODE == 'h' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$%d", (short) - INTVAL (x));                       \
-  else if (CODE == 'B' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$%d", (int) (0xff & ~ INTVAL (X)));                        \
-  else if (CODE == 'b' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$%d", (int) (0xff & - INTVAL (X)));                        \
-  else if (CODE == 'M' && GET_CODE (X) == CONST_INT)                   \
-    fprintf (FILE, "$%d", ~((1 << INTVAL (x)) - 1));                   \
-  else if (REG_P (X))                                                  \
-    fprintf (FILE, "%s", reg_names[REGNO (X)]);                                \
-  else if (MEM_P (X))                                                  \
-    output_address (XEXP (X, 0));                                      \
-  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)     \
-    { char dstr[30];                                                   \
-      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (X),              \
-                      sizeof (dstr), 0, 1);                            \
-      fprintf (FILE, "$0f%s", dstr); }                                 \
-  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)     \
-    { char dstr[30];                                                   \
-      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (X),              \
-                      sizeof (dstr), 0, 1);                            \
-      fprintf (FILE, "$0%c%s", ASM_DOUBLE_CHAR, dstr); }               \
-  else { putc ('$', FILE); output_addr_const (FILE, X); }}
+#define PRINT_OPERAND(FILE, X, CODE)  \
+  print_operand (FILE, X, CODE)
 
 /* Print a memory operand whose address is X, on file FILE.
    This uses a function in output-vax.c.  */