| 1 | 709 | jeremybenn | /* Subroutines used for code generation on Renesas RX processors.
 | 
      
         | 2 |  |  |    Copyright (C) 2008, 2009, 2010, 2011, 2012
 | 
      
         | 3 |  |  |    Free Software Foundation, Inc.
 | 
      
         | 4 |  |  |    Contributed by Red Hat.
 | 
      
         | 5 |  |  |  
 | 
      
         | 6 |  |  |    This file is part of GCC.
 | 
      
         | 7 |  |  |  
 | 
      
         | 8 |  |  |    GCC is free software; you can redistribute it and/or modify
 | 
      
         | 9 |  |  |    it under the terms of the GNU General Public License as published by
 | 
      
         | 10 |  |  |    the Free Software Foundation; either version 3, or (at your option)
 | 
      
         | 11 |  |  |    any later version.
 | 
      
         | 12 |  |  |  
 | 
      
         | 13 |  |  |    GCC is distributed in the hope that it will be useful,
 | 
      
         | 14 |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
      
         | 15 |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
      
         | 16 |  |  |    GNU General Public License for more details.
 | 
      
         | 17 |  |  |  
 | 
      
         | 18 |  |  |    You should have received a copy of the GNU General Public License
 | 
      
         | 19 |  |  |    along with GCC; see the file COPYING3.  If not see
 | 
      
         | 20 |  |  |    <http://www.gnu.org/licenses/>.  */
 | 
      
         | 21 |  |  |  
 | 
      
         | 22 |  |  | /* To Do:
 | 
      
         | 23 |  |  |  
 | 
      
         | 24 |  |  |  * Re-enable memory-to-memory copies and fix up reload.  */
 | 
      
         | 25 |  |  |  
 | 
      
         | 26 |  |  | #include "config.h"
 | 
      
         | 27 |  |  | #include "system.h"
 | 
      
         | 28 |  |  | #include "coretypes.h"
 | 
      
         | 29 |  |  | #include "tm.h"
 | 
      
         | 30 |  |  | #include "tree.h"
 | 
      
         | 31 |  |  | #include "rtl.h"
 | 
      
         | 32 |  |  | #include "regs.h"
 | 
      
         | 33 |  |  | #include "hard-reg-set.h"
 | 
      
         | 34 |  |  | #include "insn-config.h"
 | 
      
         | 35 |  |  | #include "conditions.h"
 | 
      
         | 36 |  |  | #include "output.h"
 | 
      
         | 37 |  |  | #include "insn-attr.h"
 | 
      
         | 38 |  |  | #include "flags.h"
 | 
      
         | 39 |  |  | #include "function.h"
 | 
      
         | 40 |  |  | #include "expr.h"
 | 
      
         | 41 |  |  | #include "optabs.h"
 | 
      
         | 42 |  |  | #include "libfuncs.h"
 | 
      
         | 43 |  |  | #include "recog.h"
 | 
      
         | 44 |  |  | #include "diagnostic-core.h"
 | 
      
         | 45 |  |  | #include "toplev.h"
 | 
      
         | 46 |  |  | #include "reload.h"
 | 
      
         | 47 |  |  | #include "df.h"
 | 
      
         | 48 |  |  | #include "ggc.h"
 | 
      
         | 49 |  |  | #include "tm_p.h"
 | 
      
         | 50 |  |  | #include "debug.h"
 | 
      
         | 51 |  |  | #include "target.h"
 | 
      
         | 52 |  |  | #include "target-def.h"
 | 
      
         | 53 |  |  | #include "langhooks.h"
 | 
      
         | 54 |  |  | #include "opts.h"
 | 
      
         | 55 |  |  |  
 | 
      
         | 56 |  |  | static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
 | 
      
         | 57 |  |  | static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
 | 
      
         | 58 |  |  | static unsigned int rx_num_interrupt_regs;
 | 
      
         | 59 |  |  |  
 | 
      
         | 60 |  |  | static unsigned int
 | 
      
         | 61 |  |  | rx_gp_base_regnum (void)
 | 
      
         | 62 |  |  | {
 | 
      
         | 63 |  |  |   if (rx_gp_base_regnum_val == INVALID_REGNUM)
 | 
      
         | 64 |  |  |     gcc_unreachable ();
 | 
      
         | 65 |  |  |   return rx_gp_base_regnum_val;
 | 
      
         | 66 |  |  | }
 | 
      
         | 67 |  |  |  
 | 
      
         | 68 |  |  | static unsigned int
 | 
      
         | 69 |  |  | rx_pid_base_regnum (void)
 | 
      
         | 70 |  |  | {
 | 
      
         | 71 |  |  |   if (rx_pid_base_regnum_val == INVALID_REGNUM)
 | 
      
         | 72 |  |  |     gcc_unreachable ();
 | 
      
         | 73 |  |  |   return rx_pid_base_regnum_val;
 | 
      
         | 74 |  |  | }
 | 
      
         | 75 |  |  |  
 | 
      
         | 76 |  |  | /* Find a SYMBOL_REF in a "standard" MEM address and return its decl.  */
 | 
      
         | 77 |  |  |  
 | 
      
         | 78 |  |  | static tree
 | 
      
         | 79 |  |  | rx_decl_for_addr (rtx op)
 | 
      
         | 80 |  |  | {
 | 
      
         | 81 |  |  |   if (GET_CODE (op) == MEM)
 | 
      
         | 82 |  |  |     op = XEXP (op, 0);
 | 
      
         | 83 |  |  |   if (GET_CODE (op) == CONST)
 | 
      
         | 84 |  |  |     op = XEXP (op, 0);
 | 
      
         | 85 |  |  |   while (GET_CODE (op) == PLUS)
 | 
      
         | 86 |  |  |     op = XEXP (op, 0);
 | 
      
         | 87 |  |  |   if (GET_CODE (op) == SYMBOL_REF)
 | 
      
         | 88 |  |  |     return SYMBOL_REF_DECL (op);
 | 
      
         | 89 |  |  |   return NULL_TREE;
 | 
      
         | 90 |  |  | }
 | 
      
         | 91 |  |  |  
 | 
      
         | 92 |  |  | static void rx_print_operand (FILE *, rtx, int);
 | 
      
         | 93 |  |  |  
 | 
      
         | 94 |  |  | #define CC_FLAG_S       (1 << 0)
 | 
      
         | 95 |  |  | #define CC_FLAG_Z       (1 << 1)
 | 
      
         | 96 |  |  | #define CC_FLAG_O       (1 << 2)
 | 
      
         | 97 |  |  | #define CC_FLAG_C       (1 << 3)
 | 
      
         | 98 |  |  | #define CC_FLAG_FP      (1 << 4)        /* Fake, to differentiate CC_Fmode.  */
 | 
      
         | 99 |  |  |  
 | 
      
         | 100 |  |  | static unsigned int flags_from_mode (enum machine_mode mode);
 | 
      
         | 101 |  |  | static unsigned int flags_from_code (enum rtx_code code);
 | 
      
         | 102 |  |  |  
 | 
      
         | 103 |  |  | /* Return true if OP is a reference to an object in a PID data area.  */
 | 
      
         | 104 |  |  |  
 | 
      
         | 105 |  |  | enum pid_type
 | 
      
         | 106 |  |  | {
 | 
      
         | 107 |  |  |   PID_NOT_PID = 0,       /* The object is not in the PID data area.  */
 | 
      
         | 108 |  |  |   PID_ENCODED,          /* The object is in the PID data area.  */
 | 
      
         | 109 |  |  |   PID_UNENCODED         /* The object will be placed in the PID data area, but it has not been placed there yet.  */
 | 
      
         | 110 |  |  | };
 | 
      
         | 111 |  |  |  
 | 
      
         | 112 |  |  | static enum pid_type
 | 
      
         | 113 |  |  | rx_pid_data_operand (rtx op)
 | 
      
         | 114 |  |  | {
 | 
      
         | 115 |  |  |   tree op_decl;
 | 
      
         | 116 |  |  |  
 | 
      
         | 117 |  |  |   if (!TARGET_PID)
 | 
      
         | 118 |  |  |     return PID_NOT_PID;
 | 
      
         | 119 |  |  |  
 | 
      
         | 120 |  |  |   if (GET_CODE (op) == PLUS
 | 
      
         | 121 |  |  |       && GET_CODE (XEXP (op, 0)) == REG
 | 
      
         | 122 |  |  |       && GET_CODE (XEXP (op, 1)) == CONST
 | 
      
         | 123 |  |  |       && GET_CODE (XEXP (XEXP (op, 1), 0)) == UNSPEC)
 | 
      
         | 124 |  |  |     return PID_ENCODED;
 | 
      
         | 125 |  |  |  
 | 
      
         | 126 |  |  |   op_decl = rx_decl_for_addr (op);
 | 
      
         | 127 |  |  |  
 | 
      
         | 128 |  |  |   if (op_decl)
 | 
      
         | 129 |  |  |     {
 | 
      
         | 130 |  |  |       if (TREE_READONLY (op_decl))
 | 
      
         | 131 |  |  |         return PID_UNENCODED;
 | 
      
         | 132 |  |  |     }
 | 
      
         | 133 |  |  |   else
 | 
      
         | 134 |  |  |     {
 | 
      
         | 135 |  |  |       /* Sigh, some special cases.  */
 | 
      
         | 136 |  |  |       if (GET_CODE (op) == SYMBOL_REF
 | 
      
         | 137 |  |  |           || GET_CODE (op) == LABEL_REF)
 | 
      
         | 138 |  |  |         return PID_UNENCODED;
 | 
      
         | 139 |  |  |     }
 | 
      
         | 140 |  |  |  
 | 
      
         | 141 |  |  |   return PID_NOT_PID;
 | 
      
         | 142 |  |  | }
 | 
      
         | 143 |  |  |  
 | 
      
         | 144 |  |  | static rtx
 | 
      
         | 145 |  |  | rx_legitimize_address (rtx x,
 | 
      
         | 146 |  |  |                        rtx oldx ATTRIBUTE_UNUSED,
 | 
      
         | 147 |  |  |                        enum machine_mode mode ATTRIBUTE_UNUSED)
 | 
      
         | 148 |  |  | {
 | 
      
         | 149 |  |  |   if (rx_pid_data_operand (x) == PID_UNENCODED)
 | 
      
         | 150 |  |  |     {
 | 
      
         | 151 |  |  |       rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);
 | 
      
         | 152 |  |  |       return rv;
 | 
      
         | 153 |  |  |     }
 | 
      
         | 154 |  |  |  
 | 
      
         | 155 |  |  |   if (GET_CODE (x) == PLUS
 | 
      
         | 156 |  |  |       && GET_CODE (XEXP (x, 0)) == PLUS
 | 
      
         | 157 |  |  |       && REG_P (XEXP (XEXP (x, 0), 0))
 | 
      
         | 158 |  |  |       && REG_P (XEXP (x, 1)))
 | 
      
         | 159 |  |  |     return force_reg (SImode, x);
 | 
      
         | 160 |  |  |  
 | 
      
         | 161 |  |  |   return x;
 | 
      
         | 162 |  |  | }
 | 
      
         | 163 |  |  |  
 | 
      
         | 164 |  |  | /* Return true if OP is a reference to an object in a small data area.  */
 | 
      
         | 165 |  |  |  
 | 
      
         | 166 |  |  | static bool
 | 
      
         | 167 |  |  | rx_small_data_operand (rtx op)
 | 
      
         | 168 |  |  | {
 | 
      
         | 169 |  |  |   if (rx_small_data_limit == 0)
 | 
      
         | 170 |  |  |     return false;
 | 
      
         | 171 |  |  |  
 | 
      
         | 172 |  |  |   if (GET_CODE (op) == SYMBOL_REF)
 | 
      
         | 173 |  |  |     return SYMBOL_REF_SMALL_P (op);
 | 
      
         | 174 |  |  |  
 | 
      
         | 175 |  |  |   return false;
 | 
      
         | 176 |  |  | }
 | 
      
         | 177 |  |  |  
 | 
      
         | 178 |  |  | static bool
 | 
      
         | 179 |  |  | rx_is_legitimate_address (enum machine_mode mode, rtx x,
 | 
      
         | 180 |  |  |                           bool strict ATTRIBUTE_UNUSED)
 | 
      
         | 181 |  |  | {
 | 
      
         | 182 |  |  |   if (RTX_OK_FOR_BASE (x, strict))
 | 
      
         | 183 |  |  |     /* Register Indirect.  */
 | 
      
         | 184 |  |  |     return true;
 | 
      
         | 185 |  |  |  
 | 
      
         | 186 |  |  |   if ((GET_MODE_SIZE (mode) == 4
 | 
      
         | 187 |  |  |        || GET_MODE_SIZE (mode) == 2
 | 
      
         | 188 |  |  |        || GET_MODE_SIZE (mode) == 1)
 | 
      
         | 189 |  |  |       && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC))
 | 
      
         | 190 |  |  |     /* Pre-decrement Register Indirect or
 | 
      
         | 191 |  |  |        Post-increment Register Indirect.  */
 | 
      
         | 192 |  |  |     return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
 | 
      
         | 193 |  |  |  
 | 
      
         | 194 |  |  |   switch (rx_pid_data_operand (x))
 | 
      
         | 195 |  |  |     {
 | 
      
         | 196 |  |  |     case PID_UNENCODED:
 | 
      
         | 197 |  |  |       return false;
 | 
      
         | 198 |  |  |     case PID_ENCODED:
 | 
      
         | 199 |  |  |       return true;
 | 
      
         | 200 |  |  |     default:
 | 
      
         | 201 |  |  |       break;
 | 
      
         | 202 |  |  |     }
 | 
      
         | 203 |  |  |  
 | 
      
         | 204 |  |  |   if (GET_CODE (x) == PLUS)
 | 
      
         | 205 |  |  |     {
 | 
      
         | 206 |  |  |       rtx arg1 = XEXP (x, 0);
 | 
      
         | 207 |  |  |       rtx arg2 = XEXP (x, 1);
 | 
      
         | 208 |  |  |       rtx index = NULL_RTX;
 | 
      
         | 209 |  |  |  
 | 
      
         | 210 |  |  |       if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, strict))
 | 
      
         | 211 |  |  |         index = arg2;
 | 
      
         | 212 |  |  |       else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, strict))
 | 
      
         | 213 |  |  |         index = arg1;
 | 
      
         | 214 |  |  |       else
 | 
      
         | 215 |  |  |         return false;
 | 
      
         | 216 |  |  |  
 | 
      
         | 217 |  |  |       switch (GET_CODE (index))
 | 
      
         | 218 |  |  |         {
 | 
      
         | 219 |  |  |         case CONST_INT:
 | 
      
         | 220 |  |  |           {
 | 
      
         | 221 |  |  |             /* Register Relative: REG + INT.
 | 
      
         | 222 |  |  |                Only positive, mode-aligned, mode-sized
 | 
      
         | 223 |  |  |                displacements are allowed.  */
 | 
      
         | 224 |  |  |             HOST_WIDE_INT val = INTVAL (index);
 | 
      
         | 225 |  |  |             int factor;
 | 
      
         | 226 |  |  |  
 | 
      
         | 227 |  |  |             if (val < 0)
 | 
      
         | 228 |  |  |               return false;
 | 
      
         | 229 |  |  |  
 | 
      
         | 230 |  |  |             switch (GET_MODE_SIZE (mode))
 | 
      
         | 231 |  |  |               {
 | 
      
         | 232 |  |  |               default:
 | 
      
         | 233 |  |  |               case 4: factor = 4; break;
 | 
      
         | 234 |  |  |               case 2: factor = 2; break;
 | 
      
         | 235 |  |  |               case 1: factor = 1; break;
 | 
      
         | 236 |  |  |               }
 | 
      
         | 237 |  |  |  
 | 
      
         | 238 |  |  |             if (val > (65535 * factor))
 | 
      
         | 239 |  |  |               return false;
 | 
      
         | 240 |  |  |             return (val % factor) == 0;
 | 
      
         | 241 |  |  |           }
 | 
      
         | 242 |  |  |  
 | 
      
         | 243 |  |  |         case REG:
 | 
      
         | 244 |  |  |           /* Unscaled Indexed Register Indirect: REG + REG
 | 
      
         | 245 |  |  |              Size has to be "QI", REG has to be valid.  */
 | 
      
         | 246 |  |  |           return GET_MODE_SIZE (mode) == 1 && RTX_OK_FOR_BASE (index, strict);
 | 
      
         | 247 |  |  |  
 | 
      
         | 248 |  |  |         case MULT:
 | 
      
         | 249 |  |  |           {
 | 
      
         | 250 |  |  |             /* Scaled Indexed Register Indirect: REG + (REG * FACTOR)
 | 
      
         | 251 |  |  |                Factor has to equal the mode size, REG has to be valid.  */
 | 
      
         | 252 |  |  |             rtx factor;
 | 
      
         | 253 |  |  |  
 | 
      
         | 254 |  |  |             factor = XEXP (index, 1);
 | 
      
         | 255 |  |  |             index = XEXP (index, 0);
 | 
      
         | 256 |  |  |  
 | 
      
         | 257 |  |  |             return REG_P (index)
 | 
      
         | 258 |  |  |               && RTX_OK_FOR_BASE (index, strict)
 | 
      
         | 259 |  |  |               && CONST_INT_P (factor)
 | 
      
         | 260 |  |  |               && GET_MODE_SIZE (mode) == INTVAL (factor);
 | 
      
         | 261 |  |  |           }
 | 
      
         | 262 |  |  |  
 | 
      
         | 263 |  |  |         default:
 | 
      
         | 264 |  |  |           return false;
 | 
      
         | 265 |  |  |         }
 | 
      
         | 266 |  |  |     }
 | 
      
         | 267 |  |  |  
 | 
      
         | 268 |  |  |   /* Small data area accesses turn into register relative offsets.  */
 | 
      
         | 269 |  |  |   return rx_small_data_operand (x);
 | 
      
         | 270 |  |  | }
 | 
      
         | 271 |  |  |  
 | 
      
         | 272 |  |  | /* Returns TRUE for simple memory addreses, ie ones
 | 
      
         | 273 |  |  |    that do not involve register indirect addressing
 | 
      
         | 274 |  |  |    or pre/post increment/decrement.  */
 | 
      
         | 275 |  |  |  
 | 
      
         | 276 |  |  | bool
 | 
      
         | 277 |  |  | rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
 | 
      
         | 278 |  |  | {
 | 
      
         | 279 |  |  |   if (! rx_is_legitimate_address
 | 
      
         | 280 |  |  |       (mode, mem, reload_in_progress || reload_completed))
 | 
      
         | 281 |  |  |     return false;
 | 
      
         | 282 |  |  |  
 | 
      
         | 283 |  |  |   switch (GET_CODE (mem))
 | 
      
         | 284 |  |  |     {
 | 
      
         | 285 |  |  |     case REG:
 | 
      
         | 286 |  |  |       /* Simple memory addresses are OK.  */
 | 
      
         | 287 |  |  |       return true;
 | 
      
         | 288 |  |  |  
 | 
      
         | 289 |  |  |     case PRE_DEC:
 | 
      
         | 290 |  |  |     case POST_INC:
 | 
      
         | 291 |  |  |       return false;
 | 
      
         | 292 |  |  |  
 | 
      
         | 293 |  |  |     case PLUS:
 | 
      
         | 294 |  |  |       {
 | 
      
         | 295 |  |  |         rtx base, index;
 | 
      
         | 296 |  |  |  
 | 
      
         | 297 |  |  |         /* Only allow REG+INT addressing.  */
 | 
      
         | 298 |  |  |         base = XEXP (mem, 0);
 | 
      
         | 299 |  |  |         index = XEXP (mem, 1);
 | 
      
         | 300 |  |  |  
 | 
      
         | 301 |  |  |         if (! RX_REG_P (base) || ! CONST_INT_P (index))
 | 
      
         | 302 |  |  |           return false;
 | 
      
         | 303 |  |  |  
 | 
      
         | 304 |  |  |         return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1);
 | 
      
         | 305 |  |  |       }
 | 
      
         | 306 |  |  |  
 | 
      
         | 307 |  |  |     case SYMBOL_REF:
 | 
      
         | 308 |  |  |       /* Can happen when small data is being supported.
 | 
      
         | 309 |  |  |          Assume that it will be resolved into GP+INT.  */
 | 
      
         | 310 |  |  |       return true;
 | 
      
         | 311 |  |  |  
 | 
      
         | 312 |  |  |     default:
 | 
      
         | 313 |  |  |       gcc_unreachable ();
 | 
      
         | 314 |  |  |     }
 | 
      
         | 315 |  |  | }
 | 
      
         | 316 |  |  |  
 | 
      
         | 317 |  |  | /* Implement TARGET_MODE_DEPENDENT_ADDRESS_P.  */
 | 
      
         | 318 |  |  |  
 | 
      
         | 319 |  |  | static bool
 | 
      
         | 320 |  |  | rx_mode_dependent_address_p (const_rtx addr)
 | 
      
         | 321 |  |  | {
 | 
      
         | 322 |  |  |   if (GET_CODE (addr) == CONST)
 | 
      
         | 323 |  |  |     addr = XEXP (addr, 0);
 | 
      
         | 324 |  |  |  
 | 
      
         | 325 |  |  |   switch (GET_CODE (addr))
 | 
      
         | 326 |  |  |     {
 | 
      
         | 327 |  |  |       /* --REG and REG++ only work in SImode.  */
 | 
      
         | 328 |  |  |     case PRE_DEC:
 | 
      
         | 329 |  |  |     case POST_INC:
 | 
      
         | 330 |  |  |       return true;
 | 
      
         | 331 |  |  |  
 | 
      
         | 332 |  |  |     case MINUS:
 | 
      
         | 333 |  |  |     case PLUS:
 | 
      
         | 334 |  |  |       if (! REG_P (XEXP (addr, 0)))
 | 
      
         | 335 |  |  |         return true;
 | 
      
         | 336 |  |  |  
 | 
      
         | 337 |  |  |       addr = XEXP (addr, 1);
 | 
      
         | 338 |  |  |  
 | 
      
         | 339 |  |  |       switch (GET_CODE (addr))
 | 
      
         | 340 |  |  |         {
 | 
      
         | 341 |  |  |         case REG:
 | 
      
         | 342 |  |  |           /* REG+REG only works in SImode.  */
 | 
      
         | 343 |  |  |           return true;
 | 
      
         | 344 |  |  |  
 | 
      
         | 345 |  |  |         case CONST_INT:
 | 
      
         | 346 |  |  |           /* REG+INT is only mode independent if INT is a
 | 
      
         | 347 |  |  |              multiple of 4, positive and will fit into 8-bits.  */
 | 
      
         | 348 |  |  |           if (((INTVAL (addr) & 3) == 0)
 | 
      
         | 349 |  |  |               && IN_RANGE (INTVAL (addr), 4, 252))
 | 
      
         | 350 |  |  |             return false;
 | 
      
         | 351 |  |  |           return true;
 | 
      
         | 352 |  |  |  
 | 
      
         | 353 |  |  |         case SYMBOL_REF:
 | 
      
         | 354 |  |  |         case LABEL_REF:
 | 
      
         | 355 |  |  |           return true;
 | 
      
         | 356 |  |  |  
 | 
      
         | 357 |  |  |         case MULT:
 | 
      
         | 358 |  |  |           gcc_assert (REG_P (XEXP (addr, 0)));
 | 
      
         | 359 |  |  |           gcc_assert (CONST_INT_P (XEXP (addr, 1)));
 | 
      
         | 360 |  |  |           /* REG+REG*SCALE is always mode dependent.  */
 | 
      
         | 361 |  |  |           return true;
 | 
      
         | 362 |  |  |  
 | 
      
         | 363 |  |  |         default:
 | 
      
         | 364 |  |  |           /* Not recognized, so treat as mode dependent.  */
 | 
      
         | 365 |  |  |           return true;
 | 
      
         | 366 |  |  |         }
 | 
      
         | 367 |  |  |  
 | 
      
         | 368 |  |  |     case CONST_INT:
 | 
      
         | 369 |  |  |     case SYMBOL_REF:
 | 
      
         | 370 |  |  |     case LABEL_REF:
 | 
      
         | 371 |  |  |     case REG:
 | 
      
         | 372 |  |  |       /* These are all mode independent.  */
 | 
      
         | 373 |  |  |       return false;
 | 
      
         | 374 |  |  |  
 | 
      
         | 375 |  |  |     default:
 | 
      
         | 376 |  |  |       /* Everything else is unrecognized,
 | 
      
         | 377 |  |  |          so treat as mode dependent.  */
 | 
      
         | 378 |  |  |       return true;
 | 
      
         | 379 |  |  |     }
 | 
      
         | 380 |  |  | }
 | 
      
         | 381 |  |  |  
 | 
      
         | 382 |  |  | /* A C compound statement to output to stdio stream FILE the
 | 
      
         | 383 |  |  |    assembler syntax for an instruction operand that is a memory
 | 
      
         | 384 |  |  |    reference whose address is ADDR.  */
 | 
      
         | 385 |  |  |  
 | 
      
         | 386 |  |  | static void
 | 
      
         | 387 |  |  | rx_print_operand_address (FILE * file, rtx addr)
 | 
      
         | 388 |  |  | {
 | 
      
         | 389 |  |  |   switch (GET_CODE (addr))
 | 
      
         | 390 |  |  |     {
 | 
      
         | 391 |  |  |     case REG:
 | 
      
         | 392 |  |  |       fprintf (file, "[");
 | 
      
         | 393 |  |  |       rx_print_operand (file, addr, 0);
 | 
      
         | 394 |  |  |       fprintf (file, "]");
 | 
      
         | 395 |  |  |       break;
 | 
      
         | 396 |  |  |  
 | 
      
         | 397 |  |  |     case PRE_DEC:
 | 
      
         | 398 |  |  |       fprintf (file, "[-");
 | 
      
         | 399 |  |  |       rx_print_operand (file, XEXP (addr, 0), 0);
 | 
      
         | 400 |  |  |       fprintf (file, "]");
 | 
      
         | 401 |  |  |       break;
 | 
      
         | 402 |  |  |  
 | 
      
         | 403 |  |  |     case POST_INC:
 | 
      
         | 404 |  |  |       fprintf (file, "[");
 | 
      
         | 405 |  |  |       rx_print_operand (file, XEXP (addr, 0), 0);
 | 
      
         | 406 |  |  |       fprintf (file, "+]");
 | 
      
         | 407 |  |  |       break;
 | 
      
         | 408 |  |  |  
 | 
      
         | 409 |  |  |     case PLUS:
 | 
      
         | 410 |  |  |       {
 | 
      
         | 411 |  |  |         rtx arg1 = XEXP (addr, 0);
 | 
      
         | 412 |  |  |         rtx arg2 = XEXP (addr, 1);
 | 
      
         | 413 |  |  |         rtx base, index;
 | 
      
         | 414 |  |  |  
 | 
      
         | 415 |  |  |         if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, true))
 | 
      
         | 416 |  |  |           base = arg1, index = arg2;
 | 
      
         | 417 |  |  |         else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, true))
 | 
      
         | 418 |  |  |           base = arg2, index = arg1;
 | 
      
         | 419 |  |  |         else
 | 
      
         | 420 |  |  |           {
 | 
      
         | 421 |  |  |             rx_print_operand (file, arg1, 0);
 | 
      
         | 422 |  |  |             fprintf (file, " + ");
 | 
      
         | 423 |  |  |             rx_print_operand (file, arg2, 0);
 | 
      
         | 424 |  |  |             break;
 | 
      
         | 425 |  |  |           }
 | 
      
         | 426 |  |  |  
 | 
      
         | 427 |  |  |         if (REG_P (index) || GET_CODE (index) == MULT)
 | 
      
         | 428 |  |  |           {
 | 
      
         | 429 |  |  |             fprintf (file, "[");
 | 
      
         | 430 |  |  |             rx_print_operand (file, index, 'A');
 | 
      
         | 431 |  |  |             fprintf (file, ",");
 | 
      
         | 432 |  |  |           }
 | 
      
         | 433 |  |  |         else /* GET_CODE (index) == CONST_INT  */
 | 
      
         | 434 |  |  |           {
 | 
      
         | 435 |  |  |             rx_print_operand (file, index, 'A');
 | 
      
         | 436 |  |  |             fprintf (file, "[");
 | 
      
         | 437 |  |  |           }
 | 
      
         | 438 |  |  |         rx_print_operand (file, base, 0);
 | 
      
         | 439 |  |  |         fprintf (file, "]");
 | 
      
         | 440 |  |  |         break;
 | 
      
         | 441 |  |  |       }
 | 
      
         | 442 |  |  |  
 | 
      
         | 443 |  |  |     case CONST:
 | 
      
         | 444 |  |  |       if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
 | 
      
         | 445 |  |  |         {
 | 
      
         | 446 |  |  |           addr = XEXP (addr, 0);
 | 
      
         | 447 |  |  |           gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
 | 
      
         | 448 |  |  |  
 | 
      
         | 449 |  |  |           /* FIXME: Putting this case label here is an appalling abuse of the C language.  */
 | 
      
         | 450 |  |  |         case UNSPEC:
 | 
      
         | 451 |  |  |           addr = XVECEXP (addr, 0, 0);
 | 
      
         | 452 |  |  |           gcc_assert (CONST_INT_P (addr));
 | 
      
         | 453 |  |  |         }
 | 
      
         | 454 |  |  |       /* Fall through.  */
 | 
      
         | 455 |  |  |     case LABEL_REF:
 | 
      
         | 456 |  |  |     case SYMBOL_REF:
 | 
      
         | 457 |  |  |       fprintf (file, "#");
 | 
      
         | 458 |  |  |       /* Fall through.  */
 | 
      
         | 459 |  |  |     default:
 | 
      
         | 460 |  |  |       output_addr_const (file, addr);
 | 
      
         | 461 |  |  |       break;
 | 
      
         | 462 |  |  |     }
 | 
      
         | 463 |  |  | }
 | 
      
         | 464 |  |  |  
 | 
      
         | 465 |  |  | static void
 | 
      
         | 466 |  |  | rx_print_integer (FILE * file, HOST_WIDE_INT val)
 | 
      
         | 467 |  |  | {
 | 
      
         | 468 |  |  |   if (IN_RANGE (val, -64, 64))
 | 
      
         | 469 |  |  |     fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
 | 
      
         | 470 |  |  |   else
 | 
      
         | 471 |  |  |     fprintf (file,
 | 
      
         | 472 |  |  |              TARGET_AS100_SYNTAX
 | 
      
         | 473 |  |  |              ? "0%" HOST_WIDE_INT_PRINT "xH" : HOST_WIDE_INT_PRINT_HEX,
 | 
      
         | 474 |  |  |              val);
 | 
      
         | 475 |  |  | }
 | 
      
         | 476 |  |  |  
 | 
      
         | 477 |  |  | static bool
 | 
      
         | 478 |  |  | rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
 | 
      
         | 479 |  |  | {
 | 
      
         | 480 |  |  |   const char *  op = integer_asm_op (size, is_aligned);
 | 
      
         | 481 |  |  |  
 | 
      
         | 482 |  |  |   if (! CONST_INT_P (x))
 | 
      
         | 483 |  |  |     return default_assemble_integer (x, size, is_aligned);
 | 
      
         | 484 |  |  |  
 | 
      
         | 485 |  |  |   if (op == NULL)
 | 
      
         | 486 |  |  |     return false;
 | 
      
         | 487 |  |  |   fputs (op, asm_out_file);
 | 
      
         | 488 |  |  |  
 | 
      
         | 489 |  |  |   rx_print_integer (asm_out_file, INTVAL (x));
 | 
      
         | 490 |  |  |   fputc ('\n', asm_out_file);
 | 
      
         | 491 |  |  |   return true;
 | 
      
         | 492 |  |  | }
 | 
      
         | 493 |  |  |  
 | 
      
         | 494 |  |  |  
 | 
      
         | 495 |  |  | /* Handles the insertion of a single operand into the assembler output.
 | 
      
         | 496 |  |  |    The %<letter> directives supported are:
 | 
      
         | 497 |  |  |  
 | 
      
         | 498 |  |  |      %A  Print an operand without a leading # character.
 | 
      
         | 499 |  |  |      %B  Print an integer comparison name.
 | 
      
         | 500 |  |  |      %C  Print a control register name.
 | 
      
         | 501 |  |  |      %F  Print a condition code flag name.
 | 
      
         | 502 |  |  |      %G  Register used for small-data-area addressing
 | 
      
         | 503 |  |  |      %H  Print high part of a DImode register, integer or address.
 | 
      
         | 504 |  |  |      %L  Print low part of a DImode register, integer or address.
 | 
      
         | 505 |  |  |      %N  Print the negation of the immediate value.
 | 
      
         | 506 |  |  |      %P  Register used for PID addressing
 | 
      
         | 507 |  |  |      %Q  If the operand is a MEM, then correctly generate
 | 
      
         | 508 |  |  |          register indirect or register relative addressing.
 | 
      
         | 509 |  |  |      %R  Like %Q but for zero-extending loads.  */
 | 
      
         | 510 |  |  |  
 | 
      
         | 511 |  |  | static void
 | 
      
         | 512 |  |  | rx_print_operand (FILE * file, rtx op, int letter)
 | 
      
         | 513 |  |  | {
 | 
      
         | 514 |  |  |   bool unsigned_load = false;
 | 
      
         | 515 |  |  |   bool print_hash = true;
 | 
      
         | 516 |  |  |  
 | 
      
         | 517 |  |  |   if (letter == 'A'
 | 
      
         | 518 |  |  |       && ((GET_CODE (op) == CONST
 | 
      
         | 519 |  |  |            && GET_CODE (XEXP (op, 0)) == UNSPEC)
 | 
      
         | 520 |  |  |           || GET_CODE (op) == UNSPEC))
 | 
      
         | 521 |  |  |     {
 | 
      
         | 522 |  |  |       print_hash = false;
 | 
      
         | 523 |  |  |       letter = 0;
 | 
      
         | 524 |  |  |     }
 | 
      
         | 525 |  |  |  
 | 
      
         | 526 |  |  |   switch (letter)
 | 
      
         | 527 |  |  |     {
 | 
      
         | 528 |  |  |     case 'A':
 | 
      
         | 529 |  |  |       /* Print an operand without a leading #.  */
 | 
      
         | 530 |  |  |       if (MEM_P (op))
 | 
      
         | 531 |  |  |         op = XEXP (op, 0);
 | 
      
         | 532 |  |  |  
 | 
      
         | 533 |  |  |       switch (GET_CODE (op))
 | 
      
         | 534 |  |  |         {
 | 
      
         | 535 |  |  |         case LABEL_REF:
 | 
      
         | 536 |  |  |         case SYMBOL_REF:
 | 
      
         | 537 |  |  |           output_addr_const (file, op);
 | 
      
         | 538 |  |  |           break;
 | 
      
         | 539 |  |  |         case CONST_INT:
 | 
      
         | 540 |  |  |           fprintf (file, "%ld", (long) INTVAL (op));
 | 
      
         | 541 |  |  |           break;
 | 
      
         | 542 |  |  |         default:
 | 
      
         | 543 |  |  |           rx_print_operand (file, op, 0);
 | 
      
         | 544 |  |  |           break;
 | 
      
         | 545 |  |  |         }
 | 
      
         | 546 |  |  |       break;
 | 
      
         | 547 |  |  |  
 | 
      
         | 548 |  |  |     case 'B':
 | 
      
         | 549 |  |  |       {
 | 
      
         | 550 |  |  |         enum rtx_code code = GET_CODE (op);
 | 
      
         | 551 |  |  |         enum machine_mode mode = GET_MODE (XEXP (op, 0));
 | 
      
         | 552 |  |  |         const char *ret;
 | 
      
         | 553 |  |  |  
 | 
      
         | 554 |  |  |         if (mode == CC_Fmode)
 | 
      
         | 555 |  |  |           {
 | 
      
         | 556 |  |  |             /* C flag is undefined, and O flag carries unordered.  None of the
 | 
      
         | 557 |  |  |                branch combinations that include O use it helpfully.  */
 | 
      
         | 558 |  |  |             switch (code)
 | 
      
         | 559 |  |  |               {
 | 
      
         | 560 |  |  |               case ORDERED:
 | 
      
         | 561 |  |  |                 ret = "no";
 | 
      
         | 562 |  |  |                 break;
 | 
      
         | 563 |  |  |               case UNORDERED:
 | 
      
         | 564 |  |  |                 ret = "o";
 | 
      
         | 565 |  |  |                 break;
 | 
      
         | 566 |  |  |               case LT:
 | 
      
         | 567 |  |  |                 ret = "n";
 | 
      
         | 568 |  |  |                 break;
 | 
      
         | 569 |  |  |               case GE:
 | 
      
         | 570 |  |  |                 ret = "pz";
 | 
      
         | 571 |  |  |                 break;
 | 
      
         | 572 |  |  |               case EQ:
 | 
      
         | 573 |  |  |                 ret = "eq";
 | 
      
         | 574 |  |  |                 break;
 | 
      
         | 575 |  |  |               case NE:
 | 
      
         | 576 |  |  |                 ret = "ne";
 | 
      
         | 577 |  |  |                 break;
 | 
      
         | 578 |  |  |               default:
 | 
      
         | 579 |  |  |                 gcc_unreachable ();
 | 
      
         | 580 |  |  |               }
 | 
      
         | 581 |  |  |           }
 | 
      
         | 582 |  |  |         else
 | 
      
         | 583 |  |  |           {
 | 
      
         | 584 |  |  |             unsigned int flags = flags_from_mode (mode);
 | 
      
         | 585 |  |  |  
 | 
      
         | 586 |  |  |             switch (code)
 | 
      
         | 587 |  |  |               {
 | 
      
         | 588 |  |  |               case LT:
 | 
      
         | 589 |  |  |                 ret = (flags & CC_FLAG_O ? "lt" : "n");
 | 
      
         | 590 |  |  |                 break;
 | 
      
         | 591 |  |  |               case GE:
 | 
      
         | 592 |  |  |                 ret = (flags & CC_FLAG_O ? "ge" : "pz");
 | 
      
         | 593 |  |  |                 break;
 | 
      
         | 594 |  |  |               case GT:
 | 
      
         | 595 |  |  |                 ret = "gt";
 | 
      
         | 596 |  |  |                 break;
 | 
      
         | 597 |  |  |               case LE:
 | 
      
         | 598 |  |  |                 ret = "le";
 | 
      
         | 599 |  |  |                 break;
 | 
      
         | 600 |  |  |               case GEU:
 | 
      
         | 601 |  |  |                 ret = "geu";
 | 
      
         | 602 |  |  |                 break;
 | 
      
         | 603 |  |  |               case LTU:
 | 
      
         | 604 |  |  |                 ret = "ltu";
 | 
      
         | 605 |  |  |                 break;
 | 
      
         | 606 |  |  |               case GTU:
 | 
      
         | 607 |  |  |                 ret = "gtu";
 | 
      
         | 608 |  |  |                 break;
 | 
      
         | 609 |  |  |               case LEU:
 | 
      
         | 610 |  |  |                 ret = "leu";
 | 
      
         | 611 |  |  |                 break;
 | 
      
         | 612 |  |  |               case EQ:
 | 
      
         | 613 |  |  |                 ret = "eq";
 | 
      
         | 614 |  |  |                 break;
 | 
      
         | 615 |  |  |               case NE:
 | 
      
         | 616 |  |  |                 ret = "ne";
 | 
      
         | 617 |  |  |                 break;
 | 
      
         | 618 |  |  |               default:
 | 
      
         | 619 |  |  |                 gcc_unreachable ();
 | 
      
         | 620 |  |  |               }
 | 
      
         | 621 |  |  |             gcc_checking_assert ((flags_from_code (code) & ~flags) == 0);
 | 
      
         | 622 |  |  |           }
 | 
      
         | 623 |  |  |         fputs (ret, file);
 | 
      
         | 624 |  |  |         break;
 | 
      
         | 625 |  |  |       }
 | 
      
         | 626 |  |  |  
 | 
      
         | 627 |  |  |     case 'C':
 | 
      
         | 628 |  |  |       gcc_assert (CONST_INT_P (op));
 | 
      
         | 629 |  |  |       switch (INTVAL (op))
 | 
      
         | 630 |  |  |         {
 | 
      
         | 631 |  |  |         case 0:   fprintf (file, "psw"); break;
 | 
      
         | 632 |  |  |         case 2:   fprintf (file, "usp"); break;
 | 
      
         | 633 |  |  |         case 3:   fprintf (file, "fpsw"); break;
 | 
      
         | 634 |  |  |         case 4:   fprintf (file, "cpen"); break;
 | 
      
         | 635 |  |  |         case 8:   fprintf (file, "bpsw"); break;
 | 
      
         | 636 |  |  |         case 9:   fprintf (file, "bpc"); break;
 | 
      
         | 637 |  |  |         case 0xa: fprintf (file, "isp"); break;
 | 
      
         | 638 |  |  |         case 0xb: fprintf (file, "fintv"); break;
 | 
      
         | 639 |  |  |         case 0xc: fprintf (file, "intb"); break;
 | 
      
         | 640 |  |  |         default:
 | 
      
         | 641 |  |  |           warning (0, "unrecognized control register number: %d - using 'psw'",
 | 
      
         | 642 |  |  |                    (int) INTVAL (op));
 | 
      
         | 643 |  |  |           fprintf (file, "psw");
 | 
      
         | 644 |  |  |           break;
 | 
      
         | 645 |  |  |         }
 | 
      
         | 646 |  |  |       break;
 | 
      
         | 647 |  |  |  
 | 
      
         | 648 |  |  |     case 'F':
 | 
      
         | 649 |  |  |       gcc_assert (CONST_INT_P (op));
 | 
      
         | 650 |  |  |       switch (INTVAL (op))
 | 
      
         | 651 |  |  |         {
 | 
      
         | 652 |  |  |         case 0: case 'c': case 'C': fprintf (file, "C"); break;
 | 
      
         | 653 |  |  |         case 1: case 'z': case 'Z': fprintf (file, "Z"); break;
 | 
      
         | 654 |  |  |         case 2: case 's': case 'S': fprintf (file, "S"); break;
 | 
      
         | 655 |  |  |         case 3: case 'o': case 'O': fprintf (file, "O"); break;
 | 
      
         | 656 |  |  |         case 8: case 'i': case 'I': fprintf (file, "I"); break;
 | 
      
         | 657 |  |  |         case 9: case 'u': case 'U': fprintf (file, "U"); break;
 | 
      
         | 658 |  |  |         default:
 | 
      
         | 659 |  |  |           gcc_unreachable ();
 | 
      
         | 660 |  |  |         }
 | 
      
         | 661 |  |  |       break;
 | 
      
         | 662 |  |  |  
 | 
      
         | 663 |  |  |     case 'G':
 | 
      
         | 664 |  |  |       fprintf (file, "%s", reg_names [rx_gp_base_regnum ()]);
 | 
      
         | 665 |  |  |       break;
 | 
      
         | 666 |  |  |  
 | 
      
         | 667 |  |  |     case 'H':
 | 
      
         | 668 |  |  |       switch (GET_CODE (op))
 | 
      
         | 669 |  |  |         {
 | 
      
         | 670 |  |  |         case REG:
 | 
      
         | 671 |  |  |           fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]);
 | 
      
         | 672 |  |  |           break;
 | 
      
         | 673 |  |  |         case CONST_INT:
 | 
      
         | 674 |  |  |           {
 | 
      
         | 675 |  |  |             HOST_WIDE_INT v = INTVAL (op);
 | 
      
         | 676 |  |  |  
 | 
      
         | 677 |  |  |             fprintf (file, "#");
 | 
      
         | 678 |  |  |             /* Trickery to avoid problems with shifting 32 bits at a time.  */
 | 
      
         | 679 |  |  |             v = v >> 16;
 | 
      
         | 680 |  |  |             v = v >> 16;
 | 
      
         | 681 |  |  |             rx_print_integer (file, v);
 | 
      
         | 682 |  |  |             break;
 | 
      
         | 683 |  |  |           }
 | 
      
         | 684 |  |  |         case CONST_DOUBLE:
 | 
      
         | 685 |  |  |           fprintf (file, "#");
 | 
      
         | 686 |  |  |           rx_print_integer (file, CONST_DOUBLE_HIGH (op));
 | 
      
         | 687 |  |  |           break;
 | 
      
         | 688 |  |  |         case MEM:
 | 
      
         | 689 |  |  |           if (! WORDS_BIG_ENDIAN)
 | 
      
         | 690 |  |  |             op = adjust_address (op, SImode, 4);
 | 
      
         | 691 |  |  |           output_address (XEXP (op, 0));
 | 
      
         | 692 |  |  |           break;
 | 
      
         | 693 |  |  |         default:
 | 
      
         | 694 |  |  |           gcc_unreachable ();
 | 
      
         | 695 |  |  |         }
 | 
      
         | 696 |  |  |       break;
 | 
      
         | 697 |  |  |  
 | 
      
         | 698 |  |  |     case 'L':
 | 
      
         | 699 |  |  |       switch (GET_CODE (op))
 | 
      
         | 700 |  |  |         {
 | 
      
         | 701 |  |  |         case REG:
 | 
      
         | 702 |  |  |           fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]);
 | 
      
         | 703 |  |  |           break;
 | 
      
         | 704 |  |  |         case CONST_INT:
 | 
      
         | 705 |  |  |           fprintf (file, "#");
 | 
      
         | 706 |  |  |           rx_print_integer (file, INTVAL (op) & 0xffffffff);
 | 
      
         | 707 |  |  |           break;
 | 
      
         | 708 |  |  |         case CONST_DOUBLE:
 | 
      
         | 709 |  |  |           fprintf (file, "#");
 | 
      
         | 710 |  |  |           rx_print_integer (file, CONST_DOUBLE_LOW (op));
 | 
      
         | 711 |  |  |           break;
 | 
      
         | 712 |  |  |         case MEM:
 | 
      
         | 713 |  |  |           if (WORDS_BIG_ENDIAN)
 | 
      
         | 714 |  |  |             op = adjust_address (op, SImode, 4);
 | 
      
         | 715 |  |  |           output_address (XEXP (op, 0));
 | 
      
         | 716 |  |  |           break;
 | 
      
         | 717 |  |  |         default:
 | 
      
         | 718 |  |  |           gcc_unreachable ();
 | 
      
         | 719 |  |  |         }
 | 
      
         | 720 |  |  |       break;
 | 
      
         | 721 |  |  |  
 | 
      
         | 722 |  |  |     case 'N':
 | 
      
         | 723 |  |  |       gcc_assert (CONST_INT_P (op));
 | 
      
         | 724 |  |  |       fprintf (file, "#");
 | 
      
         | 725 |  |  |       rx_print_integer (file, - INTVAL (op));
 | 
      
         | 726 |  |  |       break;
 | 
      
         | 727 |  |  |  
 | 
      
         | 728 |  |  |     case 'P':
 | 
      
         | 729 |  |  |       fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
 | 
      
         | 730 |  |  |       break;
 | 
      
         | 731 |  |  |  
 | 
      
         | 732 |  |  |     case 'R':
 | 
      
         | 733 |  |  |       gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
 | 
      
         | 734 |  |  |       unsigned_load = true;
 | 
      
         | 735 |  |  |       /* Fall through.  */
 | 
      
         | 736 |  |  |     case 'Q':
 | 
      
         | 737 |  |  |       if (MEM_P (op))
 | 
      
         | 738 |  |  |         {
 | 
      
         | 739 |  |  |           HOST_WIDE_INT offset;
 | 
      
         | 740 |  |  |           rtx mem = op;
 | 
      
         | 741 |  |  |  
 | 
      
         | 742 |  |  |           op = XEXP (op, 0);
 | 
      
         | 743 |  |  |  
 | 
      
         | 744 |  |  |           if (REG_P (op))
 | 
      
         | 745 |  |  |             offset = 0;
 | 
      
         | 746 |  |  |           else if (GET_CODE (op) == PLUS)
 | 
      
         | 747 |  |  |             {
 | 
      
         | 748 |  |  |               rtx displacement;
 | 
      
         | 749 |  |  |  
 | 
      
         | 750 |  |  |               if (REG_P (XEXP (op, 0)))
 | 
      
         | 751 |  |  |                 {
 | 
      
         | 752 |  |  |                   displacement = XEXP (op, 1);
 | 
      
         | 753 |  |  |                   op = XEXP (op, 0);
 | 
      
         | 754 |  |  |                 }
 | 
      
         | 755 |  |  |               else
 | 
      
         | 756 |  |  |                 {
 | 
      
         | 757 |  |  |                   displacement = XEXP (op, 0);
 | 
      
         | 758 |  |  |                   op = XEXP (op, 1);
 | 
      
         | 759 |  |  |                   gcc_assert (REG_P (op));
 | 
      
         | 760 |  |  |                 }
 | 
      
         | 761 |  |  |  
 | 
      
         | 762 |  |  |               gcc_assert (CONST_INT_P (displacement));
 | 
      
         | 763 |  |  |               offset = INTVAL (displacement);
 | 
      
         | 764 |  |  |               gcc_assert (offset >= 0);
 | 
      
         | 765 |  |  |  
 | 
      
         | 766 |  |  |               fprintf (file, "%ld", offset);
 | 
      
         | 767 |  |  |             }
 | 
      
         | 768 |  |  |           else
 | 
      
         | 769 |  |  |             gcc_unreachable ();
 | 
      
         | 770 |  |  |  
 | 
      
         | 771 |  |  |           fprintf (file, "[");
 | 
      
         | 772 |  |  |           rx_print_operand (file, op, 0);
 | 
      
         | 773 |  |  |           fprintf (file, "].");
 | 
      
         | 774 |  |  |  
 | 
      
         | 775 |  |  |           switch (GET_MODE_SIZE (GET_MODE (mem)))
 | 
      
         | 776 |  |  |             {
 | 
      
         | 777 |  |  |             case 1:
 | 
      
         | 778 |  |  |               gcc_assert (offset <= 65535 * 1);
 | 
      
         | 779 |  |  |               fprintf (file, unsigned_load ? "UB" : "B");
 | 
      
         | 780 |  |  |               break;
 | 
      
         | 781 |  |  |             case 2:
 | 
      
         | 782 |  |  |               gcc_assert (offset % 2 == 0);
 | 
      
         | 783 |  |  |               gcc_assert (offset <= 65535 * 2);
 | 
      
         | 784 |  |  |               fprintf (file, unsigned_load ? "UW" : "W");
 | 
      
         | 785 |  |  |               break;
 | 
      
         | 786 |  |  |             case 4:
 | 
      
         | 787 |  |  |               gcc_assert (offset % 4 == 0);
 | 
      
         | 788 |  |  |               gcc_assert (offset <= 65535 * 4);
 | 
      
         | 789 |  |  |               fprintf (file, "L");
 | 
      
         | 790 |  |  |               break;
 | 
      
         | 791 |  |  |             default:
 | 
      
         | 792 |  |  |               gcc_unreachable ();
 | 
      
         | 793 |  |  |             }
 | 
      
         | 794 |  |  |           break;
 | 
      
         | 795 |  |  |         }
 | 
      
         | 796 |  |  |  
 | 
      
         | 797 |  |  |       /* Fall through.  */
 | 
      
         | 798 |  |  |  
 | 
      
         | 799 |  |  |     default:
 | 
      
         | 800 |  |  |       if (GET_CODE (op) == CONST
 | 
      
         | 801 |  |  |           && GET_CODE (XEXP (op, 0)) == UNSPEC)
 | 
      
         | 802 |  |  |         op = XEXP (op, 0);
 | 
      
         | 803 |  |  |       else if (GET_CODE (op) == CONST
 | 
      
         | 804 |  |  |                && GET_CODE (XEXP (op, 0)) == PLUS
 | 
      
         | 805 |  |  |                && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
 | 
      
         | 806 |  |  |                && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
 | 
      
         | 807 |  |  |         {
 | 
      
         | 808 |  |  |           if (print_hash)
 | 
      
         | 809 |  |  |             fprintf (file, "#");
 | 
      
         | 810 |  |  |           fprintf (file, "(");
 | 
      
         | 811 |  |  |           rx_print_operand (file, XEXP (XEXP (op, 0), 0), 'A');
 | 
      
         | 812 |  |  |           fprintf (file, " + ");
 | 
      
         | 813 |  |  |           output_addr_const (file, XEXP (XEXP (op, 0), 1));
 | 
      
         | 814 |  |  |           fprintf (file, ")");
 | 
      
         | 815 |  |  |           return;
 | 
      
         | 816 |  |  |         }
 | 
      
         | 817 |  |  |  
 | 
      
         | 818 |  |  |       switch (GET_CODE (op))
 | 
      
         | 819 |  |  |         {
 | 
      
         | 820 |  |  |         case MULT:
 | 
      
         | 821 |  |  |           /* Should be the scaled part of an
 | 
      
         | 822 |  |  |              indexed register indirect address.  */
 | 
      
         | 823 |  |  |           {
 | 
      
         | 824 |  |  |             rtx base = XEXP (op, 0);
 | 
      
         | 825 |  |  |             rtx index = XEXP (op, 1);
 | 
      
         | 826 |  |  |  
 | 
      
         | 827 |  |  |             /* Check for a swaped index register and scaling factor.
 | 
      
         | 828 |  |  |                Not sure if this can happen, but be prepared to handle it.  */
 | 
      
         | 829 |  |  |             if (CONST_INT_P (base) && REG_P (index))
 | 
      
         | 830 |  |  |               {
 | 
      
         | 831 |  |  |                 rtx tmp = base;
 | 
      
         | 832 |  |  |                 base = index;
 | 
      
         | 833 |  |  |                 index = tmp;
 | 
      
         | 834 |  |  |               }
 | 
      
         | 835 |  |  |  
 | 
      
         | 836 |  |  |             gcc_assert (REG_P (base));
 | 
      
         | 837 |  |  |             gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
 | 
      
         | 838 |  |  |             gcc_assert (CONST_INT_P (index));
 | 
      
         | 839 |  |  |             /* Do not try to verify the value of the scalar as it is based
 | 
      
         | 840 |  |  |                on the mode of the MEM not the mode of the MULT.  (Which
 | 
      
         | 841 |  |  |                will always be SImode).  */
 | 
      
         | 842 |  |  |             fprintf (file, "%s", reg_names [REGNO (base)]);
 | 
      
         | 843 |  |  |             break;
 | 
      
         | 844 |  |  |           }
 | 
      
         | 845 |  |  |  
 | 
      
         | 846 |  |  |         case MEM:
 | 
      
         | 847 |  |  |           output_address (XEXP (op, 0));
 | 
      
         | 848 |  |  |           break;
 | 
      
         | 849 |  |  |  
 | 
      
         | 850 |  |  |         case PLUS:
 | 
      
         | 851 |  |  |           output_address (op);
 | 
      
         | 852 |  |  |           break;
 | 
      
         | 853 |  |  |  
 | 
      
         | 854 |  |  |         case REG:
 | 
      
         | 855 |  |  |           gcc_assert (REGNO (op) < FIRST_PSEUDO_REGISTER);
 | 
      
         | 856 |  |  |           fprintf (file, "%s", reg_names [REGNO (op)]);
 | 
      
         | 857 |  |  |           break;
 | 
      
         | 858 |  |  |  
 | 
      
         | 859 |  |  |         case SUBREG:
 | 
      
         | 860 |  |  |           gcc_assert (subreg_regno (op) < FIRST_PSEUDO_REGISTER);
 | 
      
         | 861 |  |  |           fprintf (file, "%s", reg_names [subreg_regno (op)]);
 | 
      
         | 862 |  |  |           break;
 | 
      
         | 863 |  |  |  
 | 
      
         | 864 |  |  |           /* This will only be single precision....  */
 | 
      
         | 865 |  |  |         case CONST_DOUBLE:
 | 
      
         | 866 |  |  |           {
 | 
      
         | 867 |  |  |             unsigned long val;
 | 
      
         | 868 |  |  |             REAL_VALUE_TYPE rv;
 | 
      
         | 869 |  |  |  
 | 
      
         | 870 |  |  |             REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
 | 
      
         | 871 |  |  |             REAL_VALUE_TO_TARGET_SINGLE (rv, val);
 | 
      
         | 872 |  |  |             if (print_hash)
 | 
      
         | 873 |  |  |               fprintf (file, "#");
 | 
      
         | 874 |  |  |             fprintf (file, TARGET_AS100_SYNTAX ? "0%lxH" : "0x%lx", val);
 | 
      
         | 875 |  |  |             break;
 | 
      
         | 876 |  |  |           }
 | 
      
         | 877 |  |  |  
 | 
      
         | 878 |  |  |         case CONST_INT:
 | 
      
         | 879 |  |  |           if (print_hash)
 | 
      
         | 880 |  |  |             fprintf (file, "#");
 | 
      
         | 881 |  |  |           rx_print_integer (file, INTVAL (op));
 | 
      
         | 882 |  |  |           break;
 | 
      
         | 883 |  |  |  
 | 
      
         | 884 |  |  |         case UNSPEC:
 | 
      
         | 885 |  |  |           switch (XINT (op, 1))
 | 
      
         | 886 |  |  |             {
 | 
      
         | 887 |  |  |             case UNSPEC_PID_ADDR:
 | 
      
         | 888 |  |  |               {
 | 
      
         | 889 |  |  |                 rtx sym, add;
 | 
      
         | 890 |  |  |  
 | 
      
         | 891 |  |  |                 if (print_hash)
 | 
      
         | 892 |  |  |                   fprintf (file, "#");
 | 
      
         | 893 |  |  |                 sym = XVECEXP (op, 0, 0);
 | 
      
         | 894 |  |  |                 add = NULL_RTX;
 | 
      
         | 895 |  |  |                 fprintf (file, "(");
 | 
      
         | 896 |  |  |                 if (GET_CODE (sym) == PLUS)
 | 
      
         | 897 |  |  |                   {
 | 
      
         | 898 |  |  |                     add = XEXP (sym, 1);
 | 
      
         | 899 |  |  |                     sym = XEXP (sym, 0);
 | 
      
         | 900 |  |  |                   }
 | 
      
         | 901 |  |  |                 output_addr_const (file, sym);
 | 
      
         | 902 |  |  |                 if (add != NULL_RTX)
 | 
      
         | 903 |  |  |                   {
 | 
      
         | 904 |  |  |                     fprintf (file, "+");
 | 
      
         | 905 |  |  |                     output_addr_const (file, add);
 | 
      
         | 906 |  |  |                   }
 | 
      
         | 907 |  |  |                 fprintf (file, "-__pid_base");
 | 
      
         | 908 |  |  |                 fprintf (file, ")");
 | 
      
         | 909 |  |  |                 return;
 | 
      
         | 910 |  |  |               }
 | 
      
         | 911 |  |  |             }
 | 
      
         | 912 |  |  |           /* Fall through */
 | 
      
         | 913 |  |  |  
 | 
      
         | 914 |  |  |         case CONST:
 | 
      
         | 915 |  |  |         case SYMBOL_REF:
 | 
      
         | 916 |  |  |         case LABEL_REF:
 | 
      
         | 917 |  |  |         case CODE_LABEL:
 | 
      
         | 918 |  |  |           rx_print_operand_address (file, op);
 | 
      
         | 919 |  |  |           break;
 | 
      
         | 920 |  |  |  
 | 
      
         | 921 |  |  |         default:
 | 
      
         | 922 |  |  |           gcc_unreachable ();
 | 
      
         | 923 |  |  |         }
 | 
      
         | 924 |  |  |       break;
 | 
      
         | 925 |  |  |     }
 | 
      
         | 926 |  |  | }
 | 
      
         | 927 |  |  |  
 | 
      
         | 928 |  |  | /* Maybe convert an operand into its PID format.  */
 | 
      
         | 929 |  |  |  
 | 
      
         | 930 |  |  | rtx
 | 
      
         | 931 |  |  | rx_maybe_pidify_operand (rtx op, int copy_to_reg)
 | 
      
         | 932 |  |  | {
 | 
      
         | 933 |  |  |   if (rx_pid_data_operand (op) == PID_UNENCODED)
 | 
      
         | 934 |  |  |     {
 | 
      
         | 935 |  |  |       if (GET_CODE (op) == MEM)
 | 
      
         | 936 |  |  |         {
 | 
      
         | 937 |  |  |           rtx a = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), XEXP (op, 0));
 | 
      
         | 938 |  |  |           op = replace_equiv_address (op, a);
 | 
      
         | 939 |  |  |         }
 | 
      
         | 940 |  |  |       else
 | 
      
         | 941 |  |  |         {
 | 
      
         | 942 |  |  |           op = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), op);
 | 
      
         | 943 |  |  |         }
 | 
      
         | 944 |  |  |  
 | 
      
         | 945 |  |  |       if (copy_to_reg)
 | 
      
         | 946 |  |  |         op = copy_to_mode_reg (GET_MODE (op), op);
 | 
      
         | 947 |  |  |     }
 | 
      
         | 948 |  |  |   return op;
 | 
      
         | 949 |  |  | }
 | 
      
         | 950 |  |  |  
 | 
      
         | 951 |  |  | /* Returns an assembler template for a move instruction.  */
 | 
      
         | 952 |  |  |  
 | 
      
         | 953 |  |  | char *
 | 
      
         | 954 |  |  | rx_gen_move_template (rtx * operands, bool is_movu)
 | 
      
         | 955 |  |  | {
 | 
      
         | 956 |  |  |   static char  out_template [64];
 | 
      
         | 957 |  |  |   const char * extension = TARGET_AS100_SYNTAX ? ".L" : "";
 | 
      
         | 958 |  |  |   const char * src_template;
 | 
      
         | 959 |  |  |   const char * dst_template;
 | 
      
         | 960 |  |  |   rtx          dest = operands[0];
 | 
      
         | 961 |  |  |   rtx          src  = operands[1];
 | 
      
         | 962 |  |  |  
 | 
      
         | 963 |  |  |   /* Decide which extension, if any, should be given to the move instruction.  */
 | 
      
         | 964 |  |  |   switch (CONST_INT_P (src) ? GET_MODE (dest) : GET_MODE (src))
 | 
      
         | 965 |  |  |     {
 | 
      
         | 966 |  |  |     case QImode:
 | 
      
         | 967 |  |  |       /* The .B extension is not valid when
 | 
      
         | 968 |  |  |          loading an immediate into a register.  */
 | 
      
         | 969 |  |  |       if (! REG_P (dest) || ! CONST_INT_P (src))
 | 
      
         | 970 |  |  |         extension = ".B";
 | 
      
         | 971 |  |  |       break;
 | 
      
         | 972 |  |  |     case HImode:
 | 
      
         | 973 |  |  |       if (! REG_P (dest) || ! CONST_INT_P (src))
 | 
      
         | 974 |  |  |         /* The .W extension is not valid when
 | 
      
         | 975 |  |  |            loading an immediate into a register.  */
 | 
      
         | 976 |  |  |         extension = ".W";
 | 
      
         | 977 |  |  |       break;
 | 
      
         | 978 |  |  |     case SFmode:
 | 
      
         | 979 |  |  |     case SImode:
 | 
      
         | 980 |  |  |       extension = ".L";
 | 
      
         | 981 |  |  |       break;
 | 
      
         | 982 |  |  |     case VOIDmode:
 | 
      
         | 983 |  |  |       /* This mode is used by constants.  */
 | 
      
         | 984 |  |  |       break;
 | 
      
         | 985 |  |  |     default:
 | 
      
         | 986 |  |  |       debug_rtx (src);
 | 
      
         | 987 |  |  |       gcc_unreachable ();
 | 
      
         | 988 |  |  |     }
 | 
      
         | 989 |  |  |  
 | 
      
         | 990 |  |  |   if (MEM_P (src) && rx_pid_data_operand (XEXP (src, 0)) == PID_UNENCODED)
 | 
      
         | 991 |  |  |     src_template = "(%A1-__pid_base)[%P1]";
 | 
      
         | 992 |  |  |   else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
 | 
      
         | 993 |  |  |     src_template = "%%gp(%A1)[%G1]";
 | 
      
         | 994 |  |  |   else
 | 
      
         | 995 |  |  |     src_template = "%1";
 | 
      
         | 996 |  |  |  
 | 
      
         | 997 |  |  |   if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
 | 
      
         | 998 |  |  |     dst_template = "%%gp(%A0)[%G0]";
 | 
      
         | 999 |  |  |   else
 | 
      
         | 1000 |  |  |     dst_template = "%0";
 | 
      
         | 1001 |  |  |  
 | 
      
         | 1002 |  |  |   sprintf (out_template, "%s%s\t%s, %s", is_movu ? "movu" : "mov",
 | 
      
         | 1003 |  |  |            extension, src_template, dst_template);
 | 
      
         | 1004 |  |  |   return out_template;
 | 
      
         | 1005 |  |  | }
 | 
      
         | 1006 |  |  |  
 | 
      
         | 1007 |  |  | /* Return VALUE rounded up to the next ALIGNMENT boundary.  */
 | 
      
         | 1008 |  |  |  
 | 
      
         | 1009 |  |  | static inline unsigned int
 | 
      
         | 1010 |  |  | rx_round_up (unsigned int value, unsigned int alignment)
 | 
      
         | 1011 |  |  | {
 | 
      
         | 1012 |  |  |   alignment -= 1;
 | 
      
         | 1013 |  |  |   return (value + alignment) & (~ alignment);
 | 
      
         | 1014 |  |  | }
 | 
      
         | 1015 |  |  |  
 | 
      
         | 1016 |  |  | /* Return the number of bytes in the argument registers
 | 
      
         | 1017 |  |  |    occupied by an argument of type TYPE and mode MODE.  */
 | 
      
         | 1018 |  |  |  
 | 
      
         | 1019 |  |  | static unsigned int
 | 
      
         | 1020 |  |  | rx_function_arg_size (enum machine_mode mode, const_tree type)
 | 
      
         | 1021 |  |  | {
 | 
      
         | 1022 |  |  |   unsigned int num_bytes;
 | 
      
         | 1023 |  |  |  
 | 
      
         | 1024 |  |  |   num_bytes = (mode == BLKmode)
 | 
      
         | 1025 |  |  |     ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
 | 
      
         | 1026 |  |  |   return rx_round_up (num_bytes, UNITS_PER_WORD);
 | 
      
         | 1027 |  |  | }
 | 
      
         | 1028 |  |  |  
 | 
      
         | 1029 |  |  | #define NUM_ARG_REGS            4
 | 
      
         | 1030 |  |  | #define MAX_NUM_ARG_BYTES       (NUM_ARG_REGS * UNITS_PER_WORD)
 | 
      
         | 1031 |  |  |  
 | 
      
         | 1032 |  |  | /* Return an RTL expression describing the register holding a function
 | 
      
         | 1033 |  |  |    parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
 | 
      
         | 1034 |  |  |    be passed on the stack.  CUM describes the previous parameters to the
 | 
      
         | 1035 |  |  |    function and NAMED is false if the parameter is part of a variable
 | 
      
         | 1036 |  |  |    parameter list, or the last named parameter before the start of a
 | 
      
         | 1037 |  |  |    variable parameter list.  */
 | 
      
         | 1038 |  |  |  
 | 
      
         | 1039 |  |  | static rtx
 | 
      
         | 1040 |  |  | rx_function_arg (cumulative_args_t cum, enum machine_mode mode,
 | 
      
         | 1041 |  |  |                  const_tree type, bool named)
 | 
      
         | 1042 |  |  | {
 | 
      
         | 1043 |  |  |   unsigned int next_reg;
 | 
      
         | 1044 |  |  |   unsigned int bytes_so_far = *get_cumulative_args (cum);
 | 
      
         | 1045 |  |  |   unsigned int size;
 | 
      
         | 1046 |  |  |   unsigned int rounded_size;
 | 
      
         | 1047 |  |  |  
 | 
      
         | 1048 |  |  |   /* An exploded version of rx_function_arg_size.  */
 | 
      
         | 1049 |  |  |   size = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
 | 
      
         | 1050 |  |  |   /* If the size is not known it cannot be passed in registers.  */
 | 
      
         | 1051 |  |  |   if (size < 1)
 | 
      
         | 1052 |  |  |     return NULL_RTX;
 | 
      
         | 1053 |  |  |  
 | 
      
         | 1054 |  |  |   rounded_size = rx_round_up (size, UNITS_PER_WORD);
 | 
      
         | 1055 |  |  |  
 | 
      
         | 1056 |  |  |   /* Don't pass this arg via registers if there
 | 
      
         | 1057 |  |  |      are insufficient registers to hold all of it.  */
 | 
      
         | 1058 |  |  |   if (rounded_size + bytes_so_far > MAX_NUM_ARG_BYTES)
 | 
      
         | 1059 |  |  |     return NULL_RTX;
 | 
      
         | 1060 |  |  |  
 | 
      
         | 1061 |  |  |   /* Unnamed arguments and the last named argument in a
 | 
      
         | 1062 |  |  |      variadic function are always passed on the stack.  */
 | 
      
         | 1063 |  |  |   if (!named)
 | 
      
         | 1064 |  |  |     return NULL_RTX;
 | 
      
         | 1065 |  |  |  
 | 
      
         | 1066 |  |  |   /* Structures must occupy an exact number of registers,
 | 
      
         | 1067 |  |  |      otherwise they are passed on the stack.  */
 | 
      
         | 1068 |  |  |   if ((type == NULL || AGGREGATE_TYPE_P (type))
 | 
      
         | 1069 |  |  |       && (size % UNITS_PER_WORD) != 0)
 | 
      
         | 1070 |  |  |     return NULL_RTX;
 | 
      
         | 1071 |  |  |  
 | 
      
         | 1072 |  |  |   next_reg = (bytes_so_far / UNITS_PER_WORD) + 1;
 | 
      
         | 1073 |  |  |  
 | 
      
         | 1074 |  |  |   return gen_rtx_REG (mode, next_reg);
 | 
      
         | 1075 |  |  | }
 | 
      
         | 1076 |  |  |  
 | 
      
         | 1077 |  |  | static void
 | 
      
         | 1078 |  |  | rx_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
 | 
      
         | 1079 |  |  |                          const_tree type, bool named ATTRIBUTE_UNUSED)
 | 
      
         | 1080 |  |  | {
 | 
      
         | 1081 |  |  |   *get_cumulative_args (cum) += rx_function_arg_size (mode, type);
 | 
      
         | 1082 |  |  | }
 | 
      
         | 1083 |  |  |  
 | 
      
         | 1084 |  |  | static unsigned int
 | 
      
         | 1085 |  |  | rx_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
 | 
      
         | 1086 |  |  |                           const_tree type ATTRIBUTE_UNUSED)
 | 
      
         | 1087 |  |  | {
 | 
      
         | 1088 |  |  |   return 32;
 | 
      
         | 1089 |  |  | }
 | 
      
         | 1090 |  |  |  
 | 
      
         | 1091 |  |  | /* Return an RTL describing where a function return value of type RET_TYPE
 | 
      
         | 1092 |  |  |    is held.  */
 | 
      
         | 1093 |  |  |  
 | 
      
         | 1094 |  |  | static rtx
 | 
      
         | 1095 |  |  | rx_function_value (const_tree ret_type,
 | 
      
         | 1096 |  |  |                    const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
 | 
      
         | 1097 |  |  |                    bool       outgoing ATTRIBUTE_UNUSED)
 | 
      
         | 1098 |  |  | {
 | 
      
         | 1099 |  |  |   enum machine_mode mode = TYPE_MODE (ret_type);
 | 
      
         | 1100 |  |  |  
 | 
      
         | 1101 |  |  |   /* RX ABI specifies that small integer types are
 | 
      
         | 1102 |  |  |      promoted to int when returned by a function.  */
 | 
      
         | 1103 |  |  |   if (GET_MODE_SIZE (mode) > 0
 | 
      
         | 1104 |  |  |       && GET_MODE_SIZE (mode) < 4
 | 
      
         | 1105 |  |  |       && ! COMPLEX_MODE_P (mode)
 | 
      
         | 1106 |  |  |       )
 | 
      
         | 1107 |  |  |     return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM);
 | 
      
         | 1108 |  |  |  
 | 
      
         | 1109 |  |  |   return gen_rtx_REG (mode, FUNC_RETURN_REGNUM);
 | 
      
         | 1110 |  |  | }
 | 
      
         | 1111 |  |  |  
 | 
      
         | 1112 |  |  | /* TARGET_PROMOTE_FUNCTION_MODE must behave in the same way with
 | 
      
         | 1113 |  |  |    regard to function returns as does TARGET_FUNCTION_VALUE.  */
 | 
      
         | 1114 |  |  |  
 | 
      
         | 1115 |  |  | static enum machine_mode
 | 
      
         | 1116 |  |  | rx_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
 | 
      
         | 1117 |  |  |                           enum machine_mode mode,
 | 
      
         | 1118 |  |  |                           int * punsignedp ATTRIBUTE_UNUSED,
 | 
      
         | 1119 |  |  |                           const_tree funtype ATTRIBUTE_UNUSED,
 | 
      
         | 1120 |  |  |                           int for_return)
 | 
      
         | 1121 |  |  | {
 | 
      
         | 1122 |  |  |   if (for_return != 1
 | 
      
         | 1123 |  |  |       || GET_MODE_SIZE (mode) >= 4
 | 
      
         | 1124 |  |  |       || COMPLEX_MODE_P (mode)
 | 
      
         | 1125 |  |  |       || GET_MODE_SIZE (mode) < 1)
 | 
      
         | 1126 |  |  |     return mode;
 | 
      
         | 1127 |  |  |  
 | 
      
         | 1128 |  |  |   return SImode;
 | 
      
         | 1129 |  |  | }
 | 
      
         | 1130 |  |  |  
 | 
      
         | 1131 |  |  | static bool
 | 
      
         | 1132 |  |  | rx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 | 
      
         | 1133 |  |  | {
 | 
      
         | 1134 |  |  |   HOST_WIDE_INT size;
 | 
      
         | 1135 |  |  |  
 | 
      
         | 1136 |  |  |   if (TYPE_MODE (type) != BLKmode
 | 
      
         | 1137 |  |  |       && ! AGGREGATE_TYPE_P (type))
 | 
      
         | 1138 |  |  |     return false;
 | 
      
         | 1139 |  |  |  
 | 
      
         | 1140 |  |  |   size = int_size_in_bytes (type);
 | 
      
         | 1141 |  |  |   /* Large structs and those whose size is not an
 | 
      
         | 1142 |  |  |      exact multiple of 4 are returned in memory.  */
 | 
      
         | 1143 |  |  |   return size < 1
 | 
      
         | 1144 |  |  |     || size > 16
 | 
      
         | 1145 |  |  |     || (size % UNITS_PER_WORD) != 0;
 | 
      
         | 1146 |  |  | }
 | 
      
         | 1147 |  |  |  
 | 
      
         | 1148 |  |  | static rtx
 | 
      
         | 1149 |  |  | rx_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
 | 
      
         | 1150 |  |  |                      int incoming ATTRIBUTE_UNUSED)
 | 
      
         | 1151 |  |  | {
 | 
      
         | 1152 |  |  |   return gen_rtx_REG (Pmode, STRUCT_VAL_REGNUM);
 | 
      
         | 1153 |  |  | }
 | 
      
         | 1154 |  |  |  
 | 
      
         | 1155 |  |  | static bool
 | 
      
         | 1156 |  |  | rx_return_in_msb (const_tree valtype)
 | 
      
         | 1157 |  |  | {
 | 
      
         | 1158 |  |  |   return TARGET_BIG_ENDIAN_DATA
 | 
      
         | 1159 |  |  |     && (AGGREGATE_TYPE_P (valtype) || TREE_CODE (valtype) == COMPLEX_TYPE);
 | 
      
         | 1160 |  |  | }
 | 
      
         | 1161 |  |  |  
 | 
      
         | 1162 |  |  | /* Returns true if the provided function has the specified attribute.  */
 | 
      
         | 1163 |  |  |  
 | 
      
         | 1164 |  |  | static inline bool
 | 
      
         | 1165 |  |  | has_func_attr (const_tree decl, const char * func_attr)
 | 
      
         | 1166 |  |  | {
 | 
      
         | 1167 |  |  |   if (decl == NULL_TREE)
 | 
      
         | 1168 |  |  |     decl = current_function_decl;
 | 
      
         | 1169 |  |  |  
 | 
      
         | 1170 |  |  |   return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
 | 
      
         | 1171 |  |  | }
 | 
      
         | 1172 |  |  |  
 | 
      
         | 1173 |  |  | /* Returns true if the provided function has the "fast_interrupt" attribute.  */
 | 
      
         | 1174 |  |  |  
 | 
      
         | 1175 |  |  | static inline bool
 | 
      
         | 1176 |  |  | is_fast_interrupt_func (const_tree decl)
 | 
      
         | 1177 |  |  | {
 | 
      
         | 1178 |  |  |   return has_func_attr (decl, "fast_interrupt");
 | 
      
         | 1179 |  |  | }
 | 
      
         | 1180 |  |  |  
 | 
      
         | 1181 |  |  | /* Returns true if the provided function has the "interrupt" attribute.  */
 | 
      
         | 1182 |  |  |  
 | 
      
         | 1183 |  |  | static inline bool
 | 
      
         | 1184 |  |  | is_interrupt_func (const_tree decl)
 | 
      
         | 1185 |  |  | {
 | 
      
         | 1186 |  |  |   return has_func_attr (decl, "interrupt");
 | 
      
         | 1187 |  |  | }
 | 
      
         | 1188 |  |  |  
 | 
      
         | 1189 |  |  | /* Returns true if the provided function has the "naked" attribute.  */
 | 
      
         | 1190 |  |  |  
 | 
      
         | 1191 |  |  | static inline bool
 | 
      
         | 1192 |  |  | is_naked_func (const_tree decl)
 | 
      
         | 1193 |  |  | {
 | 
      
         | 1194 |  |  |   return has_func_attr (decl, "naked");
 | 
      
         | 1195 |  |  | }
 | 
      
         | 1196 |  |  |  
 | 
      
         | 1197 |  |  | static bool use_fixed_regs = false;
 | 
      
         | 1198 |  |  |  
 | 
      
         | 1199 |  |  | static void
 | 
      
         | 1200 |  |  | rx_conditional_register_usage (void)
 | 
      
         | 1201 |  |  | {
 | 
      
         | 1202 |  |  |   static bool using_fixed_regs = false;
 | 
      
         | 1203 |  |  |  
 | 
      
         | 1204 |  |  |   if (TARGET_PID)
 | 
      
         | 1205 |  |  |     {
 | 
      
         | 1206 |  |  |       rx_pid_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
 | 
      
         | 1207 |  |  |       fixed_regs[rx_pid_base_regnum_val] = call_used_regs [rx_pid_base_regnum_val] = 1;
 | 
      
         | 1208 |  |  |     }
 | 
      
         | 1209 |  |  |  
 | 
      
         | 1210 |  |  |   if (rx_small_data_limit > 0)
 | 
      
         | 1211 |  |  |     {
 | 
      
         | 1212 |  |  |       if (TARGET_PID)
 | 
      
         | 1213 |  |  |         rx_gp_base_regnum_val = rx_pid_base_regnum_val - 1;
 | 
      
         | 1214 |  |  |       else
 | 
      
         | 1215 |  |  |         rx_gp_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
 | 
      
         | 1216 |  |  |  
 | 
      
         | 1217 |  |  |       fixed_regs[rx_gp_base_regnum_val] = call_used_regs [rx_gp_base_regnum_val] = 1;
 | 
      
         | 1218 |  |  |     }
 | 
      
         | 1219 |  |  |  
 | 
      
         | 1220 |  |  |   if (use_fixed_regs != using_fixed_regs)
 | 
      
         | 1221 |  |  |     {
 | 
      
         | 1222 |  |  |       static char saved_fixed_regs[FIRST_PSEUDO_REGISTER];
 | 
      
         | 1223 |  |  |       static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
 | 
      
         | 1224 |  |  |  
 | 
      
         | 1225 |  |  |       if (use_fixed_regs)
 | 
      
         | 1226 |  |  |         {
 | 
      
         | 1227 |  |  |           unsigned int r;
 | 
      
         | 1228 |  |  |  
 | 
      
         | 1229 |  |  |           memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
 | 
      
         | 1230 |  |  |           memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
 | 
      
         | 1231 |  |  |  
 | 
      
         | 1232 |  |  |           /* This is for fast interrupt handlers.  Any register in
 | 
      
         | 1233 |  |  |              the range r10 to r13 (inclusive) that is currently
 | 
      
         | 1234 |  |  |              marked as fixed is now a viable, call-used register.  */
 | 
      
         | 1235 |  |  |           for (r = 10; r <= 13; r++)
 | 
      
         | 1236 |  |  |             if (fixed_regs[r])
 | 
      
         | 1237 |  |  |               {
 | 
      
         | 1238 |  |  |                 fixed_regs[r] = 0;
 | 
      
         | 1239 |  |  |                 call_used_regs[r] = 1;
 | 
      
         | 1240 |  |  |               }
 | 
      
         | 1241 |  |  |  
 | 
      
         | 1242 |  |  |           /* Mark r7 as fixed.  This is just a hack to avoid
 | 
      
         | 1243 |  |  |              altering the reg_alloc_order array so that the newly
 | 
      
         | 1244 |  |  |              freed r10-r13 registers are the preferred registers.  */
 | 
      
         | 1245 |  |  |           fixed_regs[7] = call_used_regs[7] = 1;
 | 
      
         | 1246 |  |  |         }
 | 
      
         | 1247 |  |  |       else
 | 
      
         | 1248 |  |  |         {
 | 
      
         | 1249 |  |  |           /* Restore the normal register masks.  */
 | 
      
         | 1250 |  |  |           memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs);
 | 
      
         | 1251 |  |  |           memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs);
 | 
      
         | 1252 |  |  |         }
 | 
      
         | 1253 |  |  |  
 | 
      
         | 1254 |  |  |       using_fixed_regs = use_fixed_regs;
 | 
      
         | 1255 |  |  |     }
 | 
      
         | 1256 |  |  | }
 | 
      
         | 1257 |  |  |  
 | 
      
         | 1258 |  |  | /* Perform any actions necessary before starting to compile FNDECL.
 | 
      
         | 1259 |  |  |    For the RX we use this to make sure that we have the correct
 | 
      
         | 1260 |  |  |    set of register masks selected.  If FNDECL is NULL then we are
 | 
      
         | 1261 |  |  |    compiling top level things.  */
 | 
      
         | 1262 |  |  |  
 | 
      
         | 1263 |  |  | static void
 | 
      
         | 1264 |  |  | rx_set_current_function (tree fndecl)
 | 
      
         | 1265 |  |  | {
 | 
      
         | 1266 |  |  |   /* Remember the last target of rx_set_current_function.  */
 | 
      
         | 1267 |  |  |   static tree rx_previous_fndecl;
 | 
      
         | 1268 |  |  |   bool prev_was_fast_interrupt;
 | 
      
         | 1269 |  |  |   bool current_is_fast_interrupt;
 | 
      
         | 1270 |  |  |  
 | 
      
         | 1271 |  |  |   /* Only change the context if the function changes.  This hook is called
 | 
      
         | 1272 |  |  |      several times in the course of compiling a function, and we don't want
 | 
      
         | 1273 |  |  |      to slow things down too much or call target_reinit when it isn't safe.  */
 | 
      
         | 1274 |  |  |   if (fndecl == rx_previous_fndecl)
 | 
      
         | 1275 |  |  |     return;
 | 
      
         | 1276 |  |  |  
 | 
      
         | 1277 |  |  |   prev_was_fast_interrupt
 | 
      
         | 1278 |  |  |     = rx_previous_fndecl
 | 
      
         | 1279 |  |  |     ? is_fast_interrupt_func (rx_previous_fndecl) : false;
 | 
      
         | 1280 |  |  |  
 | 
      
         | 1281 |  |  |   current_is_fast_interrupt
 | 
      
         | 1282 |  |  |     = fndecl ? is_fast_interrupt_func (fndecl) : false;
 | 
      
         | 1283 |  |  |  
 | 
      
         | 1284 |  |  |   if (prev_was_fast_interrupt != current_is_fast_interrupt)
 | 
      
         | 1285 |  |  |     {
 | 
      
         | 1286 |  |  |       use_fixed_regs = current_is_fast_interrupt;
 | 
      
         | 1287 |  |  |       target_reinit ();
 | 
      
         | 1288 |  |  |     }
 | 
      
         | 1289 |  |  |  
 | 
      
         | 1290 |  |  |   rx_previous_fndecl = fndecl;
 | 
      
         | 1291 |  |  | }
 | 
      
         | 1292 |  |  |  
 | 
      
         | 1293 |  |  | /* Typical stack layout should looks like this after the function's prologue:
 | 
      
         | 1294 |  |  |  
 | 
      
         | 1295 |  |  |                             |    |
 | 
      
         | 1296 |  |  |                               --                       ^
 | 
      
         | 1297 |  |  |                             |    | \                   |
 | 
      
         | 1298 |  |  |                             |    |   arguments saved   | Increasing
 | 
      
         | 1299 |  |  |                             |    |   on the stack      |  addresses
 | 
      
         | 1300 |  |  |     PARENT   arg pointer -> |    | /
 | 
      
         | 1301 |  |  |   -------------------------- ---- -------------------
 | 
      
         | 1302 |  |  |     CHILD                   |ret |   return address
 | 
      
         | 1303 |  |  |                               --
 | 
      
         | 1304 |  |  |                             |    | \
 | 
      
         | 1305 |  |  |                             |    |   call saved
 | 
      
         | 1306 |  |  |                             |    |   registers
 | 
      
         | 1307 |  |  |                             |    | /
 | 
      
         | 1308 |  |  |                               --
 | 
      
         | 1309 |  |  |                             |    | \
 | 
      
         | 1310 |  |  |                             |    |   local
 | 
      
         | 1311 |  |  |                             |    |   variables
 | 
      
         | 1312 |  |  |         frame pointer ->    |    | /
 | 
      
         | 1313 |  |  |                               --
 | 
      
         | 1314 |  |  |                             |    | \
 | 
      
         | 1315 |  |  |                             |    |   outgoing          | Decreasing
 | 
      
         | 1316 |  |  |                             |    |   arguments         |  addresses
 | 
      
         | 1317 |  |  |    current stack pointer -> |    | /                   |
 | 
      
         | 1318 |  |  |   -------------------------- ---- ------------------   V
 | 
      
         | 1319 |  |  |                             |    |                 */
 | 
      
         | 1320 |  |  |  
 | 
      
         | 1321 |  |  | static unsigned int
 | 
      
         | 1322 |  |  | bit_count (unsigned int x)
 | 
      
         | 1323 |  |  | {
 | 
      
         | 1324 |  |  |   const unsigned int m1 = 0x55555555;
 | 
      
         | 1325 |  |  |   const unsigned int m2 = 0x33333333;
 | 
      
         | 1326 |  |  |   const unsigned int m4 = 0x0f0f0f0f;
 | 
      
         | 1327 |  |  |  
 | 
      
         | 1328 |  |  |   x -= (x >> 1) & m1;
 | 
      
         | 1329 |  |  |   x = (x & m2) + ((x >> 2) & m2);
 | 
      
         | 1330 |  |  |   x = (x + (x >> 4)) & m4;
 | 
      
         | 1331 |  |  |   x += x >>  8;
 | 
      
         | 1332 |  |  |  
 | 
      
         | 1333 |  |  |   return (x + (x >> 16)) & 0x3f;
 | 
      
         | 1334 |  |  | }
 | 
      
         | 1335 |  |  |  
 | 
      
         | 1336 |  |  | #define MUST_SAVE_ACC_REGISTER                  \
 | 
      
         | 1337 |  |  |   (TARGET_SAVE_ACC_REGISTER                     \
 | 
      
         | 1338 |  |  |    && (is_interrupt_func (NULL_TREE)            \
 | 
      
         | 1339 |  |  |        || is_fast_interrupt_func (NULL_TREE)))
 | 
      
         | 1340 |  |  |  
 | 
      
         | 1341 |  |  | /* Returns either the lowest numbered and highest numbered registers that
 | 
      
         | 1342 |  |  |    occupy the call-saved area of the stack frame, if the registers are
 | 
      
         | 1343 |  |  |    stored as a contiguous block, or else a bitmask of the individual
 | 
      
         | 1344 |  |  |    registers if they are stored piecemeal.
 | 
      
         | 1345 |  |  |  
 | 
      
         | 1346 |  |  |    Also computes the size of the frame and the size of the outgoing
 | 
      
         | 1347 |  |  |    arguments block (in bytes).  */
 | 
      
         | 1348 |  |  |  
 | 
      
         | 1349 |  |  | static void
 | 
      
         | 1350 |  |  | rx_get_stack_layout (unsigned int * lowest,
 | 
      
         | 1351 |  |  |                      unsigned int * highest,
 | 
      
         | 1352 |  |  |                      unsigned int * register_mask,
 | 
      
         | 1353 |  |  |                      unsigned int * frame_size,
 | 
      
         | 1354 |  |  |                      unsigned int * stack_size)
 | 
      
         | 1355 |  |  | {
 | 
      
         | 1356 |  |  |   unsigned int reg;
 | 
      
         | 1357 |  |  |   unsigned int low;
 | 
      
         | 1358 |  |  |   unsigned int high;
 | 
      
         | 1359 |  |  |   unsigned int fixed_reg = 0;
 | 
      
         | 1360 |  |  |   unsigned int save_mask;
 | 
      
         | 1361 |  |  |   unsigned int pushed_mask;
 | 
      
         | 1362 |  |  |   unsigned int unneeded_pushes;
 | 
      
         | 1363 |  |  |  
 | 
      
         | 1364 |  |  |   if (is_naked_func (NULL_TREE))
 | 
      
         | 1365 |  |  |     {
 | 
      
         | 1366 |  |  |       /* Naked functions do not create their own stack frame.
 | 
      
         | 1367 |  |  |          Instead the programmer must do that for us.  */
 | 
      
         | 1368 |  |  |       * lowest = 0;
 | 
      
         | 1369 |  |  |       * highest = 0;
 | 
      
         | 1370 |  |  |       * register_mask = 0;
 | 
      
         | 1371 |  |  |       * frame_size = 0;
 | 
      
         | 1372 |  |  |       * stack_size = 0;
 | 
      
         | 1373 |  |  |       return;
 | 
      
         | 1374 |  |  |     }
 | 
      
         | 1375 |  |  |  
 | 
      
         | 1376 |  |  |   for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++)
 | 
      
         | 1377 |  |  |     {
 | 
      
         | 1378 |  |  |       if ((df_regs_ever_live_p (reg)
 | 
      
         | 1379 |  |  |            /* Always save all call clobbered registers inside non-leaf
 | 
      
         | 1380 |  |  |               interrupt handlers, even if they are not live - they may
 | 
      
         | 1381 |  |  |               be used in (non-interrupt aware) routines called from this one.  */
 | 
      
         | 1382 |  |  |            || (call_used_regs[reg]
 | 
      
         | 1383 |  |  |                && is_interrupt_func (NULL_TREE)
 | 
      
         | 1384 |  |  |                && ! current_function_is_leaf))
 | 
      
         | 1385 |  |  |           && (! call_used_regs[reg]
 | 
      
         | 1386 |  |  |               /* Even call clobbered registered must
 | 
      
         | 1387 |  |  |                  be pushed inside interrupt handlers.  */
 | 
      
         | 1388 |  |  |               || is_interrupt_func (NULL_TREE)
 | 
      
         | 1389 |  |  |               /* Likewise for fast interrupt handlers, except registers r10 -
 | 
      
         | 1390 |  |  |                  r13.  These are normally call-saved, but may have been set
 | 
      
         | 1391 |  |  |                  to call-used by rx_conditional_register_usage.  If so then
 | 
      
         | 1392 |  |  |                  they can be used in the fast interrupt handler without
 | 
      
         | 1393 |  |  |                  saving them on the stack.  */
 | 
      
         | 1394 |  |  |               || (is_fast_interrupt_func (NULL_TREE)
 | 
      
         | 1395 |  |  |                   && ! IN_RANGE (reg, 10, 13))))
 | 
      
         | 1396 |  |  |         {
 | 
      
         | 1397 |  |  |           if (low == 0)
 | 
      
         | 1398 |  |  |             low = reg;
 | 
      
         | 1399 |  |  |           high = reg;
 | 
      
         | 1400 |  |  |  
 | 
      
         | 1401 |  |  |           save_mask |= 1 << reg;
 | 
      
         | 1402 |  |  |         }
 | 
      
         | 1403 |  |  |  
 | 
      
         | 1404 |  |  |       /* Remember if we see a fixed register
 | 
      
         | 1405 |  |  |          after having found the low register.  */
 | 
      
         | 1406 |  |  |       if (low != 0 && fixed_reg == 0 && fixed_regs [reg])
 | 
      
         | 1407 |  |  |         fixed_reg = reg;
 | 
      
         | 1408 |  |  |     }
 | 
      
         | 1409 |  |  |  
 | 
      
         | 1410 |  |  |   /* If we have to save the accumulator register, make sure
 | 
      
         | 1411 |  |  |      that at least two registers are pushed into the frame.  */
 | 
      
         | 1412 |  |  |   if (MUST_SAVE_ACC_REGISTER
 | 
      
         | 1413 |  |  |       && bit_count (save_mask) < 2)
 | 
      
         | 1414 |  |  |     {
 | 
      
         | 1415 |  |  |       save_mask |= (1 << 13) | (1 << 14);
 | 
      
         | 1416 |  |  |       if (low == 0)
 | 
      
         | 1417 |  |  |         low = 13;
 | 
      
         | 1418 |  |  |       if (high == 0 || low == high)
 | 
      
         | 1419 |  |  |         high = low + 1;
 | 
      
         | 1420 |  |  |     }
 | 
      
         | 1421 |  |  |  
 | 
      
         | 1422 |  |  |   /* Decide if it would be faster fill in the call-saved area of the stack
 | 
      
         | 1423 |  |  |      frame using multiple PUSH instructions instead of a single PUSHM
 | 
      
         | 1424 |  |  |      instruction.
 | 
      
         | 1425 |  |  |  
 | 
      
         | 1426 |  |  |      SAVE_MASK is a bitmask of the registers that must be stored in the
 | 
      
         | 1427 |  |  |      call-save area.  PUSHED_MASK is a bitmask of the registers that would
 | 
      
         | 1428 |  |  |      be pushed into the area if we used a PUSHM instruction.  UNNEEDED_PUSHES
 | 
      
         | 1429 |  |  |      is a bitmask of those registers in pushed_mask that are not in
 | 
      
         | 1430 |  |  |      save_mask.
 | 
      
         | 1431 |  |  |  
 | 
      
         | 1432 |  |  |      We use a simple heuristic that says that it is better to use
 | 
      
         | 1433 |  |  |      multiple PUSH instructions if the number of unnecessary pushes is
 | 
      
         | 1434 |  |  |      greater than the number of necessary pushes.
 | 
      
         | 1435 |  |  |  
 | 
      
         | 1436 |  |  |      We also use multiple PUSH instructions if there are any fixed registers
 | 
      
         | 1437 |  |  |      between LOW and HIGH.  The only way that this can happen is if the user
 | 
      
         | 1438 |  |  |      has specified --fixed-<reg-name> on the command line and in such
 | 
      
         | 1439 |  |  |      circumstances we do not want to touch the fixed registers at all.
 | 
      
         | 1440 |  |  |  
 | 
      
         | 1441 |  |  |      FIXME: Is it worth improving this heuristic ?  */
 | 
      
         | 1442 |  |  |   pushed_mask = (-1 << low) & ~(-1 << (high + 1));
 | 
      
         | 1443 |  |  |   unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask;
 | 
      
         | 1444 |  |  |  
 | 
      
         | 1445 |  |  |   if ((fixed_reg && fixed_reg <= high)
 | 
      
         | 1446 |  |  |       || (optimize_function_for_speed_p (cfun)
 | 
      
         | 1447 |  |  |           && bit_count (save_mask) < bit_count (unneeded_pushes)))
 | 
      
         | 1448 |  |  |     {
 | 
      
         | 1449 |  |  |       /* Use multiple pushes.  */
 | 
      
         | 1450 |  |  |       * lowest = 0;
 | 
      
         | 1451 |  |  |       * highest = 0;
 | 
      
         | 1452 |  |  |       * register_mask = save_mask;
 | 
      
         | 1453 |  |  |     }
 | 
      
         | 1454 |  |  |   else
 | 
      
         | 1455 |  |  |     {
 | 
      
         | 1456 |  |  |       /* Use one push multiple instruction.  */
 | 
      
         | 1457 |  |  |       * lowest = low;
 | 
      
         | 1458 |  |  |       * highest = high;
 | 
      
         | 1459 |  |  |       * register_mask = 0;
 | 
      
         | 1460 |  |  |     }
 | 
      
         | 1461 |  |  |  
 | 
      
         | 1462 |  |  |   * frame_size = rx_round_up
 | 
      
         | 1463 |  |  |     (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT);
 | 
      
         | 1464 |  |  |  
 | 
      
         | 1465 |  |  |   if (crtl->args.size > 0)
 | 
      
         | 1466 |  |  |     * frame_size += rx_round_up
 | 
      
         | 1467 |  |  |       (crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT);
 | 
      
         | 1468 |  |  |  
 | 
      
         | 1469 |  |  |   * stack_size = rx_round_up
 | 
      
         | 1470 |  |  |     (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT);
 | 
      
         | 1471 |  |  | }
 | 
      
         | 1472 |  |  |  
 | 
      
         | 1473 |  |  | /* Generate a PUSHM instruction that matches the given operands.  */
 | 
      
         | 1474 |  |  |  
 | 
      
         | 1475 |  |  | void
 | 
      
         | 1476 |  |  | rx_emit_stack_pushm (rtx * operands)
 | 
      
         | 1477 |  |  | {
 | 
      
         | 1478 |  |  |   HOST_WIDE_INT last_reg;
 | 
      
         | 1479 |  |  |   rtx first_push;
 | 
      
         | 1480 |  |  |  
 | 
      
         | 1481 |  |  |   gcc_assert (CONST_INT_P (operands[0]));
 | 
      
         | 1482 |  |  |   last_reg = (INTVAL (operands[0]) / UNITS_PER_WORD) - 1;
 | 
      
         | 1483 |  |  |  
 | 
      
         | 1484 |  |  |   gcc_assert (GET_CODE (operands[1]) == PARALLEL);
 | 
      
         | 1485 |  |  |   first_push = XVECEXP (operands[1], 0, 1);
 | 
      
         | 1486 |  |  |   gcc_assert (SET_P (first_push));
 | 
      
         | 1487 |  |  |   first_push = SET_SRC (first_push);
 | 
      
         | 1488 |  |  |   gcc_assert (REG_P (first_push));
 | 
      
         | 1489 |  |  |  
 | 
      
         | 1490 |  |  |   asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n",
 | 
      
         | 1491 |  |  |                reg_names [REGNO (first_push) - last_reg],
 | 
      
         | 1492 |  |  |                reg_names [REGNO (first_push)]);
 | 
      
         | 1493 |  |  | }
 | 
      
         | 1494 |  |  |  
 | 
      
         | 1495 |  |  | /* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate.  */
 | 
      
         | 1496 |  |  |  
 | 
      
         | 1497 |  |  | static rtx
 | 
      
         | 1498 |  |  | gen_rx_store_vector (unsigned int low, unsigned int high)
 | 
      
         | 1499 |  |  | {
 | 
      
         | 1500 |  |  |   unsigned int i;
 | 
      
         | 1501 |  |  |   unsigned int count = (high - low) + 2;
 | 
      
         | 1502 |  |  |   rtx vector;
 | 
      
         | 1503 |  |  |  
 | 
      
         | 1504 |  |  |   vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
 | 
      
         | 1505 |  |  |  
 | 
      
         | 1506 |  |  |   XVECEXP (vector, 0, 0) =
 | 
      
         | 1507 |  |  |     gen_rtx_SET (VOIDmode, stack_pointer_rtx,
 | 
      
         | 1508 |  |  |                  gen_rtx_MINUS (SImode, stack_pointer_rtx,
 | 
      
         | 1509 |  |  |                                 GEN_INT ((count - 1) * UNITS_PER_WORD)));
 | 
      
         | 1510 |  |  |  
 | 
      
         | 1511 |  |  |   for (i = 0; i < count - 1; i++)
 | 
      
         | 1512 |  |  |     XVECEXP (vector, 0, i + 1) =
 | 
      
         | 1513 |  |  |       gen_rtx_SET (VOIDmode,
 | 
      
         | 1514 |  |  |                    gen_rtx_MEM (SImode,
 | 
      
         | 1515 |  |  |                                 gen_rtx_MINUS (SImode, stack_pointer_rtx,
 | 
      
         | 1516 |  |  |                                                GEN_INT ((i + 1) * UNITS_PER_WORD))),
 | 
      
         | 1517 |  |  |                    gen_rtx_REG (SImode, high - i));
 | 
      
         | 1518 |  |  |   return vector;
 | 
      
         | 1519 |  |  | }
 | 
      
         | 1520 |  |  |  
 | 
      
         | 1521 |  |  | /* Mark INSN as being frame related.  If it is a PARALLEL
 | 
      
         | 1522 |  |  |    then mark each element as being frame related as well.  */
 | 
      
         | 1523 |  |  |  
 | 
      
         | 1524 |  |  | static void
 | 
      
         | 1525 |  |  | mark_frame_related (rtx insn)
 | 
      
         | 1526 |  |  | {
 | 
      
         | 1527 |  |  |   RTX_FRAME_RELATED_P (insn) = 1;
 | 
      
         | 1528 |  |  |   insn = PATTERN (insn);
 | 
      
         | 1529 |  |  |  
 | 
      
         | 1530 |  |  |   if (GET_CODE (insn) == PARALLEL)
 | 
      
         | 1531 |  |  |     {
 | 
      
         | 1532 |  |  |       unsigned int i;
 | 
      
         | 1533 |  |  |  
 | 
      
         | 1534 |  |  |       for (i = 0; i < (unsigned) XVECLEN (insn, 0); i++)
 | 
      
         | 1535 |  |  |         RTX_FRAME_RELATED_P (XVECEXP (insn, 0, i)) = 1;
 | 
      
         | 1536 |  |  |     }
 | 
      
         | 1537 |  |  | }
 | 
      
         | 1538 |  |  |  
 | 
      
         | 1539 |  |  | static bool
 | 
      
         | 1540 |  |  | ok_for_max_constant (HOST_WIDE_INT val)
 | 
      
         | 1541 |  |  | {
 | 
      
         | 1542 |  |  |   if (rx_max_constant_size == 0  || rx_max_constant_size == 4)
 | 
      
         | 1543 |  |  |     /* If there is no constraint on the size of constants
 | 
      
         | 1544 |  |  |        used as operands, then any value is legitimate.  */
 | 
      
         | 1545 |  |  |     return true;
 | 
      
         | 1546 |  |  |  
 | 
      
         | 1547 |  |  |   /* rx_max_constant_size specifies the maximum number
 | 
      
         | 1548 |  |  |      of bytes that can be used to hold a signed value.  */
 | 
      
         | 1549 |  |  |   return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
 | 
      
         | 1550 |  |  |                         ( 1 << (rx_max_constant_size * 8)));
 | 
      
         | 1551 |  |  | }
 | 
      
         | 1552 |  |  |  
 | 
      
         | 1553 |  |  | /* Generate an ADD of SRC plus VAL into DEST.
 | 
      
         | 1554 |  |  |    Handles the case where VAL is too big for max_constant_value.
 | 
      
         | 1555 |  |  |    Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true.  */
 | 
      
         | 1556 |  |  |  
 | 
      
         | 1557 |  |  | static void
 | 
      
         | 1558 |  |  | gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related)
 | 
      
         | 1559 |  |  | {
 | 
      
         | 1560 |  |  |   rtx insn;
 | 
      
         | 1561 |  |  |  
 | 
      
         | 1562 |  |  |   if (val == NULL_RTX || INTVAL (val) == 0)
 | 
      
         | 1563 |  |  |     {
 | 
      
         | 1564 |  |  |       gcc_assert (dest != src);
 | 
      
         | 1565 |  |  |  
 | 
      
         | 1566 |  |  |       insn = emit_move_insn (dest, src);
 | 
      
         | 1567 |  |  |     }
 | 
      
         | 1568 |  |  |   else if (ok_for_max_constant (INTVAL (val)))
 | 
      
         | 1569 |  |  |     insn = emit_insn (gen_addsi3 (dest, src, val));
 | 
      
         | 1570 |  |  |   else
 | 
      
         | 1571 |  |  |     {
 | 
      
         | 1572 |  |  |       /* Wrap VAL in an UNSPEC so that rx_is_legitimate_constant
 | 
      
         | 1573 |  |  |          will not reject it.  */
 | 
      
         | 1574 |  |  |       val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST));
 | 
      
         | 1575 |  |  |       insn = emit_insn (gen_addsi3 (dest, src, val));
 | 
      
         | 1576 |  |  |  
 | 
      
         | 1577 |  |  |       if (is_frame_related)
 | 
      
         | 1578 |  |  |         /* We have to provide our own frame related note here
 | 
      
         | 1579 |  |  |            as the dwarf2out code cannot be expected to grok
 | 
      
         | 1580 |  |  |            our unspec.  */
 | 
      
         | 1581 |  |  |         add_reg_note (insn, REG_FRAME_RELATED_EXPR,
 | 
      
         | 1582 |  |  |                       gen_rtx_SET (SImode, dest,
 | 
      
         | 1583 |  |  |                                    gen_rtx_PLUS (SImode, src, val)));
 | 
      
         | 1584 |  |  |       return;
 | 
      
         | 1585 |  |  |     }
 | 
      
         | 1586 |  |  |  
 | 
      
         | 1587 |  |  |   if (is_frame_related)
 | 
      
         | 1588 |  |  |     RTX_FRAME_RELATED_P (insn) = 1;
 | 
      
         | 1589 |  |  |   return;
 | 
      
         | 1590 |  |  | }
 | 
      
         | 1591 |  |  |  
 | 
      
         | 1592 |  |  | void
 | 
      
         | 1593 |  |  | rx_expand_prologue (void)
 | 
      
         | 1594 |  |  | {
 | 
      
         | 1595 |  |  |   unsigned int stack_size;
 | 
      
         | 1596 |  |  |   unsigned int frame_size;
 | 
      
         | 1597 |  |  |   unsigned int mask;
 | 
      
         | 1598 |  |  |   unsigned int low;
 | 
      
         | 1599 |  |  |   unsigned int high;
 | 
      
         | 1600 |  |  |   unsigned int reg;
 | 
      
         | 1601 |  |  |   rtx insn;
 | 
      
         | 1602 |  |  |  
 | 
      
         | 1603 |  |  |   /* Naked functions use their own, programmer provided prologues.  */
 | 
      
         | 1604 |  |  |   if (is_naked_func (NULL_TREE))
 | 
      
         | 1605 |  |  |     return;
 | 
      
         | 1606 |  |  |  
 | 
      
         | 1607 |  |  |   rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
 | 
      
         | 1608 |  |  |  
 | 
      
         | 1609 |  |  |   /* If we use any of the callee-saved registers, save them now.  */
 | 
      
         | 1610 |  |  |   if (mask)
 | 
      
         | 1611 |  |  |     {
 | 
      
         | 1612 |  |  |       /* Push registers in reverse order.  */
 | 
      
         | 1613 |  |  |       for (reg = CC_REGNUM; reg --;)
 | 
      
         | 1614 |  |  |         if (mask & (1 << reg))
 | 
      
         | 1615 |  |  |           {
 | 
      
         | 1616 |  |  |             insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
 | 
      
         | 1617 |  |  |             mark_frame_related (insn);
 | 
      
         | 1618 |  |  |           }
 | 
      
         | 1619 |  |  |     }
 | 
      
         | 1620 |  |  |   else if (low)
 | 
      
         | 1621 |  |  |     {
 | 
      
         | 1622 |  |  |       if (high == low)
 | 
      
         | 1623 |  |  |         insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
 | 
      
         | 1624 |  |  |       else
 | 
      
         | 1625 |  |  |         insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
 | 
      
         | 1626 |  |  |                                                     * UNITS_PER_WORD),
 | 
      
         | 1627 |  |  |                                            gen_rx_store_vector (low, high)));
 | 
      
         | 1628 |  |  |       mark_frame_related (insn);
 | 
      
         | 1629 |  |  |     }
 | 
      
         | 1630 |  |  |  
 | 
      
         | 1631 |  |  |   if (MUST_SAVE_ACC_REGISTER)
 | 
      
         | 1632 |  |  |     {
 | 
      
         | 1633 |  |  |       unsigned int acc_high, acc_low;
 | 
      
         | 1634 |  |  |  
 | 
      
         | 1635 |  |  |       /* Interrupt handlers have to preserve the accumulator
 | 
      
         | 1636 |  |  |          register if so requested by the user.  Use the first
 | 
      
         | 1637 |  |  |          two pushed registers as intermediaries.  */
 | 
      
         | 1638 |  |  |       if (mask)
 | 
      
         | 1639 |  |  |         {
 | 
      
         | 1640 |  |  |           acc_low = acc_high = 0;
 | 
      
         | 1641 |  |  |  
 | 
      
         | 1642 |  |  |           for (reg = 1; reg < CC_REGNUM; reg ++)
 | 
      
         | 1643 |  |  |             if (mask & (1 << reg))
 | 
      
         | 1644 |  |  |               {
 | 
      
         | 1645 |  |  |                 if (acc_low == 0)
 | 
      
         | 1646 |  |  |                   acc_low = reg;
 | 
      
         | 1647 |  |  |                 else
 | 
      
         | 1648 |  |  |                   {
 | 
      
         | 1649 |  |  |                     acc_high = reg;
 | 
      
         | 1650 |  |  |                     break;
 | 
      
         | 1651 |  |  |                   }
 | 
      
         | 1652 |  |  |               }
 | 
      
         | 1653 |  |  |  
 | 
      
         | 1654 |  |  |           /* We have assumed that there are at least two registers pushed... */
 | 
      
         | 1655 |  |  |           gcc_assert (acc_high != 0);
 | 
      
         | 1656 |  |  |  
 | 
      
         | 1657 |  |  |           /* Note - the bottom 16 bits of the accumulator are inaccessible.
 | 
      
         | 1658 |  |  |              We just assume that they are zero.  */
 | 
      
         | 1659 |  |  |           emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
 | 
      
         | 1660 |  |  |           emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
 | 
      
         | 1661 |  |  |           emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
 | 
      
         | 1662 |  |  |           emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
 | 
      
         | 1663 |  |  |         }
 | 
      
         | 1664 |  |  |       else
 | 
      
         | 1665 |  |  |         {
 | 
      
         | 1666 |  |  |           acc_low = low;
 | 
      
         | 1667 |  |  |           acc_high = low + 1;
 | 
      
         | 1668 |  |  |  
 | 
      
         | 1669 |  |  |           /* We have assumed that there are at least two registers pushed... */
 | 
      
         | 1670 |  |  |           gcc_assert (acc_high <= high);
 | 
      
         | 1671 |  |  |  
 | 
      
         | 1672 |  |  |           emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
 | 
      
         | 1673 |  |  |           emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
 | 
      
         | 1674 |  |  |           emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
 | 
      
         | 1675 |  |  |                                       gen_rx_store_vector (acc_low, acc_high)));
 | 
      
         | 1676 |  |  |         }
 | 
      
         | 1677 |  |  |     }
 | 
      
         | 1678 |  |  |  
 | 
      
         | 1679 |  |  |   /* If needed, set up the frame pointer.  */
 | 
      
         | 1680 |  |  |   if (frame_pointer_needed)
 | 
      
         | 1681 |  |  |     gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 1682 |  |  |                   GEN_INT (- (HOST_WIDE_INT) frame_size), true);
 | 
      
         | 1683 |  |  |  
 | 
      
         | 1684 |  |  |   /* Allocate space for the outgoing args.
 | 
      
         | 1685 |  |  |      If the stack frame has not already been set up then handle this as well.  */
 | 
      
         | 1686 |  |  |   if (stack_size)
 | 
      
         | 1687 |  |  |     {
 | 
      
         | 1688 |  |  |       if (frame_size)
 | 
      
         | 1689 |  |  |         {
 | 
      
         | 1690 |  |  |           if (frame_pointer_needed)
 | 
      
         | 1691 |  |  |             gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
 | 
      
         | 1692 |  |  |                           GEN_INT (- (HOST_WIDE_INT) stack_size), true);
 | 
      
         | 1693 |  |  |           else
 | 
      
         | 1694 |  |  |             gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 1695 |  |  |                           GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
 | 
      
         | 1696 |  |  |                           true);
 | 
      
         | 1697 |  |  |         }
 | 
      
         | 1698 |  |  |       else
 | 
      
         | 1699 |  |  |         gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 1700 |  |  |                       GEN_INT (- (HOST_WIDE_INT) stack_size), true);
 | 
      
         | 1701 |  |  |     }
 | 
      
         | 1702 |  |  |   else if (frame_size)
 | 
      
         | 1703 |  |  |     {
 | 
      
         | 1704 |  |  |       if (! frame_pointer_needed)
 | 
      
         | 1705 |  |  |         gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 1706 |  |  |                       GEN_INT (- (HOST_WIDE_INT) frame_size), true);
 | 
      
         | 1707 |  |  |       else
 | 
      
         | 1708 |  |  |         gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
 | 
      
         | 1709 |  |  |                       true);
 | 
      
         | 1710 |  |  |     }
 | 
      
         | 1711 |  |  | }
 | 
      
         | 1712 |  |  |  
 | 
      
         | 1713 |  |  | static void
 | 
      
         | 1714 |  |  | rx_output_function_prologue (FILE * file,
 | 
      
         | 1715 |  |  |                              HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
 | 
      
         | 1716 |  |  | {
 | 
      
         | 1717 |  |  |   if (is_fast_interrupt_func (NULL_TREE))
 | 
      
         | 1718 |  |  |     asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
 | 
      
         | 1719 |  |  |  
 | 
      
         | 1720 |  |  |   if (is_interrupt_func (NULL_TREE))
 | 
      
         | 1721 |  |  |     asm_fprintf (file, "\t; Note: Interrupt Handler\n");
 | 
      
         | 1722 |  |  |  
 | 
      
         | 1723 |  |  |   if (is_naked_func (NULL_TREE))
 | 
      
         | 1724 |  |  |     asm_fprintf (file, "\t; Note: Naked Function\n");
 | 
      
         | 1725 |  |  |  
 | 
      
         | 1726 |  |  |   if (cfun->static_chain_decl != NULL)
 | 
      
         | 1727 |  |  |     asm_fprintf (file, "\t; Note: Nested function declared "
 | 
      
         | 1728 |  |  |                  "inside another function.\n");
 | 
      
         | 1729 |  |  |  
 | 
      
         | 1730 |  |  |   if (crtl->calls_eh_return)
 | 
      
         | 1731 |  |  |     asm_fprintf (file, "\t; Note: Calls __builtin_eh_return.\n");
 | 
      
         | 1732 |  |  | }
 | 
      
         | 1733 |  |  |  
 | 
      
         | 1734 |  |  | /* Generate a POPM or RTSD instruction that matches the given operands.  */
 | 
      
         | 1735 |  |  |  
 | 
      
         | 1736 |  |  | void
 | 
      
         | 1737 |  |  | rx_emit_stack_popm (rtx * operands, bool is_popm)
 | 
      
         | 1738 |  |  | {
 | 
      
         | 1739 |  |  |   HOST_WIDE_INT stack_adjust;
 | 
      
         | 1740 |  |  |   HOST_WIDE_INT last_reg;
 | 
      
         | 1741 |  |  |   rtx first_push;
 | 
      
         | 1742 |  |  |  
 | 
      
         | 1743 |  |  |   gcc_assert (CONST_INT_P (operands[0]));
 | 
      
         | 1744 |  |  |   stack_adjust = INTVAL (operands[0]);
 | 
      
         | 1745 |  |  |  
 | 
      
         | 1746 |  |  |   gcc_assert (GET_CODE (operands[1]) == PARALLEL);
 | 
      
         | 1747 |  |  |   last_reg = XVECLEN (operands[1], 0) - (is_popm ? 2 : 3);
 | 
      
         | 1748 |  |  |  
 | 
      
         | 1749 |  |  |   first_push = XVECEXP (operands[1], 0, 1);
 | 
      
         | 1750 |  |  |   gcc_assert (SET_P (first_push));
 | 
      
         | 1751 |  |  |   first_push = SET_DEST (first_push);
 | 
      
         | 1752 |  |  |   gcc_assert (REG_P (first_push));
 | 
      
         | 1753 |  |  |  
 | 
      
         | 1754 |  |  |   if (is_popm)
 | 
      
         | 1755 |  |  |     asm_fprintf (asm_out_file, "\tpopm\t%s-%s\n",
 | 
      
         | 1756 |  |  |                  reg_names [REGNO (first_push)],
 | 
      
         | 1757 |  |  |                  reg_names [REGNO (first_push) + last_reg]);
 | 
      
         | 1758 |  |  |   else
 | 
      
         | 1759 |  |  |     asm_fprintf (asm_out_file, "\trtsd\t#%d, %s-%s\n",
 | 
      
         | 1760 |  |  |                  (int) stack_adjust,
 | 
      
         | 1761 |  |  |                  reg_names [REGNO (first_push)],
 | 
      
         | 1762 |  |  |                  reg_names [REGNO (first_push) + last_reg]);
 | 
      
         | 1763 |  |  | }
 | 
      
         | 1764 |  |  |  
 | 
      
         | 1765 |  |  | /* Generate a PARALLEL which will satisfy the rx_rtsd_vector predicate.  */
 | 
      
         | 1766 |  |  |  
 | 
      
         | 1767 |  |  | static rtx
 | 
      
         | 1768 |  |  | gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high)
 | 
      
         | 1769 |  |  | {
 | 
      
         | 1770 |  |  |   unsigned int i;
 | 
      
         | 1771 |  |  |   unsigned int bias = 3;
 | 
      
         | 1772 |  |  |   unsigned int count = (high - low) + bias;
 | 
      
         | 1773 |  |  |   rtx vector;
 | 
      
         | 1774 |  |  |  
 | 
      
         | 1775 |  |  |   vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
 | 
      
         | 1776 |  |  |  
 | 
      
         | 1777 |  |  |   XVECEXP (vector, 0, 0) =
 | 
      
         | 1778 |  |  |     gen_rtx_SET (VOIDmode, stack_pointer_rtx,
 | 
      
         | 1779 |  |  |                  plus_constant (stack_pointer_rtx, adjust));
 | 
      
         | 1780 |  |  |  
 | 
      
         | 1781 |  |  |   for (i = 0; i < count - 2; i++)
 | 
      
         | 1782 |  |  |     XVECEXP (vector, 0, i + 1) =
 | 
      
         | 1783 |  |  |       gen_rtx_SET (VOIDmode,
 | 
      
         | 1784 |  |  |                    gen_rtx_REG (SImode, low + i),
 | 
      
         | 1785 |  |  |                    gen_rtx_MEM (SImode,
 | 
      
         | 1786 |  |  |                                 i == 0 ? stack_pointer_rtx
 | 
      
         | 1787 |  |  |                                 : plus_constant (stack_pointer_rtx,
 | 
      
         | 1788 |  |  |                                                  i * UNITS_PER_WORD)));
 | 
      
         | 1789 |  |  |  
 | 
      
         | 1790 |  |  |   XVECEXP (vector, 0, count - 1) = ret_rtx;
 | 
      
         | 1791 |  |  |  
 | 
      
         | 1792 |  |  |   return vector;
 | 
      
         | 1793 |  |  | }
 | 
      
         | 1794 |  |  |  
 | 
      
         | 1795 |  |  | /* Generate a PARALLEL which will satisfy the rx_load_multiple_vector predicate.  */
 | 
      
         | 1796 |  |  |  
 | 
      
         | 1797 |  |  | static rtx
 | 
      
         | 1798 |  |  | gen_rx_popm_vector (unsigned int low, unsigned int high)
 | 
      
         | 1799 |  |  | {
 | 
      
         | 1800 |  |  |   unsigned int i;
 | 
      
         | 1801 |  |  |   unsigned int count = (high - low) + 2;
 | 
      
         | 1802 |  |  |   rtx vector;
 | 
      
         | 1803 |  |  |  
 | 
      
         | 1804 |  |  |   vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
 | 
      
         | 1805 |  |  |  
 | 
      
         | 1806 |  |  |   XVECEXP (vector, 0, 0) =
 | 
      
         | 1807 |  |  |     gen_rtx_SET (VOIDmode, stack_pointer_rtx,
 | 
      
         | 1808 |  |  |                  plus_constant (stack_pointer_rtx,
 | 
      
         | 1809 |  |  |                                 (count - 1) * UNITS_PER_WORD));
 | 
      
         | 1810 |  |  |  
 | 
      
         | 1811 |  |  |   for (i = 0; i < count - 1; i++)
 | 
      
         | 1812 |  |  |     XVECEXP (vector, 0, i + 1) =
 | 
      
         | 1813 |  |  |       gen_rtx_SET (VOIDmode,
 | 
      
         | 1814 |  |  |                    gen_rtx_REG (SImode, low + i),
 | 
      
         | 1815 |  |  |                    gen_rtx_MEM (SImode,
 | 
      
         | 1816 |  |  |                                 i == 0 ? stack_pointer_rtx
 | 
      
         | 1817 |  |  |                                 : plus_constant (stack_pointer_rtx,
 | 
      
         | 1818 |  |  |                                                  i * UNITS_PER_WORD)));
 | 
      
         | 1819 |  |  |  
 | 
      
         | 1820 |  |  |   return vector;
 | 
      
         | 1821 |  |  | }
 | 
      
         | 1822 |  |  |  
 | 
      
         | 1823 |  |  | /* Returns true if a simple return insn can be used.  */
 | 
      
         | 1824 |  |  |  
 | 
      
         | 1825 |  |  | bool
 | 
      
         | 1826 |  |  | rx_can_use_simple_return (void)
 | 
      
         | 1827 |  |  | {
 | 
      
         | 1828 |  |  |   unsigned int low;
 | 
      
         | 1829 |  |  |   unsigned int high;
 | 
      
         | 1830 |  |  |   unsigned int frame_size;
 | 
      
         | 1831 |  |  |   unsigned int stack_size;
 | 
      
         | 1832 |  |  |   unsigned int register_mask;
 | 
      
         | 1833 |  |  |  
 | 
      
         | 1834 |  |  |   if (is_naked_func (NULL_TREE)
 | 
      
         | 1835 |  |  |       || is_fast_interrupt_func (NULL_TREE)
 | 
      
         | 1836 |  |  |       || is_interrupt_func (NULL_TREE))
 | 
      
         | 1837 |  |  |     return false;
 | 
      
         | 1838 |  |  |  
 | 
      
         | 1839 |  |  |   rx_get_stack_layout (& low, & high, & register_mask,
 | 
      
         | 1840 |  |  |                        & frame_size, & stack_size);
 | 
      
         | 1841 |  |  |  
 | 
      
         | 1842 |  |  |   return (register_mask == 0
 | 
      
         | 1843 |  |  |           && (frame_size + stack_size) == 0
 | 
      
         | 1844 |  |  |           && low == 0);
 | 
      
         | 1845 |  |  | }
 | 
      
         | 1846 |  |  |  
 | 
      
         | 1847 |  |  | void
 | 
      
         | 1848 |  |  | rx_expand_epilogue (bool is_sibcall)
 | 
      
         | 1849 |  |  | {
 | 
      
         | 1850 |  |  |   unsigned int low;
 | 
      
         | 1851 |  |  |   unsigned int high;
 | 
      
         | 1852 |  |  |   unsigned int frame_size;
 | 
      
         | 1853 |  |  |   unsigned int stack_size;
 | 
      
         | 1854 |  |  |   unsigned int register_mask;
 | 
      
         | 1855 |  |  |   unsigned int regs_size;
 | 
      
         | 1856 |  |  |   unsigned int reg;
 | 
      
         | 1857 |  |  |   unsigned HOST_WIDE_INT total_size;
 | 
      
         | 1858 |  |  |  
 | 
      
         | 1859 |  |  |   /* FIXME: We do not support indirect sibcalls at the moment becaause we
 | 
      
         | 1860 |  |  |      cannot guarantee that the register holding the function address is a
 | 
      
         | 1861 |  |  |      call-used register.  If it is a call-saved register then the stack
 | 
      
         | 1862 |  |  |      pop instructions generated in the epilogue will corrupt the address
 | 
      
         | 1863 |  |  |      before it is used.
 | 
      
         | 1864 |  |  |  
 | 
      
         | 1865 |  |  |      Creating a new call-used-only register class works but then the
 | 
      
         | 1866 |  |  |      reload pass gets stuck because it cannot always find a call-used
 | 
      
         | 1867 |  |  |      register for spilling sibcalls.
 | 
      
         | 1868 |  |  |  
 | 
      
         | 1869 |  |  |      The other possible solution is for this pass to scan forward for the
 | 
      
         | 1870 |  |  |      sibcall instruction (if it has been generated) and work out if it
 | 
      
         | 1871 |  |  |      is an indirect sibcall using a call-saved register.  If it is then
 | 
      
         | 1872 |  |  |      the address can copied into a call-used register in this epilogue
 | 
      
         | 1873 |  |  |      code and the sibcall instruction modified to use that register.  */
 | 
      
         | 1874 |  |  |  
 | 
      
         | 1875 |  |  |   if (is_naked_func (NULL_TREE))
 | 
      
         | 1876 |  |  |     {
 | 
      
         | 1877 |  |  |       gcc_assert (! is_sibcall);
 | 
      
         | 1878 |  |  |  
 | 
      
         | 1879 |  |  |       /* Naked functions use their own, programmer provided epilogues.
 | 
      
         | 1880 |  |  |          But, in order to keep gcc happy we have to generate some kind of
 | 
      
         | 1881 |  |  |          epilogue RTL.  */
 | 
      
         | 1882 |  |  |       emit_jump_insn (gen_naked_return ());
 | 
      
         | 1883 |  |  |       return;
 | 
      
         | 1884 |  |  |     }
 | 
      
         | 1885 |  |  |  
 | 
      
         | 1886 |  |  |   rx_get_stack_layout (& low, & high, & register_mask,
 | 
      
         | 1887 |  |  |                        & frame_size, & stack_size);
 | 
      
         | 1888 |  |  |  
 | 
      
         | 1889 |  |  |   total_size = frame_size + stack_size;
 | 
      
         | 1890 |  |  |   regs_size = ((high - low) + 1) * UNITS_PER_WORD;
 | 
      
         | 1891 |  |  |  
 | 
      
         | 1892 |  |  |   /* See if we are unable to use the special stack frame deconstruct and
 | 
      
         | 1893 |  |  |      return instructions.  In most cases we can use them, but the exceptions
 | 
      
         | 1894 |  |  |      are:
 | 
      
         | 1895 |  |  |  
 | 
      
         | 1896 |  |  |      - Sibling calling functions deconstruct the frame but do not return to
 | 
      
         | 1897 |  |  |        their caller.  Instead they branch to their sibling and allow their
 | 
      
         | 1898 |  |  |        return instruction to return to this function's parent.
 | 
      
         | 1899 |  |  |  
 | 
      
         | 1900 |  |  |      - Fast and normal interrupt handling functions have to use special
 | 
      
         | 1901 |  |  |        return instructions.
 | 
      
         | 1902 |  |  |  
 | 
      
         | 1903 |  |  |      - Functions where we have pushed a fragmented set of registers into the
 | 
      
         | 1904 |  |  |        call-save area must have the same set of registers popped.  */
 | 
      
         | 1905 |  |  |   if (is_sibcall
 | 
      
         | 1906 |  |  |       || is_fast_interrupt_func (NULL_TREE)
 | 
      
         | 1907 |  |  |       || is_interrupt_func (NULL_TREE)
 | 
      
         | 1908 |  |  |       || register_mask)
 | 
      
         | 1909 |  |  |     {
 | 
      
         | 1910 |  |  |       /* Cannot use the special instructions - deconstruct by hand.  */
 | 
      
         | 1911 |  |  |       if (total_size)
 | 
      
         | 1912 |  |  |         gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 1913 |  |  |                       GEN_INT (total_size), false);
 | 
      
         | 1914 |  |  |  
 | 
      
         | 1915 |  |  |       if (MUST_SAVE_ACC_REGISTER)
 | 
      
         | 1916 |  |  |         {
 | 
      
         | 1917 |  |  |           unsigned int acc_low, acc_high;
 | 
      
         | 1918 |  |  |  
 | 
      
         | 1919 |  |  |           /* Reverse the saving of the accumulator register onto the stack.
 | 
      
         | 1920 |  |  |              Note we must adjust the saved "low" accumulator value as it
 | 
      
         | 1921 |  |  |              is really the middle 32-bits of the accumulator.  */
 | 
      
         | 1922 |  |  |           if (register_mask)
 | 
      
         | 1923 |  |  |             {
 | 
      
         | 1924 |  |  |               acc_low = acc_high = 0;
 | 
      
         | 1925 |  |  |  
 | 
      
         | 1926 |  |  |               for (reg = 1; reg < CC_REGNUM; reg ++)
 | 
      
         | 1927 |  |  |                 if (register_mask & (1 << reg))
 | 
      
         | 1928 |  |  |                   {
 | 
      
         | 1929 |  |  |                     if (acc_low == 0)
 | 
      
         | 1930 |  |  |                       acc_low = reg;
 | 
      
         | 1931 |  |  |                     else
 | 
      
         | 1932 |  |  |                       {
 | 
      
         | 1933 |  |  |                         acc_high = reg;
 | 
      
         | 1934 |  |  |                         break;
 | 
      
         | 1935 |  |  |                       }
 | 
      
         | 1936 |  |  |                   }
 | 
      
         | 1937 |  |  |               emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
 | 
      
         | 1938 |  |  |               emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
 | 
      
         | 1939 |  |  |             }
 | 
      
         | 1940 |  |  |           else
 | 
      
         | 1941 |  |  |             {
 | 
      
         | 1942 |  |  |               acc_low = low;
 | 
      
         | 1943 |  |  |               acc_high = low + 1;
 | 
      
         | 1944 |  |  |               emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
 | 
      
         | 1945 |  |  |                                          gen_rx_popm_vector (acc_low, acc_high)));
 | 
      
         | 1946 |  |  |             }
 | 
      
         | 1947 |  |  |  
 | 
      
         | 1948 |  |  |           emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
 | 
      
         | 1949 |  |  |                                   gen_rtx_REG (SImode, acc_low),
 | 
      
         | 1950 |  |  |                                   GEN_INT (16)));
 | 
      
         | 1951 |  |  |           emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
 | 
      
         | 1952 |  |  |           emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
 | 
      
         | 1953 |  |  |         }
 | 
      
         | 1954 |  |  |  
 | 
      
         | 1955 |  |  |       if (register_mask)
 | 
      
         | 1956 |  |  |         {
 | 
      
         | 1957 |  |  |           for (reg = 0; reg < CC_REGNUM; reg ++)
 | 
      
         | 1958 |  |  |             if (register_mask & (1 << reg))
 | 
      
         | 1959 |  |  |               emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
 | 
      
         | 1960 |  |  |         }
 | 
      
         | 1961 |  |  |       else if (low)
 | 
      
         | 1962 |  |  |         {
 | 
      
         | 1963 |  |  |           if (high == low)
 | 
      
         | 1964 |  |  |             emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
 | 
      
         | 1965 |  |  |           else
 | 
      
         | 1966 |  |  |             emit_insn (gen_stack_popm (GEN_INT (regs_size),
 | 
      
         | 1967 |  |  |                                        gen_rx_popm_vector (low, high)));
 | 
      
         | 1968 |  |  |         }
 | 
      
         | 1969 |  |  |  
 | 
      
         | 1970 |  |  |       if (is_fast_interrupt_func (NULL_TREE))
 | 
      
         | 1971 |  |  |         {
 | 
      
         | 1972 |  |  |           gcc_assert (! is_sibcall);
 | 
      
         | 1973 |  |  |           emit_jump_insn (gen_fast_interrupt_return ());
 | 
      
         | 1974 |  |  |         }
 | 
      
         | 1975 |  |  |       else if (is_interrupt_func (NULL_TREE))
 | 
      
         | 1976 |  |  |         {
 | 
      
         | 1977 |  |  |           gcc_assert (! is_sibcall);
 | 
      
         | 1978 |  |  |           emit_jump_insn (gen_exception_return ());
 | 
      
         | 1979 |  |  |         }
 | 
      
         | 1980 |  |  |       else if (! is_sibcall)
 | 
      
         | 1981 |  |  |         emit_jump_insn (gen_simple_return ());
 | 
      
         | 1982 |  |  |  
 | 
      
         | 1983 |  |  |       return;
 | 
      
         | 1984 |  |  |     }
 | 
      
         | 1985 |  |  |  
 | 
      
         | 1986 |  |  |   /* If we allocated space on the stack, free it now.  */
 | 
      
         | 1987 |  |  |   if (total_size)
 | 
      
         | 1988 |  |  |     {
 | 
      
         | 1989 |  |  |       unsigned HOST_WIDE_INT rtsd_size;
 | 
      
         | 1990 |  |  |  
 | 
      
         | 1991 |  |  |       /* See if we can use the RTSD instruction.  */
 | 
      
         | 1992 |  |  |       rtsd_size = total_size + regs_size;
 | 
      
         | 1993 |  |  |       if (rtsd_size < 1024 && (rtsd_size % 4) == 0)
 | 
      
         | 1994 |  |  |         {
 | 
      
         | 1995 |  |  |           if (low)
 | 
      
         | 1996 |  |  |             emit_jump_insn (gen_pop_and_return
 | 
      
         | 1997 |  |  |                             (GEN_INT (rtsd_size),
 | 
      
         | 1998 |  |  |                              gen_rx_rtsd_vector (rtsd_size, low, high)));
 | 
      
         | 1999 |  |  |           else
 | 
      
         | 2000 |  |  |             emit_jump_insn (gen_deallocate_and_return (GEN_INT (total_size)));
 | 
      
         | 2001 |  |  |  
 | 
      
         | 2002 |  |  |           return;
 | 
      
         | 2003 |  |  |         }
 | 
      
         | 2004 |  |  |  
 | 
      
         | 2005 |  |  |       gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
 | 
      
         | 2006 |  |  |                     GEN_INT (total_size), false);
 | 
      
         | 2007 |  |  |     }
 | 
      
         | 2008 |  |  |  
 | 
      
         | 2009 |  |  |   if (low)
 | 
      
         | 2010 |  |  |     emit_jump_insn (gen_pop_and_return (GEN_INT (regs_size),
 | 
      
         | 2011 |  |  |                                         gen_rx_rtsd_vector (regs_size,
 | 
      
         | 2012 |  |  |                                                             low, high)));
 | 
      
         | 2013 |  |  |   else
 | 
      
         | 2014 |  |  |     emit_jump_insn (gen_simple_return ());
 | 
      
         | 2015 |  |  | }
 | 
      
         | 2016 |  |  |  
 | 
      
         | 2017 |  |  |  
 | 
      
         | 2018 |  |  | /* Compute the offset (in words) between FROM (arg pointer
 | 
      
         | 2019 |  |  |    or frame pointer) and TO (frame pointer or stack pointer).
 | 
      
         | 2020 |  |  |    See ASCII art comment at the start of rx_expand_prologue
 | 
      
         | 2021 |  |  |    for more information.  */
 | 
      
         | 2022 |  |  |  
 | 
      
         | 2023 |  |  | int
 | 
      
         | 2024 |  |  | rx_initial_elimination_offset (int from, int to)
 | 
      
         | 2025 |  |  | {
 | 
      
         | 2026 |  |  |   unsigned int low;
 | 
      
         | 2027 |  |  |   unsigned int high;
 | 
      
         | 2028 |  |  |   unsigned int frame_size;
 | 
      
         | 2029 |  |  |   unsigned int stack_size;
 | 
      
         | 2030 |  |  |   unsigned int mask;
 | 
      
         | 2031 |  |  |  
 | 
      
         | 2032 |  |  |   rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
 | 
      
         | 2033 |  |  |  
 | 
      
         | 2034 |  |  |   if (from == ARG_POINTER_REGNUM)
 | 
      
         | 2035 |  |  |     {
 | 
      
         | 2036 |  |  |       /* Extend the computed size of the stack frame to
 | 
      
         | 2037 |  |  |          include the registers pushed in the prologue.  */
 | 
      
         | 2038 |  |  |       if (low)
 | 
      
         | 2039 |  |  |         frame_size += ((high - low) + 1) * UNITS_PER_WORD;
 | 
      
         | 2040 |  |  |       else
 | 
      
         | 2041 |  |  |         frame_size += bit_count (mask) * UNITS_PER_WORD;
 | 
      
         | 2042 |  |  |  
 | 
      
         | 2043 |  |  |       /* Remember to include the return address.  */
 | 
      
         | 2044 |  |  |       frame_size += 1 * UNITS_PER_WORD;
 | 
      
         | 2045 |  |  |  
 | 
      
         | 2046 |  |  |       if (to == FRAME_POINTER_REGNUM)
 | 
      
         | 2047 |  |  |         return frame_size;
 | 
      
         | 2048 |  |  |  
 | 
      
         | 2049 |  |  |       gcc_assert (to == STACK_POINTER_REGNUM);
 | 
      
         | 2050 |  |  |       return frame_size + stack_size;
 | 
      
         | 2051 |  |  |     }
 | 
      
         | 2052 |  |  |  
 | 
      
         | 2053 |  |  |   gcc_assert (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM);
 | 
      
         | 2054 |  |  |   return stack_size;
 | 
      
         | 2055 |  |  | }
 | 
      
         | 2056 |  |  |  
 | 
      
         | 2057 |  |  | /* Decide if a variable should go into one of the small data sections.  */
 | 
      
         | 2058 |  |  |  
 | 
      
         | 2059 |  |  | static bool
 | 
      
         | 2060 |  |  | rx_in_small_data (const_tree decl)
 | 
      
         | 2061 |  |  | {
 | 
      
         | 2062 |  |  |   int size;
 | 
      
         | 2063 |  |  |   const_tree section;
 | 
      
         | 2064 |  |  |  
 | 
      
         | 2065 |  |  |   if (rx_small_data_limit == 0)
 | 
      
         | 2066 |  |  |     return false;
 | 
      
         | 2067 |  |  |  
 | 
      
         | 2068 |  |  |   if (TREE_CODE (decl) != VAR_DECL)
 | 
      
         | 2069 |  |  |     return false;
 | 
      
         | 2070 |  |  |  
 | 
      
         | 2071 |  |  |   /* We do not put read-only variables into a small data area because
 | 
      
         | 2072 |  |  |      they would be placed with the other read-only sections, far away
 | 
      
         | 2073 |  |  |      from the read-write data sections, and we only have one small
 | 
      
         | 2074 |  |  |      data area pointer.
 | 
      
         | 2075 |  |  |      Similarly commons are placed in the .bss section which might be
 | 
      
         | 2076 |  |  |      far away (and out of alignment with respect to) the .data section.  */
 | 
      
         | 2077 |  |  |   if (TREE_READONLY (decl) || DECL_COMMON (decl))
 | 
      
         | 2078 |  |  |     return false;
 | 
      
         | 2079 |  |  |  
 | 
      
         | 2080 |  |  |   section = DECL_SECTION_NAME (decl);
 | 
      
         | 2081 |  |  |   if (section)
 | 
      
         | 2082 |  |  |     {
 | 
      
         | 2083 |  |  |       const char * const name = TREE_STRING_POINTER (section);
 | 
      
         | 2084 |  |  |  
 | 
      
         | 2085 |  |  |       return (strcmp (name, "D_2") == 0) || (strcmp (name, "B_2") == 0);
 | 
      
         | 2086 |  |  |     }
 | 
      
         | 2087 |  |  |  
 | 
      
         | 2088 |  |  |   size = int_size_in_bytes (TREE_TYPE (decl));
 | 
      
         | 2089 |  |  |  
 | 
      
         | 2090 |  |  |   return (size > 0) && (size <= rx_small_data_limit);
 | 
      
         | 2091 |  |  | }
 | 
      
         | 2092 |  |  |  
 | 
      
         | 2093 |  |  | /* Return a section for X.
 | 
      
         | 2094 |  |  |    The only special thing we do here is to honor small data.  */
 | 
      
         | 2095 |  |  |  
 | 
      
         | 2096 |  |  | static section *
 | 
      
         | 2097 |  |  | rx_select_rtx_section (enum machine_mode mode,
 | 
      
         | 2098 |  |  |                        rtx x,
 | 
      
         | 2099 |  |  |                        unsigned HOST_WIDE_INT align)
 | 
      
         | 2100 |  |  | {
 | 
      
         | 2101 |  |  |   if (rx_small_data_limit > 0
 | 
      
         | 2102 |  |  |       && GET_MODE_SIZE (mode) <= rx_small_data_limit
 | 
      
         | 2103 |  |  |       && align <= (unsigned HOST_WIDE_INT) rx_small_data_limit * BITS_PER_UNIT)
 | 
      
         | 2104 |  |  |     return sdata_section;
 | 
      
         | 2105 |  |  |  
 | 
      
         | 2106 |  |  |   return default_elf_select_rtx_section (mode, x, align);
 | 
      
         | 2107 |  |  | }
 | 
      
         | 2108 |  |  |  
 | 
      
         | 2109 |  |  | static section *
 | 
      
         | 2110 |  |  | rx_select_section (tree decl,
 | 
      
         | 2111 |  |  |                    int reloc,
 | 
      
         | 2112 |  |  |                    unsigned HOST_WIDE_INT align)
 | 
      
         | 2113 |  |  | {
 | 
      
         | 2114 |  |  |   if (rx_small_data_limit > 0)
 | 
      
         | 2115 |  |  |     {
 | 
      
         | 2116 |  |  |       switch (categorize_decl_for_section (decl, reloc))
 | 
      
         | 2117 |  |  |         {
 | 
      
         | 2118 |  |  |         case SECCAT_SDATA:      return sdata_section;
 | 
      
         | 2119 |  |  |         case SECCAT_SBSS:       return sbss_section;
 | 
      
         | 2120 |  |  |         case SECCAT_SRODATA:
 | 
      
         | 2121 |  |  |           /* Fall through.  We do not put small, read only
 | 
      
         | 2122 |  |  |              data into the C_2 section because we are not
 | 
      
         | 2123 |  |  |              using the C_2 section.  We do not use the C_2
 | 
      
         | 2124 |  |  |              section because it is located with the other
 | 
      
         | 2125 |  |  |              read-only data sections, far away from the read-write
 | 
      
         | 2126 |  |  |              data sections and we only have one small data
 | 
      
         | 2127 |  |  |              pointer (r13).  */
 | 
      
         | 2128 |  |  |         default:
 | 
      
         | 2129 |  |  |           break;
 | 
      
         | 2130 |  |  |         }
 | 
      
         | 2131 |  |  |     }
 | 
      
         | 2132 |  |  |  
 | 
      
         | 2133 |  |  |   /* If we are supporting the Renesas assembler
 | 
      
         | 2134 |  |  |      we cannot use mergeable sections.  */
 | 
      
         | 2135 |  |  |   if (TARGET_AS100_SYNTAX)
 | 
      
         | 2136 |  |  |     switch (categorize_decl_for_section (decl, reloc))
 | 
      
         | 2137 |  |  |       {
 | 
      
         | 2138 |  |  |       case SECCAT_RODATA_MERGE_CONST:
 | 
      
         | 2139 |  |  |       case SECCAT_RODATA_MERGE_STR_INIT:
 | 
      
         | 2140 |  |  |       case SECCAT_RODATA_MERGE_STR:
 | 
      
         | 2141 |  |  |         return readonly_data_section;
 | 
      
         | 2142 |  |  |  
 | 
      
         | 2143 |  |  |       default:
 | 
      
         | 2144 |  |  |         break;
 | 
      
         | 2145 |  |  |       }
 | 
      
         | 2146 |  |  |  
 | 
      
         | 2147 |  |  |   return default_elf_select_section (decl, reloc, align);
 | 
      
         | 2148 |  |  | }
 | 
      
         | 2149 |  |  |  
 | 
      
         | 2150 |  |  | enum rx_builtin
 | 
      
         | 2151 |  |  | {
 | 
      
         | 2152 |  |  |   RX_BUILTIN_BRK,
 | 
      
         | 2153 |  |  |   RX_BUILTIN_CLRPSW,
 | 
      
         | 2154 |  |  |   RX_BUILTIN_INT,
 | 
      
         | 2155 |  |  |   RX_BUILTIN_MACHI,
 | 
      
         | 2156 |  |  |   RX_BUILTIN_MACLO,
 | 
      
         | 2157 |  |  |   RX_BUILTIN_MULHI,
 | 
      
         | 2158 |  |  |   RX_BUILTIN_MULLO,
 | 
      
         | 2159 |  |  |   RX_BUILTIN_MVFACHI,
 | 
      
         | 2160 |  |  |   RX_BUILTIN_MVFACMI,
 | 
      
         | 2161 |  |  |   RX_BUILTIN_MVFC,
 | 
      
         | 2162 |  |  |   RX_BUILTIN_MVTACHI,
 | 
      
         | 2163 |  |  |   RX_BUILTIN_MVTACLO,
 | 
      
         | 2164 |  |  |   RX_BUILTIN_MVTC,
 | 
      
         | 2165 |  |  |   RX_BUILTIN_MVTIPL,
 | 
      
         | 2166 |  |  |   RX_BUILTIN_RACW,
 | 
      
         | 2167 |  |  |   RX_BUILTIN_REVW,
 | 
      
         | 2168 |  |  |   RX_BUILTIN_RMPA,
 | 
      
         | 2169 |  |  |   RX_BUILTIN_ROUND,
 | 
      
         | 2170 |  |  |   RX_BUILTIN_SETPSW,
 | 
      
         | 2171 |  |  |   RX_BUILTIN_WAIT,
 | 
      
         | 2172 |  |  |   RX_BUILTIN_max
 | 
      
         | 2173 |  |  | };
 | 
      
         | 2174 |  |  |  
 | 
      
         | 2175 |  |  | static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max];
 | 
      
         | 2176 |  |  |  
 | 
      
         | 2177 |  |  | static void
 | 
      
         | 2178 |  |  | rx_init_builtins (void)
 | 
      
         | 2179 |  |  | {
 | 
      
         | 2180 |  |  | #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE)           \
 | 
      
         | 2181 |  |  |    rx_builtins[RX_BUILTIN_##UC_NAME] =                                  \
 | 
      
         | 2182 |  |  |    add_builtin_function ("__builtin_rx_" LC_NAME,                       \
 | 
      
         | 2183 |  |  |                         build_function_type_list (RET_TYPE##_type_node, \
 | 
      
         | 2184 |  |  |                                                   ARG_TYPE##_type_node, \
 | 
      
         | 2185 |  |  |                                                   NULL_TREE),           \
 | 
      
         | 2186 |  |  |                         RX_BUILTIN_##UC_NAME,                           \
 | 
      
         | 2187 |  |  |                         BUILT_IN_MD, NULL, NULL_TREE)
 | 
      
         | 2188 |  |  |  
 | 
      
         | 2189 |  |  | #define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
 | 
      
         | 2190 |  |  |   rx_builtins[RX_BUILTIN_##UC_NAME] =                                   \
 | 
      
         | 2191 |  |  |   add_builtin_function ("__builtin_rx_" LC_NAME,                        \
 | 
      
         | 2192 |  |  |                         build_function_type_list (RET_TYPE##_type_node, \
 | 
      
         | 2193 |  |  |                                                   ARG_TYPE1##_type_node,\
 | 
      
         | 2194 |  |  |                                                   ARG_TYPE2##_type_node,\
 | 
      
         | 2195 |  |  |                                                   NULL_TREE),           \
 | 
      
         | 2196 |  |  |                         RX_BUILTIN_##UC_NAME,                           \
 | 
      
         | 2197 |  |  |                         BUILT_IN_MD, NULL, NULL_TREE)
 | 
      
         | 2198 |  |  |  
 | 
      
         | 2199 |  |  | #define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \
 | 
      
         | 2200 |  |  |   rx_builtins[RX_BUILTIN_##UC_NAME] =                                   \
 | 
      
         | 2201 |  |  |   add_builtin_function ("__builtin_rx_" LC_NAME,                        \
 | 
      
         | 2202 |  |  |                         build_function_type_list (RET_TYPE##_type_node, \
 | 
      
         | 2203 |  |  |                                                   ARG_TYPE1##_type_node,\
 | 
      
         | 2204 |  |  |                                                   ARG_TYPE2##_type_node,\
 | 
      
         | 2205 |  |  |                                                   ARG_TYPE3##_type_node,\
 | 
      
         | 2206 |  |  |                                                   NULL_TREE),           \
 | 
      
         | 2207 |  |  |                         RX_BUILTIN_##UC_NAME,                           \
 | 
      
         | 2208 |  |  |                         BUILT_IN_MD, NULL, NULL_TREE)
 | 
      
         | 2209 |  |  |  
 | 
      
         | 2210 |  |  |   ADD_RX_BUILTIN1 (BRK,     "brk",     void,  void);
 | 
      
         | 2211 |  |  |   ADD_RX_BUILTIN1 (CLRPSW,  "clrpsw",  void,  integer);
 | 
      
         | 2212 |  |  |   ADD_RX_BUILTIN1 (SETPSW,  "setpsw",  void,  integer);
 | 
      
         | 2213 |  |  |   ADD_RX_BUILTIN1 (INT,     "int",     void,  integer);
 | 
      
         | 2214 |  |  |   ADD_RX_BUILTIN2 (MACHI,   "machi",   void,  intSI, intSI);
 | 
      
         | 2215 |  |  |   ADD_RX_BUILTIN2 (MACLO,   "maclo",   void,  intSI, intSI);
 | 
      
         | 2216 |  |  |   ADD_RX_BUILTIN2 (MULHI,   "mulhi",   void,  intSI, intSI);
 | 
      
         | 2217 |  |  |   ADD_RX_BUILTIN2 (MULLO,   "mullo",   void,  intSI, intSI);
 | 
      
         | 2218 |  |  |   ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void);
 | 
      
         | 2219 |  |  |   ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void);
 | 
      
         | 2220 |  |  |   ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void,  intSI);
 | 
      
         | 2221 |  |  |   ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void,  intSI);
 | 
      
         | 2222 |  |  |   ADD_RX_BUILTIN1 (RMPA,    "rmpa",    void,  void);
 | 
      
         | 2223 |  |  |   ADD_RX_BUILTIN1 (MVFC,    "mvfc",    intSI, integer);
 | 
      
         | 2224 |  |  |   ADD_RX_BUILTIN2 (MVTC,    "mvtc",    void,  integer, integer);
 | 
      
         | 2225 |  |  |   ADD_RX_BUILTIN1 (MVTIPL,  "mvtipl",  void,  integer);
 | 
      
         | 2226 |  |  |   ADD_RX_BUILTIN1 (RACW,    "racw",    void,  integer);
 | 
      
         | 2227 |  |  |   ADD_RX_BUILTIN1 (ROUND,   "round",   intSI, float);
 | 
      
         | 2228 |  |  |   ADD_RX_BUILTIN1 (REVW,    "revw",    intSI, intSI);
 | 
      
         | 2229 |  |  |   ADD_RX_BUILTIN1 (WAIT,    "wait",    void,  void);
 | 
      
         | 2230 |  |  | }
 | 
      
         | 2231 |  |  |  
 | 
      
         | 2232 |  |  | /* Return the RX builtin for CODE.  */
 | 
      
         | 2233 |  |  |  
 | 
      
         | 2234 |  |  | static tree
 | 
      
         | 2235 |  |  | rx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
 | 
      
         | 2236 |  |  | {
 | 
      
         | 2237 |  |  |   if (code >= RX_BUILTIN_max)
 | 
      
         | 2238 |  |  |     return error_mark_node;
 | 
      
         | 2239 |  |  |  
 | 
      
         | 2240 |  |  |   return rx_builtins[code];
 | 
      
         | 2241 |  |  | }
 | 
      
         | 2242 |  |  |  
 | 
      
         | 2243 |  |  | static rtx
 | 
      
         | 2244 |  |  | rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
 | 
      
         | 2245 |  |  | {
 | 
      
         | 2246 |  |  |   if (reg && ! REG_P (arg))
 | 
      
         | 2247 |  |  |     arg = force_reg (SImode, arg);
 | 
      
         | 2248 |  |  |  
 | 
      
         | 2249 |  |  |   emit_insn (gen_func (arg));
 | 
      
         | 2250 |  |  |  
 | 
      
         | 2251 |  |  |   return NULL_RTX;
 | 
      
         | 2252 |  |  | }
 | 
      
         | 2253 |  |  |  
 | 
      
         | 2254 |  |  | static rtx
 | 
      
         | 2255 |  |  | rx_expand_builtin_mvtc (tree exp)
 | 
      
         | 2256 |  |  | {
 | 
      
         | 2257 |  |  |   rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
 | 
      
         | 2258 |  |  |   rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
 | 
      
         | 2259 |  |  |  
 | 
      
         | 2260 |  |  |   if (! CONST_INT_P (arg1))
 | 
      
         | 2261 |  |  |     return NULL_RTX;
 | 
      
         | 2262 |  |  |  
 | 
      
         | 2263 |  |  |   if (! REG_P (arg2))
 | 
      
         | 2264 |  |  |     arg2 = force_reg (SImode, arg2);
 | 
      
         | 2265 |  |  |  
 | 
      
         | 2266 |  |  |   emit_insn (gen_mvtc (arg1, arg2));
 | 
      
         | 2267 |  |  |  
 | 
      
         | 2268 |  |  |   return NULL_RTX;
 | 
      
         | 2269 |  |  | }
 | 
      
         | 2270 |  |  |  
 | 
      
         | 2271 |  |  | static rtx
 | 
      
         | 2272 |  |  | rx_expand_builtin_mvfc (tree t_arg, rtx target)
 | 
      
         | 2273 |  |  | {
 | 
      
         | 2274 |  |  |   rtx arg = expand_normal (t_arg);
 | 
      
         | 2275 |  |  |  
 | 
      
         | 2276 |  |  |   if (! CONST_INT_P (arg))
 | 
      
         | 2277 |  |  |     return NULL_RTX;
 | 
      
         | 2278 |  |  |  
 | 
      
         | 2279 |  |  |   if (target == NULL_RTX)
 | 
      
         | 2280 |  |  |     return NULL_RTX;
 | 
      
         | 2281 |  |  |  
 | 
      
         | 2282 |  |  |   if (! REG_P (target))
 | 
      
         | 2283 |  |  |     target = force_reg (SImode, target);
 | 
      
         | 2284 |  |  |  
 | 
      
         | 2285 |  |  |   emit_insn (gen_mvfc (target, arg));
 | 
      
         | 2286 |  |  |  
 | 
      
         | 2287 |  |  |   return target;
 | 
      
         | 2288 |  |  | }
 | 
      
         | 2289 |  |  |  
 | 
      
         | 2290 |  |  | static rtx
 | 
      
         | 2291 |  |  | rx_expand_builtin_mvtipl (rtx arg)
 | 
      
         | 2292 |  |  | {
 | 
      
         | 2293 |  |  |   /* The RX610 does not support the MVTIPL instruction.  */
 | 
      
         | 2294 |  |  |   if (rx_cpu_type == RX610)
 | 
      
         | 2295 |  |  |     return NULL_RTX;
 | 
      
         | 2296 |  |  |  
 | 
      
         | 2297 |  |  |   if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1))
 | 
      
         | 2298 |  |  |     return NULL_RTX;
 | 
      
         | 2299 |  |  |  
 | 
      
         | 2300 |  |  |   emit_insn (gen_mvtipl (arg));
 | 
      
         | 2301 |  |  |  
 | 
      
         | 2302 |  |  |   return NULL_RTX;
 | 
      
         | 2303 |  |  | }
 | 
      
         | 2304 |  |  |  
 | 
      
         | 2305 |  |  | static rtx
 | 
      
         | 2306 |  |  | rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
 | 
      
         | 2307 |  |  | {
 | 
      
         | 2308 |  |  |   rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
 | 
      
         | 2309 |  |  |   rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
 | 
      
         | 2310 |  |  |  
 | 
      
         | 2311 |  |  |   if (! REG_P (arg1))
 | 
      
         | 2312 |  |  |     arg1 = force_reg (SImode, arg1);
 | 
      
         | 2313 |  |  |  
 | 
      
         | 2314 |  |  |   if (! REG_P (arg2))
 | 
      
         | 2315 |  |  |     arg2 = force_reg (SImode, arg2);
 | 
      
         | 2316 |  |  |  
 | 
      
         | 2317 |  |  |   emit_insn (gen_func (arg1, arg2));
 | 
      
         | 2318 |  |  |  
 | 
      
         | 2319 |  |  |   return NULL_RTX;
 | 
      
         | 2320 |  |  | }
 | 
      
         | 2321 |  |  |  
 | 
      
         | 2322 |  |  | static rtx
 | 
      
         | 2323 |  |  | rx_expand_int_builtin_1_arg (rtx arg,
 | 
      
         | 2324 |  |  |                              rtx target,
 | 
      
         | 2325 |  |  |                              rtx (* gen_func)(rtx, rtx),
 | 
      
         | 2326 |  |  |                              bool mem_ok)
 | 
      
         | 2327 |  |  | {
 | 
      
         | 2328 |  |  |   if (! REG_P (arg))
 | 
      
         | 2329 |  |  |     if (!mem_ok || ! MEM_P (arg))
 | 
      
         | 2330 |  |  |       arg = force_reg (SImode, arg);
 | 
      
         | 2331 |  |  |  
 | 
      
         | 2332 |  |  |   if (target == NULL_RTX || ! REG_P (target))
 | 
      
         | 2333 |  |  |     target = gen_reg_rtx (SImode);
 | 
      
         | 2334 |  |  |  
 | 
      
         | 2335 |  |  |   emit_insn (gen_func (target, arg));
 | 
      
         | 2336 |  |  |  
 | 
      
         | 2337 |  |  |   return target;
 | 
      
         | 2338 |  |  | }
 | 
      
         | 2339 |  |  |  
 | 
      
         | 2340 |  |  | static rtx
 | 
      
         | 2341 |  |  | rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx))
 | 
      
         | 2342 |  |  | {
 | 
      
         | 2343 |  |  |   if (target == NULL_RTX || ! REG_P (target))
 | 
      
         | 2344 |  |  |     target = gen_reg_rtx (SImode);
 | 
      
         | 2345 |  |  |  
 | 
      
         | 2346 |  |  |   emit_insn (gen_func (target));
 | 
      
         | 2347 |  |  |  
 | 
      
         | 2348 |  |  |   return target;
 | 
      
         | 2349 |  |  | }
 | 
      
         | 2350 |  |  |  
 | 
      
         | 2351 |  |  | static rtx
 | 
      
         | 2352 |  |  | rx_expand_builtin_round (rtx arg, rtx target)
 | 
      
         | 2353 |  |  | {
 | 
      
         | 2354 |  |  |   if ((! REG_P (arg) && ! MEM_P (arg))
 | 
      
         | 2355 |  |  |       || GET_MODE (arg) != SFmode)
 | 
      
         | 2356 |  |  |     arg = force_reg (SFmode, arg);
 | 
      
         | 2357 |  |  |  
 | 
      
         | 2358 |  |  |   if (target == NULL_RTX || ! REG_P (target))
 | 
      
         | 2359 |  |  |     target = gen_reg_rtx (SImode);
 | 
      
         | 2360 |  |  |  
 | 
      
         | 2361 |  |  |   emit_insn (gen_lrintsf2 (target, arg));
 | 
      
         | 2362 |  |  |  
 | 
      
         | 2363 |  |  |   return target;
 | 
      
         | 2364 |  |  | }
 | 
      
         | 2365 |  |  |  
 | 
      
         | 2366 |  |  | static int
 | 
      
         | 2367 |  |  | valid_psw_flag (rtx op, const char *which)
 | 
      
         | 2368 |  |  | {
 | 
      
         | 2369 |  |  |   static int mvtc_inform_done = 0;
 | 
      
         | 2370 |  |  |  
 | 
      
         | 2371 |  |  |   if (GET_CODE (op) == CONST_INT)
 | 
      
         | 2372 |  |  |     switch (INTVAL (op))
 | 
      
         | 2373 |  |  |       {
 | 
      
         | 2374 |  |  |       case 0: case 'c': case 'C':
 | 
      
         | 2375 |  |  |       case 1: case 'z': case 'Z':
 | 
      
         | 2376 |  |  |       case 2: case 's': case 'S':
 | 
      
         | 2377 |  |  |       case 3: case 'o': case 'O':
 | 
      
         | 2378 |  |  |       case 8: case 'i': case 'I':
 | 
      
         | 2379 |  |  |       case 9: case 'u': case 'U':
 | 
      
         | 2380 |  |  |         return 1;
 | 
      
         | 2381 |  |  |       }
 | 
      
         | 2382 |  |  |  
 | 
      
         | 2383 |  |  |   error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which);
 | 
      
         | 2384 |  |  |   if (!mvtc_inform_done)
 | 
      
         | 2385 |  |  |     error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW");
 | 
      
         | 2386 |  |  |   mvtc_inform_done = 1;
 | 
      
         | 2387 |  |  |  
 | 
      
         | 2388 |  |  |   return 0;
 | 
      
         | 2389 |  |  | }
 | 
      
         | 2390 |  |  |  
 | 
      
         | 2391 |  |  | static rtx
 | 
      
         | 2392 |  |  | rx_expand_builtin (tree exp,
 | 
      
         | 2393 |  |  |                    rtx target,
 | 
      
         | 2394 |  |  |                    rtx subtarget ATTRIBUTE_UNUSED,
 | 
      
         | 2395 |  |  |                    enum machine_mode mode ATTRIBUTE_UNUSED,
 | 
      
         | 2396 |  |  |                    int ignore ATTRIBUTE_UNUSED)
 | 
      
         | 2397 |  |  | {
 | 
      
         | 2398 |  |  |   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
 | 
      
         | 2399 |  |  |   tree arg    = call_expr_nargs (exp) >= 1 ? CALL_EXPR_ARG (exp, 0) : NULL_TREE;
 | 
      
         | 2400 |  |  |   rtx  op     = arg ? expand_normal (arg) : NULL_RTX;
 | 
      
         | 2401 |  |  |   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
 | 
      
         | 2402 |  |  |  
 | 
      
         | 2403 |  |  |   switch (fcode)
 | 
      
         | 2404 |  |  |     {
 | 
      
         | 2405 |  |  |     case RX_BUILTIN_BRK:     emit_insn (gen_brk ()); return NULL_RTX;
 | 
      
         | 2406 |  |  |     case RX_BUILTIN_CLRPSW:
 | 
      
         | 2407 |  |  |       if (!valid_psw_flag (op, "clrpsw"))
 | 
      
         | 2408 |  |  |         return NULL_RTX;
 | 
      
         | 2409 |  |  |       return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false);
 | 
      
         | 2410 |  |  |     case RX_BUILTIN_SETPSW:
 | 
      
         | 2411 |  |  |       if (!valid_psw_flag (op, "setpsw"))
 | 
      
         | 2412 |  |  |         return NULL_RTX;
 | 
      
         | 2413 |  |  |       return rx_expand_void_builtin_1_arg (op, gen_setpsw, false);
 | 
      
         | 2414 |  |  |     case RX_BUILTIN_INT:     return rx_expand_void_builtin_1_arg
 | 
      
         | 2415 |  |  |         (op, gen_int, false);
 | 
      
         | 2416 |  |  |     case RX_BUILTIN_MACHI:   return rx_expand_builtin_mac (exp, gen_machi);
 | 
      
         | 2417 |  |  |     case RX_BUILTIN_MACLO:   return rx_expand_builtin_mac (exp, gen_maclo);
 | 
      
         | 2418 |  |  |     case RX_BUILTIN_MULHI:   return rx_expand_builtin_mac (exp, gen_mulhi);
 | 
      
         | 2419 |  |  |     case RX_BUILTIN_MULLO:   return rx_expand_builtin_mac (exp, gen_mullo);
 | 
      
         | 2420 |  |  |     case RX_BUILTIN_MVFACHI: return rx_expand_int_builtin_0_arg
 | 
      
         | 2421 |  |  |         (target, gen_mvfachi);
 | 
      
         | 2422 |  |  |     case RX_BUILTIN_MVFACMI: return rx_expand_int_builtin_0_arg
 | 
      
         | 2423 |  |  |         (target, gen_mvfacmi);
 | 
      
         | 2424 |  |  |     case RX_BUILTIN_MVTACHI: return rx_expand_void_builtin_1_arg
 | 
      
         | 2425 |  |  |         (op, gen_mvtachi, true);
 | 
      
         | 2426 |  |  |     case RX_BUILTIN_MVTACLO: return rx_expand_void_builtin_1_arg
 | 
      
         | 2427 |  |  |         (op, gen_mvtaclo, true);
 | 
      
         | 2428 |  |  |     case RX_BUILTIN_RMPA:    emit_insn (gen_rmpa ()); return NULL_RTX;
 | 
      
         | 2429 |  |  |     case RX_BUILTIN_MVFC:    return rx_expand_builtin_mvfc (arg, target);
 | 
      
         | 2430 |  |  |     case RX_BUILTIN_MVTC:    return rx_expand_builtin_mvtc (exp);
 | 
      
         | 2431 |  |  |     case RX_BUILTIN_MVTIPL:  return rx_expand_builtin_mvtipl (op);
 | 
      
         | 2432 |  |  |     case RX_BUILTIN_RACW:    return rx_expand_void_builtin_1_arg
 | 
      
         | 2433 |  |  |         (op, gen_racw, false);
 | 
      
         | 2434 |  |  |     case RX_BUILTIN_ROUND:   return rx_expand_builtin_round (op, target);
 | 
      
         | 2435 |  |  |     case RX_BUILTIN_REVW:    return rx_expand_int_builtin_1_arg
 | 
      
         | 2436 |  |  |         (op, target, gen_revw, false);
 | 
      
         | 2437 |  |  |     case RX_BUILTIN_WAIT:    emit_insn (gen_wait ()); return NULL_RTX;
 | 
      
         | 2438 |  |  |  
 | 
      
         | 2439 |  |  |     default:
 | 
      
         | 2440 |  |  |       internal_error ("bad builtin code");
 | 
      
         | 2441 |  |  |       break;
 | 
      
         | 2442 |  |  |     }
 | 
      
         | 2443 |  |  |  
 | 
      
         | 2444 |  |  |   return NULL_RTX;
 | 
      
         | 2445 |  |  | }
 | 
      
         | 2446 |  |  |  
 | 
      
         | 2447 |  |  | /* Place an element into a constructor or destructor section.
 | 
      
         | 2448 |  |  |    Like default_ctor_section_asm_out_constructor in varasm.c
 | 
      
         | 2449 |  |  |    except that it uses .init_array (or .fini_array) and it
 | 
      
         | 2450 |  |  |    handles constructor priorities.  */
 | 
      
         | 2451 |  |  |  
 | 
      
         | 2452 |  |  | static void
 | 
      
         | 2453 |  |  | rx_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
 | 
      
         | 2454 |  |  | {
 | 
      
         | 2455 |  |  |   section * s;
 | 
      
         | 2456 |  |  |  
 | 
      
         | 2457 |  |  |   if (priority != DEFAULT_INIT_PRIORITY)
 | 
      
         | 2458 |  |  |     {
 | 
      
         | 2459 |  |  |       char buf[18];
 | 
      
         | 2460 |  |  |  
 | 
      
         | 2461 |  |  |       sprintf (buf, "%s.%.5u",
 | 
      
         | 2462 |  |  |                is_ctor ? ".init_array" : ".fini_array",
 | 
      
         | 2463 |  |  |                priority);
 | 
      
         | 2464 |  |  |       s = get_section (buf, SECTION_WRITE, NULL_TREE);
 | 
      
         | 2465 |  |  |     }
 | 
      
         | 2466 |  |  |   else if (is_ctor)
 | 
      
         | 2467 |  |  |     s = ctors_section;
 | 
      
         | 2468 |  |  |   else
 | 
      
         | 2469 |  |  |     s = dtors_section;
 | 
      
         | 2470 |  |  |  
 | 
      
         | 2471 |  |  |   switch_to_section (s);
 | 
      
         | 2472 |  |  |   assemble_align (POINTER_SIZE);
 | 
      
         | 2473 |  |  |   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
 | 
      
         | 2474 |  |  | }
 | 
      
         | 2475 |  |  |  
 | 
      
         | 2476 |  |  | static void
 | 
      
         | 2477 |  |  | rx_elf_asm_constructor (rtx symbol, int priority)
 | 
      
         | 2478 |  |  | {
 | 
      
         | 2479 |  |  |   rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */true);
 | 
      
         | 2480 |  |  | }
 | 
      
         | 2481 |  |  |  
 | 
      
         | 2482 |  |  | static void
 | 
      
         | 2483 |  |  | rx_elf_asm_destructor (rtx symbol, int priority)
 | 
      
         | 2484 |  |  | {
 | 
      
         | 2485 |  |  |   rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */false);
 | 
      
         | 2486 |  |  | }
 | 
      
         | 2487 |  |  |  
 | 
      
         | 2488 |  |  | /* Check "fast_interrupt", "interrupt" and "naked" attributes.  */
 | 
      
         | 2489 |  |  |  
 | 
      
         | 2490 |  |  | static tree
 | 
      
         | 2491 |  |  | rx_handle_func_attribute (tree * node,
 | 
      
         | 2492 |  |  |                           tree   name,
 | 
      
         | 2493 |  |  |                           tree   args,
 | 
      
         | 2494 |  |  |                           int    flags ATTRIBUTE_UNUSED,
 | 
      
         | 2495 |  |  |                           bool * no_add_attrs)
 | 
      
         | 2496 |  |  | {
 | 
      
         | 2497 |  |  |   gcc_assert (DECL_P (* node));
 | 
      
         | 2498 |  |  |   gcc_assert (args == NULL_TREE);
 | 
      
         | 2499 |  |  |  
 | 
      
         | 2500 |  |  |   if (TREE_CODE (* node) != FUNCTION_DECL)
 | 
      
         | 2501 |  |  |     {
 | 
      
         | 2502 |  |  |       warning (OPT_Wattributes, "%qE attribute only applies to functions",
 | 
      
         | 2503 |  |  |                name);
 | 
      
         | 2504 |  |  |       * no_add_attrs = true;
 | 
      
         | 2505 |  |  |     }
 | 
      
         | 2506 |  |  |  
 | 
      
         | 2507 |  |  |   /* FIXME: We ought to check for conflicting attributes.  */
 | 
      
         | 2508 |  |  |  
 | 
      
         | 2509 |  |  |   /* FIXME: We ought to check that the interrupt and exception
 | 
      
         | 2510 |  |  |      handler attributes have been applied to void functions.  */
 | 
      
         | 2511 |  |  |   return NULL_TREE;
 | 
      
         | 2512 |  |  | }
 | 
      
         | 2513 |  |  |  
 | 
      
         | 2514 |  |  | /* Table of RX specific attributes.  */
 | 
      
         | 2515 |  |  | const struct attribute_spec rx_attribute_table[] =
 | 
      
         | 2516 |  |  | {
 | 
      
         | 2517 |  |  |   /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
 | 
      
         | 2518 |  |  |      affects_type_identity.  */
 | 
      
         | 2519 |  |  |   { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
 | 
      
         | 2520 |  |  |     false },
 | 
      
         | 2521 |  |  |   { "interrupt",      0, 0, true, false, false, rx_handle_func_attribute,
 | 
      
         | 2522 |  |  |     false },
 | 
      
         | 2523 |  |  |   { "naked",          0, 0, true, false, false, rx_handle_func_attribute,
 | 
      
         | 2524 |  |  |     false },
 | 
      
         | 2525 |  |  |   { NULL,             0, 0, false, false, false, NULL, false }
 | 
      
         | 2526 |  |  | };
 | 
      
         | 2527 |  |  |  
 | 
      
         | 2528 |  |  | /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
 | 
      
         | 2529 |  |  |  
 | 
      
         | 2530 |  |  | static void
 | 
      
         | 2531 |  |  | rx_override_options_after_change (void)
 | 
      
         | 2532 |  |  | {
 | 
      
         | 2533 |  |  |   static bool first_time = TRUE;
 | 
      
         | 2534 |  |  |  
 | 
      
         | 2535 |  |  |   if (first_time)
 | 
      
         | 2536 |  |  |     {
 | 
      
         | 2537 |  |  |       /* If this is the first time through and the user has not disabled
 | 
      
         | 2538 |  |  |          the use of RX FPU hardware then enable -ffinite-math-only,
 | 
      
         | 2539 |  |  |          since the FPU instructions do not support NaNs and infinities.  */
 | 
      
         | 2540 |  |  |       if (TARGET_USE_FPU)
 | 
      
         | 2541 |  |  |         flag_finite_math_only = 1;
 | 
      
         | 2542 |  |  |  
 | 
      
         | 2543 |  |  |       first_time = FALSE;
 | 
      
         | 2544 |  |  |     }
 | 
      
         | 2545 |  |  |   else
 | 
      
         | 2546 |  |  |     {
 | 
      
         | 2547 |  |  |       /* Alert the user if they are changing the optimization options
 | 
      
         | 2548 |  |  |          to use IEEE compliant floating point arithmetic with RX FPU insns.  */
 | 
      
         | 2549 |  |  |       if (TARGET_USE_FPU
 | 
      
         | 2550 |  |  |           && !flag_finite_math_only)
 | 
      
         | 2551 |  |  |         warning (0, "RX FPU instructions do not support NaNs and infinities");
 | 
      
         | 2552 |  |  |     }
 | 
      
         | 2553 |  |  | }
 | 
      
         | 2554 |  |  |  
 | 
      
         | 2555 |  |  | static void
 | 
      
         | 2556 |  |  | rx_option_override (void)
 | 
      
         | 2557 |  |  | {
 | 
      
         | 2558 |  |  |   unsigned int i;
 | 
      
         | 2559 |  |  |   cl_deferred_option *opt;
 | 
      
         | 2560 |  |  |   VEC(cl_deferred_option,heap) *vec
 | 
      
         | 2561 |  |  |     = (VEC(cl_deferred_option,heap) *) rx_deferred_options;
 | 
      
         | 2562 |  |  |  
 | 
      
         | 2563 |  |  |   FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
 | 
      
         | 2564 |  |  |     {
 | 
      
         | 2565 |  |  |       switch (opt->opt_index)
 | 
      
         | 2566 |  |  |         {
 | 
      
         | 2567 |  |  |         case OPT_mint_register_:
 | 
      
         | 2568 |  |  |           switch (opt->value)
 | 
      
         | 2569 |  |  |             {
 | 
      
         | 2570 |  |  |             case 4:
 | 
      
         | 2571 |  |  |               fixed_regs[10] = call_used_regs [10] = 1;
 | 
      
         | 2572 |  |  |               /* Fall through.  */
 | 
      
         | 2573 |  |  |             case 3:
 | 
      
         | 2574 |  |  |               fixed_regs[11] = call_used_regs [11] = 1;
 | 
      
         | 2575 |  |  |               /* Fall through.  */
 | 
      
         | 2576 |  |  |             case 2:
 | 
      
         | 2577 |  |  |               fixed_regs[12] = call_used_regs [12] = 1;
 | 
      
         | 2578 |  |  |               /* Fall through.  */
 | 
      
         | 2579 |  |  |             case 1:
 | 
      
         | 2580 |  |  |               fixed_regs[13] = call_used_regs [13] = 1;
 | 
      
         | 2581 |  |  |               /* Fall through.  */
 | 
      
         | 2582 |  |  |             case 0:
 | 
      
         | 2583 |  |  |               rx_num_interrupt_regs = opt->value;
 | 
      
         | 2584 |  |  |               break;
 | 
      
         | 2585 |  |  |             default:
 | 
      
         | 2586 |  |  |               rx_num_interrupt_regs = 0;
 | 
      
         | 2587 |  |  |               /* Error message already given because rx_handle_option
 | 
      
         | 2588 |  |  |                  returned false.  */
 | 
      
         | 2589 |  |  |               break;
 | 
      
         | 2590 |  |  |             }
 | 
      
         | 2591 |  |  |           break;
 | 
      
         | 2592 |  |  |  
 | 
      
         | 2593 |  |  |         default:
 | 
      
         | 2594 |  |  |           gcc_unreachable ();
 | 
      
         | 2595 |  |  |         }
 | 
      
         | 2596 |  |  |     }
 | 
      
         | 2597 |  |  |  
 | 
      
         | 2598 |  |  |   /* This target defaults to strict volatile bitfields.  */
 | 
      
         | 2599 |  |  |   if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
 | 
      
         | 2600 |  |  |     flag_strict_volatile_bitfields = 1;
 | 
      
         | 2601 |  |  |  
 | 
      
         | 2602 |  |  |   rx_override_options_after_change ();
 | 
      
         | 2603 |  |  |  
 | 
      
         | 2604 |  |  |   if (align_jumps == 0 && ! optimize_size)
 | 
      
         | 2605 |  |  |     align_jumps = 3;
 | 
      
         | 2606 |  |  |   if (align_loops == 0 && ! optimize_size)
 | 
      
         | 2607 |  |  |     align_loops = 3;
 | 
      
         | 2608 |  |  |   if (align_labels == 0 && ! optimize_size)
 | 
      
         | 2609 |  |  |     align_labels = 3;
 | 
      
         | 2610 |  |  | }
 | 
      
         | 2611 |  |  |  
 | 
      
         | 2612 |  |  |  
 | 
      
         | 2613 |  |  | static bool
 | 
      
         | 2614 |  |  | rx_allocate_stack_slots_for_args (void)
 | 
      
         | 2615 |  |  | {
 | 
      
         | 2616 |  |  |   /* Naked functions should not allocate stack slots for arguments.  */
 | 
      
         | 2617 |  |  |   return ! is_naked_func (NULL_TREE);
 | 
      
         | 2618 |  |  | }
 | 
      
         | 2619 |  |  |  
 | 
      
         | 2620 |  |  | static bool
 | 
      
         | 2621 |  |  | rx_func_attr_inlinable (const_tree decl)
 | 
      
         | 2622 |  |  | {
 | 
      
         | 2623 |  |  |   return ! is_fast_interrupt_func (decl)
 | 
      
         | 2624 |  |  |     &&   ! is_interrupt_func (decl)
 | 
      
         | 2625 |  |  |     &&   ! is_naked_func (decl);
 | 
      
         | 2626 |  |  | }
 | 
      
         | 2627 |  |  |  
 | 
      
         | 2628 |  |  | /* Return nonzero if it is ok to make a tail-call to DECL,
 | 
      
         | 2629 |  |  |    a function_decl or NULL if this is an indirect call, using EXP  */
 | 
      
         | 2630 |  |  |  
 | 
      
         | 2631 |  |  | static bool
 | 
      
         | 2632 |  |  | rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 | 
      
         | 2633 |  |  | {
 | 
      
         | 2634 |  |  |   /* Do not allow indirect tailcalls.  The
 | 
      
         | 2635 |  |  |      sibcall patterns do not support them.  */
 | 
      
         | 2636 |  |  |   if (decl == NULL)
 | 
      
         | 2637 |  |  |     return false;
 | 
      
         | 2638 |  |  |  
 | 
      
         | 2639 |  |  |   /* Never tailcall from inside interrupt handlers or naked functions.  */
 | 
      
         | 2640 |  |  |   if (is_fast_interrupt_func (NULL_TREE)
 | 
      
         | 2641 |  |  |       || is_interrupt_func (NULL_TREE)
 | 
      
         | 2642 |  |  |       || is_naked_func (NULL_TREE))
 | 
      
         | 2643 |  |  |     return false;
 | 
      
         | 2644 |  |  |  
 | 
      
         | 2645 |  |  |   return true;
 | 
      
         | 2646 |  |  | }
 | 
      
         | 2647 |  |  |  
 | 
      
         | 2648 |  |  | static void
 | 
      
         | 2649 |  |  | rx_file_start (void)
 | 
      
         | 2650 |  |  | {
 | 
      
         | 2651 |  |  |   if (! TARGET_AS100_SYNTAX)
 | 
      
         | 2652 |  |  |     default_file_start ();
 | 
      
         | 2653 |  |  | }
 | 
      
         | 2654 |  |  |  
 | 
      
         | 2655 |  |  | static bool
 | 
      
         | 2656 |  |  | rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
 | 
      
         | 2657 |  |  | {
 | 
      
         | 2658 |  |  |   /* The packed attribute overrides the MS behaviour.  */
 | 
      
         | 2659 |  |  |   return ! TYPE_PACKED (record_type);
 | 
      
         | 2660 |  |  | }
 | 
      
         | 2661 |  |  |  
 | 
      
         | 2662 |  |  | /* Returns true if X a legitimate constant for an immediate
 | 
      
         | 2663 |  |  |    operand on the RX.  X is already known to satisfy CONSTANT_P.  */
 | 
      
         | 2664 |  |  |  
 | 
      
         | 2665 |  |  | bool
 | 
      
         | 2666 |  |  | rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 | 
      
         | 2667 |  |  | {
 | 
      
         | 2668 |  |  |   switch (GET_CODE (x))
 | 
      
         | 2669 |  |  |     {
 | 
      
         | 2670 |  |  |     case CONST:
 | 
      
         | 2671 |  |  |       x = XEXP (x, 0);
 | 
      
         | 2672 |  |  |  
 | 
      
         | 2673 |  |  |       if (GET_CODE (x) == PLUS)
 | 
      
         | 2674 |  |  |         {
 | 
      
         | 2675 |  |  |           if (! CONST_INT_P (XEXP (x, 1)))
 | 
      
         | 2676 |  |  |             return false;
 | 
      
         | 2677 |  |  |  
 | 
      
         | 2678 |  |  |           /* GCC would not pass us CONST_INT + CONST_INT so we
 | 
      
         | 2679 |  |  |              know that we have {SYMBOL|LABEL} + CONST_INT.  */
 | 
      
         | 2680 |  |  |           x = XEXP (x, 0);
 | 
      
         | 2681 |  |  |           gcc_assert (! CONST_INT_P (x));
 | 
      
         | 2682 |  |  |         }
 | 
      
         | 2683 |  |  |  
 | 
      
         | 2684 |  |  |       switch (GET_CODE (x))
 | 
      
         | 2685 |  |  |         {
 | 
      
         | 2686 |  |  |         case LABEL_REF:
 | 
      
         | 2687 |  |  |         case SYMBOL_REF:
 | 
      
         | 2688 |  |  |           return true;
 | 
      
         | 2689 |  |  |  
 | 
      
         | 2690 |  |  |         case UNSPEC:
 | 
      
         | 2691 |  |  |           return XINT (x, 1) == UNSPEC_CONST || XINT (x, 1) == UNSPEC_PID_ADDR;
 | 
      
         | 2692 |  |  |  
 | 
      
         | 2693 |  |  |         default:
 | 
      
         | 2694 |  |  |           /* FIXME: Can this ever happen ?  */
 | 
      
         | 2695 |  |  |           gcc_unreachable ();
 | 
      
         | 2696 |  |  |         }
 | 
      
         | 2697 |  |  |       break;
 | 
      
         | 2698 |  |  |  
 | 
      
         | 2699 |  |  |     case LABEL_REF:
 | 
      
         | 2700 |  |  |     case SYMBOL_REF:
 | 
      
         | 2701 |  |  |       return true;
 | 
      
         | 2702 |  |  |     case CONST_DOUBLE:
 | 
      
         | 2703 |  |  |       return (rx_max_constant_size == 0 || rx_max_constant_size == 4);
 | 
      
         | 2704 |  |  |     case CONST_VECTOR:
 | 
      
         | 2705 |  |  |       return false;
 | 
      
         | 2706 |  |  |     default:
 | 
      
         | 2707 |  |  |       gcc_assert (CONST_INT_P (x));
 | 
      
         | 2708 |  |  |       break;
 | 
      
         | 2709 |  |  |     }
 | 
      
         | 2710 |  |  |  
 | 
      
         | 2711 |  |  |   return ok_for_max_constant (INTVAL (x));
 | 
      
         | 2712 |  |  | }
 | 
      
         | 2713 |  |  |  
 | 
      
         | 2714 |  |  | static int
 | 
      
         | 2715 |  |  | rx_address_cost (rtx addr, bool speed)
 | 
      
         | 2716 |  |  | {
 | 
      
         | 2717 |  |  |   rtx a, b;
 | 
      
         | 2718 |  |  |  
 | 
      
         | 2719 |  |  |   if (GET_CODE (addr) != PLUS)
 | 
      
         | 2720 |  |  |     return COSTS_N_INSNS (1);
 | 
      
         | 2721 |  |  |  
 | 
      
         | 2722 |  |  |   a = XEXP (addr, 0);
 | 
      
         | 2723 |  |  |   b = XEXP (addr, 1);
 | 
      
         | 2724 |  |  |  
 | 
      
         | 2725 |  |  |   if (REG_P (a) && REG_P (b))
 | 
      
         | 2726 |  |  |     /* Try to discourage REG+REG addressing as it keeps two registers live.  */
 | 
      
         | 2727 |  |  |     return COSTS_N_INSNS (4);
 | 
      
         | 2728 |  |  |  
 | 
      
         | 2729 |  |  |   if (speed)
 | 
      
         | 2730 |  |  |     /* [REG+OFF] is just as fast as [REG].  */
 | 
      
         | 2731 |  |  |     return COSTS_N_INSNS (1);
 | 
      
         | 2732 |  |  |  
 | 
      
         | 2733 |  |  |   if (CONST_INT_P (b)
 | 
      
         | 2734 |  |  |       && ((INTVAL (b) > 128) || INTVAL (b) < -127))
 | 
      
         | 2735 |  |  |     /* Try to discourage REG + <large OFF> when optimizing for size.  */
 | 
      
         | 2736 |  |  |     return COSTS_N_INSNS (2);
 | 
      
         | 2737 |  |  |  
 | 
      
         | 2738 |  |  |   return COSTS_N_INSNS (1);
 | 
      
         | 2739 |  |  | }
 | 
      
         | 2740 |  |  |  
 | 
      
         | 2741 |  |  | static bool
 | 
      
         | 2742 |  |  | rx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
 | 
      
         | 2743 |  |  | {
 | 
      
         | 2744 |  |  |   /* We can always eliminate to the frame pointer.
 | 
      
         | 2745 |  |  |      We can eliminate to the stack pointer unless a frame
 | 
      
         | 2746 |  |  |      pointer is needed.  */
 | 
      
         | 2747 |  |  |  
 | 
      
         | 2748 |  |  |   return to == FRAME_POINTER_REGNUM
 | 
      
         | 2749 |  |  |     || ( to == STACK_POINTER_REGNUM && ! frame_pointer_needed);
 | 
      
         | 2750 |  |  | }
 | 
      
         | 2751 |  |  |  
 | 
      
         | 2752 |  |  |  
 | 
      
         | 2753 |  |  | static void
 | 
      
         | 2754 |  |  | rx_trampoline_template (FILE * file)
 | 
      
         | 2755 |  |  | {
 | 
      
         | 2756 |  |  |   /* Output assembler code for a block containing the constant
 | 
      
         | 2757 |  |  |      part of a trampoline, leaving space for the variable parts.
 | 
      
         | 2758 |  |  |  
 | 
      
         | 2759 |  |  |      On the RX, (where r8 is the static chain regnum) the trampoline
 | 
      
         | 2760 |  |  |      looks like:
 | 
      
         | 2761 |  |  |  
 | 
      
         | 2762 |  |  |            mov          #<static chain value>, r8
 | 
      
         | 2763 |  |  |            mov          #<function's address>, r9
 | 
      
         | 2764 |  |  |            jmp          r9
 | 
      
         | 2765 |  |  |  
 | 
      
         | 2766 |  |  |      In big-endian-data-mode however instructions are read into the CPU
 | 
      
         | 2767 |  |  |      4 bytes at a time.  These bytes are then swapped around before being
 | 
      
         | 2768 |  |  |      passed to the decoder.  So...we must partition our trampoline into
 | 
      
         | 2769 |  |  |      4 byte packets and swap these packets around so that the instruction
 | 
      
         | 2770 |  |  |      reader will reverse the process.  But, in order to avoid splitting
 | 
      
         | 2771 |  |  |      the 32-bit constants across these packet boundaries, (making inserting
 | 
      
         | 2772 |  |  |      them into the constructed trampoline very difficult) we have to pad the
 | 
      
         | 2773 |  |  |      instruction sequence with NOP insns.  ie:
 | 
      
         | 2774 |  |  |  
 | 
      
         | 2775 |  |  |            nop
 | 
      
         | 2776 |  |  |            nop
 | 
      
         | 2777 |  |  |            mov.l        #<...>, r8
 | 
      
         | 2778 |  |  |            nop
 | 
      
         | 2779 |  |  |            nop
 | 
      
         | 2780 |  |  |            mov.l        #<...>, r9
 | 
      
         | 2781 |  |  |            jmp          r9
 | 
      
         | 2782 |  |  |            nop
 | 
      
         | 2783 |  |  |            nop             */
 | 
      
         | 2784 |  |  |  
 | 
      
         | 2785 |  |  |   if (! TARGET_BIG_ENDIAN_DATA)
 | 
      
         | 2786 |  |  |     {
 | 
      
         | 2787 |  |  |       asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", STATIC_CHAIN_REGNUM);
 | 
      
         | 2788 |  |  |       asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", TRAMPOLINE_TEMP_REGNUM);
 | 
      
         | 2789 |  |  |       asm_fprintf (file, "\tjmp\tr%d\n",                TRAMPOLINE_TEMP_REGNUM);
 | 
      
         | 2790 |  |  |     }
 | 
      
         | 2791 |  |  |   else
 | 
      
         | 2792 |  |  |     {
 | 
      
         | 2793 |  |  |       char r8 = '0' + STATIC_CHAIN_REGNUM;
 | 
      
         | 2794 |  |  |       char r9 = '0' + TRAMPOLINE_TEMP_REGNUM;
 | 
      
         | 2795 |  |  |  
 | 
      
         | 2796 |  |  |       if (TARGET_AS100_SYNTAX)
 | 
      
         | 2797 |  |  |         {
 | 
      
         | 2798 |  |  |           asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H,  003H\n", r8);
 | 
      
         | 2799 |  |  |           asm_fprintf (file, "\t.BYTE 0deH,  0adH, 0beH,  0efH\n");
 | 
      
         | 2800 |  |  |           asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H,  003H\n", r9);
 | 
      
         | 2801 |  |  |           asm_fprintf (file, "\t.BYTE 0deH,  0adH, 0beH,  0efH\n");
 | 
      
         | 2802 |  |  |           asm_fprintf (file, "\t.BYTE 003H,  003H, 00%cH, 07fH\n", r9);
 | 
      
         | 2803 |  |  |         }
 | 
      
         | 2804 |  |  |       else
 | 
      
         | 2805 |  |  |         {
 | 
      
         | 2806 |  |  |           asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03,  0x03\n", r8);
 | 
      
         | 2807 |  |  |           asm_fprintf (file, "\t.byte 0xde,  0xad, 0xbe,  0xef\n");
 | 
      
         | 2808 |  |  |           asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03,  0x03\n", r9);
 | 
      
         | 2809 |  |  |           asm_fprintf (file, "\t.byte 0xde,  0xad, 0xbe,  0xef\n");
 | 
      
         | 2810 |  |  |           asm_fprintf (file, "\t.byte 0x03,  0x03, 0x0%c, 0x7f\n", r9);
 | 
      
         | 2811 |  |  |         }
 | 
      
         | 2812 |  |  |     }
 | 
      
         | 2813 |  |  | }
 | 
      
         | 2814 |  |  |  
 | 
      
         | 2815 |  |  | static void
 | 
      
         | 2816 |  |  | rx_trampoline_init (rtx tramp, tree fndecl, rtx chain)
 | 
      
         | 2817 |  |  | {
 | 
      
         | 2818 |  |  |   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
 | 
      
         | 2819 |  |  |  
 | 
      
         | 2820 |  |  |   emit_block_move (tramp, assemble_trampoline_template (),
 | 
      
         | 2821 |  |  |                    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
 | 
      
         | 2822 |  |  |  
 | 
      
         | 2823 |  |  |   if (TARGET_BIG_ENDIAN_DATA)
 | 
      
         | 2824 |  |  |     {
 | 
      
         | 2825 |  |  |       emit_move_insn (adjust_address (tramp, SImode, 4), chain);
 | 
      
         | 2826 |  |  |       emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
 | 
      
         | 2827 |  |  |     }
 | 
      
         | 2828 |  |  |   else
 | 
      
         | 2829 |  |  |     {
 | 
      
         | 2830 |  |  |       emit_move_insn (adjust_address (tramp, SImode, 2), chain);
 | 
      
         | 2831 |  |  |       emit_move_insn (adjust_address (tramp, SImode, 6 + 2), fnaddr);
 | 
      
         | 2832 |  |  |     }
 | 
      
         | 2833 |  |  | }
 | 
      
         | 2834 |  |  |  
 | 
      
         | 2835 |  |  | static int
 | 
      
         | 2836 |  |  | rx_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
 | 
      
         | 2837 |  |  |                      reg_class_t regclass ATTRIBUTE_UNUSED,
 | 
      
         | 2838 |  |  |                      bool in)
 | 
      
         | 2839 |  |  | {
 | 
      
         | 2840 |  |  |   return (in ? 2 : 0) + REGISTER_MOVE_COST (mode, regclass, regclass);
 | 
      
         | 2841 |  |  | }
 | 
      
         | 2842 |  |  |  
 | 
      
         | 2843 |  |  | /* Convert a CC_MODE to the set of flags that it represents.  */
 | 
      
         | 2844 |  |  |  
 | 
      
         | 2845 |  |  | static unsigned int
 | 
      
         | 2846 |  |  | flags_from_mode (enum machine_mode mode)
 | 
      
         | 2847 |  |  | {
 | 
      
         | 2848 |  |  |   switch (mode)
 | 
      
         | 2849 |  |  |     {
 | 
      
         | 2850 |  |  |     case CC_ZSmode:
 | 
      
         | 2851 |  |  |       return CC_FLAG_S | CC_FLAG_Z;
 | 
      
         | 2852 |  |  |     case CC_ZSOmode:
 | 
      
         | 2853 |  |  |       return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O;
 | 
      
         | 2854 |  |  |     case CC_ZSCmode:
 | 
      
         | 2855 |  |  |       return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C;
 | 
      
         | 2856 |  |  |     case CCmode:
 | 
      
         | 2857 |  |  |       return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C;
 | 
      
         | 2858 |  |  |     case CC_Fmode:
 | 
      
         | 2859 |  |  |       return CC_FLAG_FP;
 | 
      
         | 2860 |  |  |     default:
 | 
      
         | 2861 |  |  |       gcc_unreachable ();
 | 
      
         | 2862 |  |  |     }
 | 
      
         | 2863 |  |  | }
 | 
      
         | 2864 |  |  |  
 | 
      
         | 2865 |  |  | /* Convert a set of flags to a CC_MODE that can implement it.  */
 | 
      
         | 2866 |  |  |  
 | 
      
         | 2867 |  |  | static enum machine_mode
 | 
      
         | 2868 |  |  | mode_from_flags (unsigned int f)
 | 
      
         | 2869 |  |  | {
 | 
      
         | 2870 |  |  |   if (f & CC_FLAG_FP)
 | 
      
         | 2871 |  |  |     return CC_Fmode;
 | 
      
         | 2872 |  |  |   if (f & CC_FLAG_O)
 | 
      
         | 2873 |  |  |     {
 | 
      
         | 2874 |  |  |       if (f & CC_FLAG_C)
 | 
      
         | 2875 |  |  |         return CCmode;
 | 
      
         | 2876 |  |  |       else
 | 
      
         | 2877 |  |  |         return CC_ZSOmode;
 | 
      
         | 2878 |  |  |     }
 | 
      
         | 2879 |  |  |   else if (f & CC_FLAG_C)
 | 
      
         | 2880 |  |  |     return CC_ZSCmode;
 | 
      
         | 2881 |  |  |   else
 | 
      
         | 2882 |  |  |     return CC_ZSmode;
 | 
      
         | 2883 |  |  | }
 | 
      
         | 2884 |  |  |  
 | 
      
         | 2885 |  |  | /* Convert an RTX_CODE to the set of flags needed to implement it.
 | 
      
         | 2886 |  |  |    This assumes an integer comparison.  */
 | 
      
         | 2887 |  |  |  
 | 
      
         | 2888 |  |  | static unsigned int
 | 
      
         | 2889 |  |  | flags_from_code (enum rtx_code code)
 | 
      
         | 2890 |  |  | {
 | 
      
         | 2891 |  |  |   switch (code)
 | 
      
         | 2892 |  |  |     {
 | 
      
         | 2893 |  |  |     case LT:
 | 
      
         | 2894 |  |  |     case GE:
 | 
      
         | 2895 |  |  |       return CC_FLAG_S;
 | 
      
         | 2896 |  |  |     case GT:
 | 
      
         | 2897 |  |  |     case LE:
 | 
      
         | 2898 |  |  |       return CC_FLAG_S | CC_FLAG_O | CC_FLAG_Z;
 | 
      
         | 2899 |  |  |     case GEU:
 | 
      
         | 2900 |  |  |     case LTU:
 | 
      
         | 2901 |  |  |       return CC_FLAG_C;
 | 
      
         | 2902 |  |  |     case GTU:
 | 
      
         | 2903 |  |  |     case LEU:
 | 
      
         | 2904 |  |  |       return CC_FLAG_C | CC_FLAG_Z;
 | 
      
         | 2905 |  |  |     case EQ:
 | 
      
         | 2906 |  |  |     case NE:
 | 
      
         | 2907 |  |  |       return CC_FLAG_Z;
 | 
      
         | 2908 |  |  |     default:
 | 
      
         | 2909 |  |  |       gcc_unreachable ();
 | 
      
         | 2910 |  |  |     }
 | 
      
         | 2911 |  |  | }
 | 
      
         | 2912 |  |  |  
 | 
      
         | 2913 |  |  | /* Return a CC_MODE of which both M1 and M2 are subsets.  */
 | 
      
         | 2914 |  |  |  
 | 
      
         | 2915 |  |  | static enum machine_mode
 | 
      
         | 2916 |  |  | rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
 | 
      
         | 2917 |  |  | {
 | 
      
         | 2918 |  |  |   unsigned f;
 | 
      
         | 2919 |  |  |  
 | 
      
         | 2920 |  |  |   /* Early out for identical modes.  */
 | 
      
         | 2921 |  |  |   if (m1 == m2)
 | 
      
         | 2922 |  |  |     return m1;
 | 
      
         | 2923 |  |  |  
 | 
      
         | 2924 |  |  |   /* There's no valid combination for FP vs non-FP.  */
 | 
      
         | 2925 |  |  |   f = flags_from_mode (m1) | flags_from_mode (m2);
 | 
      
         | 2926 |  |  |   if (f & CC_FLAG_FP)
 | 
      
         | 2927 |  |  |     return VOIDmode;
 | 
      
         | 2928 |  |  |  
 | 
      
         | 2929 |  |  |   /* Otherwise, see what mode can implement all the flags.  */
 | 
      
         | 2930 |  |  |   return mode_from_flags (f);
 | 
      
         | 2931 |  |  | }
 | 
      
         | 2932 |  |  |  
 | 
      
         | 2933 |  |  | /* Return the minimal CC mode needed to implement (CMP_CODE X Y).  */
 | 
      
         | 2934 |  |  |  
 | 
      
         | 2935 |  |  | enum machine_mode
 | 
      
         | 2936 |  |  | rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y)
 | 
      
         | 2937 |  |  | {
 | 
      
         | 2938 |  |  |   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
 | 
      
         | 2939 |  |  |     return CC_Fmode;
 | 
      
         | 2940 |  |  |  
 | 
      
         | 2941 |  |  |   if (y != const0_rtx)
 | 
      
         | 2942 |  |  |     return CCmode;
 | 
      
         | 2943 |  |  |  
 | 
      
         | 2944 |  |  |   return mode_from_flags (flags_from_code (cmp_code));
 | 
      
         | 2945 |  |  | }
 | 
      
         | 2946 |  |  |  
 | 
      
         | 2947 |  |  | /* Split the conditional branch.  Emit (COMPARE C1 C2) into CC_REG with
 | 
      
         | 2948 |  |  |    CC_MODE, and use that in branches based on that compare.  */
 | 
      
         | 2949 |  |  |  
 | 
      
         | 2950 |  |  | void
 | 
      
         | 2951 |  |  | rx_split_cbranch (enum machine_mode cc_mode, enum rtx_code cmp1,
 | 
      
         | 2952 |  |  |                   rtx c1, rtx c2, rtx label)
 | 
      
         | 2953 |  |  | {
 | 
      
         | 2954 |  |  |   rtx flags, x;
 | 
      
         | 2955 |  |  |  
 | 
      
         | 2956 |  |  |   flags = gen_rtx_REG (cc_mode, CC_REG);
 | 
      
         | 2957 |  |  |   x = gen_rtx_COMPARE (cc_mode, c1, c2);
 | 
      
         | 2958 |  |  |   x = gen_rtx_SET (VOIDmode, flags, x);
 | 
      
         | 2959 |  |  |   emit_insn (x);
 | 
      
         | 2960 |  |  |  
 | 
      
         | 2961 |  |  |   x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx);
 | 
      
         | 2962 |  |  |   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
 | 
      
         | 2963 |  |  |   x = gen_rtx_SET (VOIDmode, pc_rtx, x);
 | 
      
         | 2964 |  |  |   emit_jump_insn (x);
 | 
      
         | 2965 |  |  | }
 | 
      
         | 2966 |  |  |  
 | 
      
         | 2967 |  |  | /* A helper function for matching parallels that set the flags.  */
 | 
      
         | 2968 |  |  |  
 | 
      
         | 2969 |  |  | bool
 | 
      
         | 2970 |  |  | rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
 | 
      
         | 2971 |  |  | {
 | 
      
         | 2972 |  |  |   rtx op1, flags;
 | 
      
         | 2973 |  |  |   enum machine_mode flags_mode;
 | 
      
         | 2974 |  |  |  
 | 
      
         | 2975 |  |  |   gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
 | 
      
         | 2976 |  |  |  
 | 
      
         | 2977 |  |  |   op1 = XVECEXP (PATTERN (insn), 0, 1);
 | 
      
         | 2978 |  |  |   gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
 | 
      
         | 2979 |  |  |  
 | 
      
         | 2980 |  |  |   flags = SET_DEST (op1);
 | 
      
         | 2981 |  |  |   flags_mode = GET_MODE (flags);
 | 
      
         | 2982 |  |  |  
 | 
      
         | 2983 |  |  |   if (GET_MODE (SET_SRC (op1)) != flags_mode)
 | 
      
         | 2984 |  |  |     return false;
 | 
      
         | 2985 |  |  |   if (GET_MODE_CLASS (flags_mode) != MODE_CC)
 | 
      
         | 2986 |  |  |     return false;
 | 
      
         | 2987 |  |  |  
 | 
      
         | 2988 |  |  |   /* Ensure that the mode of FLAGS is compatible with CC_MODE.  */
 | 
      
         | 2989 |  |  |   if (flags_from_mode (flags_mode) & ~flags_from_mode (cc_mode))
 | 
      
         | 2990 |  |  |     return false;
 | 
      
         | 2991 |  |  |  
 | 
      
         | 2992 |  |  |   return true;
 | 
      
         | 2993 |  |  | }
 | 
      
         | 2994 |  |  |  
 | 
      
         | 2995 |  |  | int
 | 
      
         | 2996 |  |  | rx_align_for_label (rtx lab, int uses_threshold)
 | 
      
         | 2997 |  |  | {
 | 
      
         | 2998 |  |  |   /* This is a simple heuristic to guess when an alignment would not be useful
 | 
      
         | 2999 |  |  |      because the delay due to the inserted NOPs would be greater than the delay
 | 
      
         | 3000 |  |  |      due to the misaligned branch.  If uses_threshold is zero then the alignment
 | 
      
         | 3001 |  |  |      is always useful.  */
 | 
      
         | 3002 |  |  |   if (LABEL_P (lab) && LABEL_NUSES (lab) < uses_threshold)
 | 
      
         | 3003 |  |  |     return 0;
 | 
      
         | 3004 |  |  |  
 | 
      
         | 3005 |  |  |   return optimize_size ? 1 : 3;
 | 
      
         | 3006 |  |  | }
 | 
      
         | 3007 |  |  |  
 | 
      
         | 3008 |  |  | static int
 | 
      
         | 3009 |  |  | rx_max_skip_for_label (rtx lab)
 | 
      
         | 3010 |  |  | {
 | 
      
         | 3011 |  |  |   int opsize;
 | 
      
         | 3012 |  |  |   rtx op;
 | 
      
         | 3013 |  |  |  
 | 
      
         | 3014 |  |  |   if (lab == NULL_RTX)
 | 
      
         | 3015 |  |  |     return 0;
 | 
      
         | 3016 |  |  |  
 | 
      
         | 3017 |  |  |   op = lab;
 | 
      
         | 3018 |  |  |   do
 | 
      
         | 3019 |  |  |     {
 | 
      
         | 3020 |  |  |       op = next_nonnote_nondebug_insn (op);
 | 
      
         | 3021 |  |  |     }
 | 
      
         | 3022 |  |  |   while (op && (LABEL_P (op)
 | 
      
         | 3023 |  |  |                 || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE)));
 | 
      
         | 3024 |  |  |   if (!op)
 | 
      
         | 3025 |  |  |     return 0;
 | 
      
         | 3026 |  |  |  
 | 
      
         | 3027 |  |  |   opsize = get_attr_length (op);
 | 
      
         | 3028 |  |  |   if (opsize >= 0 && opsize < 8)
 | 
      
         | 3029 |  |  |     return opsize - 1;
 | 
      
         | 3030 |  |  |   return 0;
 | 
      
         | 3031 |  |  | }
 | 
      
         | 3032 |  |  |  
 | 
      
         | 3033 |  |  | /* Compute the real length of the extending load-and-op instructions.  */
 | 
      
         | 3034 |  |  |  
 | 
      
         | 3035 |  |  | int
 | 
      
         | 3036 |  |  | rx_adjust_insn_length (rtx insn, int current_length)
 | 
      
         | 3037 |  |  | {
 | 
      
         | 3038 |  |  |   rtx extend, mem, offset;
 | 
      
         | 3039 |  |  |   bool zero;
 | 
      
         | 3040 |  |  |   int factor;
 | 
      
         | 3041 |  |  |  
 | 
      
         | 3042 |  |  |   switch (INSN_CODE (insn))
 | 
      
         | 3043 |  |  |     {
 | 
      
         | 3044 |  |  |     default:
 | 
      
         | 3045 |  |  |       return current_length;
 | 
      
         | 3046 |  |  |  
 | 
      
         | 3047 |  |  |     case CODE_FOR_plussi3_zero_extendhi:
 | 
      
         | 3048 |  |  |     case CODE_FOR_andsi3_zero_extendhi:
 | 
      
         | 3049 |  |  |     case CODE_FOR_iorsi3_zero_extendhi:
 | 
      
         | 3050 |  |  |     case CODE_FOR_xorsi3_zero_extendhi:
 | 
      
         | 3051 |  |  |     case CODE_FOR_divsi3_zero_extendhi:
 | 
      
         | 3052 |  |  |     case CODE_FOR_udivsi3_zero_extendhi:
 | 
      
         | 3053 |  |  |     case CODE_FOR_minussi3_zero_extendhi:
 | 
      
         | 3054 |  |  |     case CODE_FOR_smaxsi3_zero_extendhi:
 | 
      
         | 3055 |  |  |     case CODE_FOR_sminsi3_zero_extendhi:
 | 
      
         | 3056 |  |  |     case CODE_FOR_multsi3_zero_extendhi:
 | 
      
         | 3057 |  |  |     case CODE_FOR_comparesi3_zero_extendhi:
 | 
      
         | 3058 |  |  |       zero = true;
 | 
      
         | 3059 |  |  |       factor = 2;
 | 
      
         | 3060 |  |  |       break;
 | 
      
         | 3061 |  |  |  
 | 
      
         | 3062 |  |  |     case CODE_FOR_plussi3_sign_extendhi:
 | 
      
         | 3063 |  |  |     case CODE_FOR_andsi3_sign_extendhi:
 | 
      
         | 3064 |  |  |     case CODE_FOR_iorsi3_sign_extendhi:
 | 
      
         | 3065 |  |  |     case CODE_FOR_xorsi3_sign_extendhi:
 | 
      
         | 3066 |  |  |     case CODE_FOR_divsi3_sign_extendhi:
 | 
      
         | 3067 |  |  |     case CODE_FOR_udivsi3_sign_extendhi:
 | 
      
         | 3068 |  |  |     case CODE_FOR_minussi3_sign_extendhi:
 | 
      
         | 3069 |  |  |     case CODE_FOR_smaxsi3_sign_extendhi:
 | 
      
         | 3070 |  |  |     case CODE_FOR_sminsi3_sign_extendhi:
 | 
      
         | 3071 |  |  |     case CODE_FOR_multsi3_sign_extendhi:
 | 
      
         | 3072 |  |  |     case CODE_FOR_comparesi3_sign_extendhi:
 | 
      
         | 3073 |  |  |       zero = false;
 | 
      
         | 3074 |  |  |       factor = 2;
 | 
      
         | 3075 |  |  |       break;
 | 
      
         | 3076 |  |  |  
 | 
      
         | 3077 |  |  |     case CODE_FOR_plussi3_zero_extendqi:
 | 
      
         | 3078 |  |  |     case CODE_FOR_andsi3_zero_extendqi:
 | 
      
         | 3079 |  |  |     case CODE_FOR_iorsi3_zero_extendqi:
 | 
      
         | 3080 |  |  |     case CODE_FOR_xorsi3_zero_extendqi:
 | 
      
         | 3081 |  |  |     case CODE_FOR_divsi3_zero_extendqi:
 | 
      
         | 3082 |  |  |     case CODE_FOR_udivsi3_zero_extendqi:
 | 
      
         | 3083 |  |  |     case CODE_FOR_minussi3_zero_extendqi:
 | 
      
         | 3084 |  |  |     case CODE_FOR_smaxsi3_zero_extendqi:
 | 
      
         | 3085 |  |  |     case CODE_FOR_sminsi3_zero_extendqi:
 | 
      
         | 3086 |  |  |     case CODE_FOR_multsi3_zero_extendqi:
 | 
      
         | 3087 |  |  |     case CODE_FOR_comparesi3_zero_extendqi:
 | 
      
         | 3088 |  |  |       zero = true;
 | 
      
         | 3089 |  |  |       factor = 1;
 | 
      
         | 3090 |  |  |       break;
 | 
      
         | 3091 |  |  |  
 | 
      
         | 3092 |  |  |     case CODE_FOR_plussi3_sign_extendqi:
 | 
      
         | 3093 |  |  |     case CODE_FOR_andsi3_sign_extendqi:
 | 
      
         | 3094 |  |  |     case CODE_FOR_iorsi3_sign_extendqi:
 | 
      
         | 3095 |  |  |     case CODE_FOR_xorsi3_sign_extendqi:
 | 
      
         | 3096 |  |  |     case CODE_FOR_divsi3_sign_extendqi:
 | 
      
         | 3097 |  |  |     case CODE_FOR_udivsi3_sign_extendqi:
 | 
      
         | 3098 |  |  |     case CODE_FOR_minussi3_sign_extendqi:
 | 
      
         | 3099 |  |  |     case CODE_FOR_smaxsi3_sign_extendqi:
 | 
      
         | 3100 |  |  |     case CODE_FOR_sminsi3_sign_extendqi:
 | 
      
         | 3101 |  |  |     case CODE_FOR_multsi3_sign_extendqi:
 | 
      
         | 3102 |  |  |     case CODE_FOR_comparesi3_sign_extendqi:
 | 
      
         | 3103 |  |  |       zero = false;
 | 
      
         | 3104 |  |  |       factor = 1;
 | 
      
         | 3105 |  |  |       break;
 | 
      
         | 3106 |  |  |     }
 | 
      
         | 3107 |  |  |  
 | 
      
         | 3108 |  |  |   /* We are expecting: (SET (REG) (<OP> (REG) (<EXTEND> (MEM)))).  */
 | 
      
         | 3109 |  |  |   extend = single_set (insn);
 | 
      
         | 3110 |  |  |   gcc_assert (extend != NULL_RTX);
 | 
      
         | 3111 |  |  |  
 | 
      
         | 3112 |  |  |   extend = SET_SRC (extend);
 | 
      
         | 3113 |  |  |   if (GET_CODE (XEXP (extend, 0)) == ZERO_EXTEND
 | 
      
         | 3114 |  |  |       || GET_CODE (XEXP (extend, 0)) == SIGN_EXTEND)
 | 
      
         | 3115 |  |  |     extend = XEXP (extend, 0);
 | 
      
         | 3116 |  |  |   else
 | 
      
         | 3117 |  |  |     extend = XEXP (extend, 1);
 | 
      
         | 3118 |  |  |  
 | 
      
         | 3119 |  |  |   gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND))
 | 
      
         | 3120 |  |  |               || (! zero && (GET_CODE (extend) == SIGN_EXTEND)));
 | 
      
         | 3121 |  |  |  
 | 
      
         | 3122 |  |  |   mem = XEXP (extend, 0);
 | 
      
         | 3123 |  |  |   gcc_checking_assert (MEM_P (mem));
 | 
      
         | 3124 |  |  |   if (REG_P (XEXP (mem, 0)))
 | 
      
         | 3125 |  |  |     return (zero && factor == 1) ? 2 : 3;
 | 
      
         | 3126 |  |  |  
 | 
      
         | 3127 |  |  |   /* We are expecting: (MEM (PLUS (REG) (CONST_INT))).  */
 | 
      
         | 3128 |  |  |   gcc_checking_assert (GET_CODE (XEXP (mem, 0)) == PLUS);
 | 
      
         | 3129 |  |  |   gcc_checking_assert (REG_P (XEXP (XEXP (mem, 0), 0)));
 | 
      
         | 3130 |  |  |  
 | 
      
         | 3131 |  |  |   offset = XEXP (XEXP (mem, 0), 1);
 | 
      
         | 3132 |  |  |   gcc_checking_assert (GET_CODE (offset) == CONST_INT);
 | 
      
         | 3133 |  |  |  
 | 
      
         | 3134 |  |  |   if (IN_RANGE (INTVAL (offset), 0, 255 * factor))
 | 
      
         | 3135 |  |  |     return (zero && factor == 1) ? 3 : 4;
 | 
      
         | 3136 |  |  |  
 | 
      
         | 3137 |  |  |   return (zero && factor == 1) ? 4 : 5;
 | 
      
         | 3138 |  |  | }
 | 
      
         | 3139 |  |  |  
 | 
      
         | 3140 |  |  | #undef  TARGET_ASM_JUMP_ALIGN_MAX_SKIP
 | 
      
         | 3141 |  |  | #define TARGET_ASM_JUMP_ALIGN_MAX_SKIP                  rx_max_skip_for_label
 | 
      
         | 3142 |  |  | #undef  TARGET_ASM_LOOP_ALIGN_MAX_SKIP
 | 
      
         | 3143 |  |  | #define TARGET_ASM_LOOP_ALIGN_MAX_SKIP                  rx_max_skip_for_label
 | 
      
         | 3144 |  |  | #undef  TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
 | 
      
         | 3145 |  |  | #define TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP       rx_max_skip_for_label
 | 
      
         | 3146 |  |  | #undef  TARGET_ASM_LABEL_ALIGN_MAX_SKIP
 | 
      
         | 3147 |  |  | #define TARGET_ASM_LABEL_ALIGN_MAX_SKIP                 rx_max_skip_for_label
 | 
      
         | 3148 |  |  |  
 | 
      
         | 3149 |  |  | #undef  TARGET_FUNCTION_VALUE
 | 
      
         | 3150 |  |  | #define TARGET_FUNCTION_VALUE           rx_function_value
 | 
      
         | 3151 |  |  |  
 | 
      
         | 3152 |  |  | #undef  TARGET_RETURN_IN_MSB
 | 
      
         | 3153 |  |  | #define TARGET_RETURN_IN_MSB            rx_return_in_msb
 | 
      
         | 3154 |  |  |  
 | 
      
         | 3155 |  |  | #undef  TARGET_IN_SMALL_DATA_P
 | 
      
         | 3156 |  |  | #define TARGET_IN_SMALL_DATA_P          rx_in_small_data
 | 
      
         | 3157 |  |  |  
 | 
      
         | 3158 |  |  | #undef  TARGET_RETURN_IN_MEMORY
 | 
      
         | 3159 |  |  | #define TARGET_RETURN_IN_MEMORY         rx_return_in_memory
 | 
      
         | 3160 |  |  |  
 | 
      
         | 3161 |  |  | #undef  TARGET_HAVE_SRODATA_SECTION
 | 
      
         | 3162 |  |  | #define TARGET_HAVE_SRODATA_SECTION     true
 | 
      
         | 3163 |  |  |  
 | 
      
         | 3164 |  |  | #undef  TARGET_ASM_SELECT_RTX_SECTION
 | 
      
         | 3165 |  |  | #define TARGET_ASM_SELECT_RTX_SECTION   rx_select_rtx_section
 | 
      
         | 3166 |  |  |  
 | 
      
         | 3167 |  |  | #undef  TARGET_ASM_SELECT_SECTION
 | 
      
         | 3168 |  |  | #define TARGET_ASM_SELECT_SECTION       rx_select_section
 | 
      
         | 3169 |  |  |  
 | 
      
         | 3170 |  |  | #undef  TARGET_INIT_BUILTINS
 | 
      
         | 3171 |  |  | #define TARGET_INIT_BUILTINS            rx_init_builtins
 | 
      
         | 3172 |  |  |  
 | 
      
         | 3173 |  |  | #undef  TARGET_BUILTIN_DECL
 | 
      
         | 3174 |  |  | #define TARGET_BUILTIN_DECL             rx_builtin_decl
 | 
      
         | 3175 |  |  |  
 | 
      
         | 3176 |  |  | #undef  TARGET_EXPAND_BUILTIN
 | 
      
         | 3177 |  |  | #define TARGET_EXPAND_BUILTIN           rx_expand_builtin
 | 
      
         | 3178 |  |  |  
 | 
      
         | 3179 |  |  | #undef  TARGET_ASM_CONSTRUCTOR
 | 
      
         | 3180 |  |  | #define TARGET_ASM_CONSTRUCTOR          rx_elf_asm_constructor
 | 
      
         | 3181 |  |  |  
 | 
      
         | 3182 |  |  | #undef  TARGET_ASM_DESTRUCTOR
 | 
      
         | 3183 |  |  | #define TARGET_ASM_DESTRUCTOR           rx_elf_asm_destructor
 | 
      
         | 3184 |  |  |  
 | 
      
         | 3185 |  |  | #undef  TARGET_STRUCT_VALUE_RTX
 | 
      
         | 3186 |  |  | #define TARGET_STRUCT_VALUE_RTX         rx_struct_value_rtx
 | 
      
         | 3187 |  |  |  
 | 
      
         | 3188 |  |  | #undef  TARGET_ATTRIBUTE_TABLE
 | 
      
         | 3189 |  |  | #define TARGET_ATTRIBUTE_TABLE          rx_attribute_table
 | 
      
         | 3190 |  |  |  
 | 
      
         | 3191 |  |  | #undef  TARGET_ASM_FILE_START
 | 
      
         | 3192 |  |  | #define TARGET_ASM_FILE_START                   rx_file_start
 | 
      
         | 3193 |  |  |  
 | 
      
         | 3194 |  |  | #undef  TARGET_MS_BITFIELD_LAYOUT_P
 | 
      
         | 3195 |  |  | #define TARGET_MS_BITFIELD_LAYOUT_P             rx_is_ms_bitfield_layout
 | 
      
         | 3196 |  |  |  
 | 
      
         | 3197 |  |  | #undef  TARGET_LEGITIMATE_ADDRESS_P
 | 
      
         | 3198 |  |  | #define TARGET_LEGITIMATE_ADDRESS_P             rx_is_legitimate_address
 | 
      
         | 3199 |  |  |  
 | 
      
         | 3200 |  |  | #undef  TARGET_MODE_DEPENDENT_ADDRESS_P
 | 
      
         | 3201 |  |  | #define TARGET_MODE_DEPENDENT_ADDRESS_P         rx_mode_dependent_address_p
 | 
      
         | 3202 |  |  |  
 | 
      
         | 3203 |  |  | #undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
 | 
      
         | 3204 |  |  | #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS    rx_allocate_stack_slots_for_args
 | 
      
         | 3205 |  |  |  
 | 
      
         | 3206 |  |  | #undef  TARGET_ASM_FUNCTION_PROLOGUE
 | 
      
         | 3207 |  |  | #define TARGET_ASM_FUNCTION_PROLOGUE            rx_output_function_prologue
 | 
      
         | 3208 |  |  |  
 | 
      
         | 3209 |  |  | #undef  TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
 | 
      
         | 3210 |  |  | #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P   rx_func_attr_inlinable
 | 
      
         | 3211 |  |  |  
 | 
      
         | 3212 |  |  | #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
 | 
      
         | 3213 |  |  | #define TARGET_FUNCTION_OK_FOR_SIBCALL          rx_function_ok_for_sibcall
 | 
      
         | 3214 |  |  |  
 | 
      
         | 3215 |  |  | #undef  TARGET_FUNCTION_ARG
 | 
      
         | 3216 |  |  | #define TARGET_FUNCTION_ARG                     rx_function_arg
 | 
      
         | 3217 |  |  |  
 | 
      
         | 3218 |  |  | #undef  TARGET_FUNCTION_ARG_ADVANCE
 | 
      
         | 3219 |  |  | #define TARGET_FUNCTION_ARG_ADVANCE             rx_function_arg_advance
 | 
      
         | 3220 |  |  |  
 | 
      
         | 3221 |  |  | #undef  TARGET_FUNCTION_ARG_BOUNDARY
 | 
      
         | 3222 |  |  | #define TARGET_FUNCTION_ARG_BOUNDARY            rx_function_arg_boundary
 | 
      
         | 3223 |  |  |  
 | 
      
         | 3224 |  |  | #undef  TARGET_SET_CURRENT_FUNCTION
 | 
      
         | 3225 |  |  | #define TARGET_SET_CURRENT_FUNCTION             rx_set_current_function
 | 
      
         | 3226 |  |  |  
 | 
      
         | 3227 |  |  | #undef  TARGET_ASM_INTEGER
 | 
      
         | 3228 |  |  | #define TARGET_ASM_INTEGER                      rx_assemble_integer
 | 
      
         | 3229 |  |  |  
 | 
      
         | 3230 |  |  | #undef  TARGET_USE_BLOCKS_FOR_CONSTANT_P
 | 
      
         | 3231 |  |  | #define TARGET_USE_BLOCKS_FOR_CONSTANT_P        hook_bool_mode_const_rtx_true
 | 
      
         | 3232 |  |  |  
 | 
      
         | 3233 |  |  | #undef  TARGET_MAX_ANCHOR_OFFSET
 | 
      
         | 3234 |  |  | #define TARGET_MAX_ANCHOR_OFFSET                32
 | 
      
         | 3235 |  |  |  
 | 
      
         | 3236 |  |  | #undef  TARGET_ADDRESS_COST
 | 
      
         | 3237 |  |  | #define TARGET_ADDRESS_COST                     rx_address_cost
 | 
      
         | 3238 |  |  |  
 | 
      
         | 3239 |  |  | #undef  TARGET_CAN_ELIMINATE
 | 
      
         | 3240 |  |  | #define TARGET_CAN_ELIMINATE                    rx_can_eliminate
 | 
      
         | 3241 |  |  |  
 | 
      
         | 3242 |  |  | #undef  TARGET_CONDITIONAL_REGISTER_USAGE
 | 
      
         | 3243 |  |  | #define TARGET_CONDITIONAL_REGISTER_USAGE       rx_conditional_register_usage
 | 
      
         | 3244 |  |  |  
 | 
      
         | 3245 |  |  | #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
 | 
      
         | 3246 |  |  | #define TARGET_ASM_TRAMPOLINE_TEMPLATE          rx_trampoline_template
 | 
      
         | 3247 |  |  |  
 | 
      
         | 3248 |  |  | #undef  TARGET_TRAMPOLINE_INIT
 | 
      
         | 3249 |  |  | #define TARGET_TRAMPOLINE_INIT                  rx_trampoline_init
 | 
      
         | 3250 |  |  |  
 | 
      
         | 3251 |  |  | #undef  TARGET_PRINT_OPERAND
 | 
      
         | 3252 |  |  | #define TARGET_PRINT_OPERAND                    rx_print_operand
 | 
      
         | 3253 |  |  |  
 | 
      
         | 3254 |  |  | #undef  TARGET_PRINT_OPERAND_ADDRESS
 | 
      
         | 3255 |  |  | #define TARGET_PRINT_OPERAND_ADDRESS            rx_print_operand_address
 | 
      
         | 3256 |  |  |  
 | 
      
         | 3257 |  |  | #undef  TARGET_CC_MODES_COMPATIBLE
 | 
      
         | 3258 |  |  | #define TARGET_CC_MODES_COMPATIBLE              rx_cc_modes_compatible
 | 
      
         | 3259 |  |  |  
 | 
      
         | 3260 |  |  | #undef  TARGET_MEMORY_MOVE_COST
 | 
      
         | 3261 |  |  | #define TARGET_MEMORY_MOVE_COST                 rx_memory_move_cost
 | 
      
         | 3262 |  |  |  
 | 
      
         | 3263 |  |  | #undef  TARGET_OPTION_OVERRIDE
 | 
      
         | 3264 |  |  | #define TARGET_OPTION_OVERRIDE                  rx_option_override
 | 
      
         | 3265 |  |  |  
 | 
      
         | 3266 |  |  | #undef  TARGET_PROMOTE_FUNCTION_MODE
 | 
      
         | 3267 |  |  | #define TARGET_PROMOTE_FUNCTION_MODE            rx_promote_function_mode
 | 
      
         | 3268 |  |  |  
 | 
      
         | 3269 |  |  | #undef  TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
 | 
      
         | 3270 |  |  | #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE    rx_override_options_after_change
 | 
      
         | 3271 |  |  |  
 | 
      
         | 3272 |  |  | #undef  TARGET_FLAGS_REGNUM
 | 
      
         | 3273 |  |  | #define TARGET_FLAGS_REGNUM                     CC_REG
 | 
      
         | 3274 |  |  |  
 | 
      
         | 3275 |  |  | #undef  TARGET_LEGITIMATE_CONSTANT_P
 | 
      
         | 3276 |  |  | #define TARGET_LEGITIMATE_CONSTANT_P            rx_is_legitimate_constant
 | 
      
         | 3277 |  |  |  
 | 
      
         | 3278 |  |  | #undef  TARGET_LEGITIMIZE_ADDRESS
 | 
      
         | 3279 |  |  | #define TARGET_LEGITIMIZE_ADDRESS               rx_legitimize_address
 | 
      
         | 3280 |  |  |  
 | 
      
         | 3281 |  |  | struct gcc_target targetm = TARGET_INITIALIZER;
 | 
      
         | 3282 |  |  |  
 | 
      
         | 3283 |  |  | #include "gt-rx.h"
 |