OSDN Git Service

5b4c5709b31079bbad6b9370d856323902fcf5ee
[pf3gnuchains/gcc-fork.git] / gcc / config / c4x / c4x.c
1 /* Subroutines for assembler code output on the TMS320C[34]x
2    Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3    Free Software Foundation, Inc.
4
5    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
6               and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
7
8 This file is part of GNU CC.
9
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING.  If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.  */
24
25 /* Some output-actions in c4x.md need these.  */
26 #include "config.h"
27 #include "system.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "basic-block.h"
33 #include "real.h"
34 #include "insn-config.h"
35 #include "insn-attr.h"
36 #include "conditions.h"
37 #include "output.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "optabs.h"
41 #include "libfuncs.h"
42 #include "flags.h"
43 #include "loop.h"
44 #include "recog.h"
45 #include "c-tree.h"
46 #include "ggc.h"
47 #include "cpplib.h"
48 #include "toplev.h"
49 #include "c4x-protos.h"
50 #include "target.h"
51 #include "target-def.h"
52
53 rtx smulhi3_libfunc;
54 rtx umulhi3_libfunc;
55 rtx fix_truncqfhi2_libfunc;
56 rtx fixuns_truncqfhi2_libfunc;
57 rtx fix_trunchfhi2_libfunc;
58 rtx fixuns_trunchfhi2_libfunc;
59 rtx floathiqf2_libfunc;
60 rtx floatunshiqf2_libfunc;
61 rtx floathihf2_libfunc;
62 rtx floatunshihf2_libfunc;
63
64 static int c4x_leaf_function;
65
66 static const char *const float_reg_names[] = FLOAT_REGISTER_NAMES;
67
68 /* Array of the smallest class containing reg number REGNO, indexed by
69    REGNO.  Used by REGNO_REG_CLASS in c4x.h.  We assume that all these
70    registers are available and set the class to NO_REGS for registers 
71    that the target switches say are unavailable.  */
72
73 enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] =
74 {
75                                 /* Reg          Modes           Saved.  */
76   R0R1_REGS,                    /* R0           QI, QF, HF      No.  */
77   R0R1_REGS,                    /* R1           QI, QF, HF      No.  */
78   R2R3_REGS,                    /* R2           QI, QF, HF      No.  */
79   R2R3_REGS,                    /* R3           QI, QF, HF      No.  */
80   EXT_LOW_REGS,                 /* R4           QI, QF, HF      QI.  */
81   EXT_LOW_REGS,                 /* R5           QI, QF, HF      QI.  */
82   EXT_LOW_REGS,                 /* R6           QI, QF, HF      QF.  */
83   EXT_LOW_REGS,                 /* R7           QI, QF, HF      QF.  */
84   ADDR_REGS,                    /* AR0          QI              No.  */
85   ADDR_REGS,                    /* AR1          QI              No.  */
86   ADDR_REGS,                    /* AR2          QI              No.  */
87   ADDR_REGS,                    /* AR3          QI              QI.  */
88   ADDR_REGS,                    /* AR4          QI              QI.  */
89   ADDR_REGS,                    /* AR5          QI              QI.  */
90   ADDR_REGS,                    /* AR6          QI              QI.  */
91   ADDR_REGS,                    /* AR7          QI              QI.  */
92   DP_REG,                       /* DP           QI              No.  */
93   INDEX_REGS,                   /* IR0          QI              No.  */
94   INDEX_REGS,                   /* IR1          QI              No.  */
95   BK_REG,                       /* BK           QI              QI.  */
96   SP_REG,                       /* SP           QI              No.  */
97   ST_REG,                       /* ST           CC              No.  */
98   NO_REGS,                      /* DIE/IE                       No.  */
99   NO_REGS,                      /* IIE/IF                       No.  */
100   NO_REGS,                      /* IIF/IOF                      No.  */
101   INT_REGS,                     /* RS           QI              No.  */
102   INT_REGS,                     /* RE           QI              No.  */
103   RC_REG,                       /* RC           QI              No.  */
104   EXT_REGS,                     /* R8           QI, QF, HF      QI.  */
105   EXT_REGS,                     /* R9           QI, QF, HF      No.  */
106   EXT_REGS,                     /* R10          QI, QF, HF      No.  */
107   EXT_REGS,                     /* R11          QI, QF, HF      No.  */
108 };
109
110 enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] =
111 {
112                                 /* Reg          Modes           Saved.  */
113   HFmode,                       /* R0           QI, QF, HF      No.  */
114   HFmode,                       /* R1           QI, QF, HF      No.  */
115   HFmode,                       /* R2           QI, QF, HF      No.  */
116   HFmode,                       /* R3           QI, QF, HF      No.  */
117   QFmode,                       /* R4           QI, QF, HF      QI.  */
118   QFmode,                       /* R5           QI, QF, HF      QI.  */
119   QImode,                       /* R6           QI, QF, HF      QF.  */
120   QImode,                       /* R7           QI, QF, HF      QF.  */
121   QImode,                       /* AR0          QI              No.  */
122   QImode,                       /* AR1          QI              No.  */
123   QImode,                       /* AR2          QI              No.  */
124   QImode,                       /* AR3          QI              QI.  */
125   QImode,                       /* AR4          QI              QI.  */
126   QImode,                       /* AR5          QI              QI.  */
127   QImode,                       /* AR6          QI              QI.  */
128   QImode,                       /* AR7          QI              QI.  */
129   VOIDmode,                     /* DP           QI              No.  */
130   QImode,                       /* IR0          QI              No.  */
131   QImode,                       /* IR1          QI              No.  */
132   QImode,                       /* BK           QI              QI.  */
133   VOIDmode,                     /* SP           QI              No.  */
134   VOIDmode,                     /* ST           CC              No.  */
135   VOIDmode,                     /* DIE/IE                       No.  */
136   VOIDmode,                     /* IIE/IF                       No.  */
137   VOIDmode,                     /* IIF/IOF                      No.  */
138   QImode,                       /* RS           QI              No.  */
139   QImode,                       /* RE           QI              No.  */
140   VOIDmode,                     /* RC           QI              No.  */
141   QFmode,                       /* R8           QI, QF, HF      QI.  */
142   HFmode,                       /* R9           QI, QF, HF      No.  */
143   HFmode,                       /* R10          QI, QF, HF      No.  */
144   HFmode,                       /* R11          QI, QF, HF      No.  */
145 };
146
147
148 /* Test and compare insns in c4x.md store the information needed to
149    generate branch and scc insns here.  */
150
151 rtx c4x_compare_op0;
152 rtx c4x_compare_op1;
153
154 const char *c4x_rpts_cycles_string;
155 int c4x_rpts_cycles = 0;        /* Max. cycles for RPTS.  */
156 const char *c4x_cpu_version_string;
157 int c4x_cpu_version = 40;       /* CPU version C30/31/32/33/40/44.  */
158
159 /* Pragma definitions.  */
160
161 tree code_tree = NULL_TREE;
162 tree data_tree = NULL_TREE;
163 tree pure_tree = NULL_TREE;
164 tree noreturn_tree = NULL_TREE;
165 tree interrupt_tree = NULL_TREE;
166
167 /* Forward declarations */
168 static int c4x_isr_reg_used_p PARAMS ((unsigned int));
169 static int c4x_leaf_function_p PARAMS ((void));
170 static int c4x_assembler_function_p PARAMS ((void));
171 static int c4x_immed_float_p PARAMS ((rtx));
172 static int c4x_a_register PARAMS ((rtx));
173 static int c4x_x_register PARAMS ((rtx));
174 static int c4x_immed_int_constant PARAMS ((rtx));
175 static int c4x_immed_float_constant PARAMS ((rtx));
176 static int c4x_K_constant PARAMS ((rtx));
177 static int c4x_N_constant PARAMS ((rtx));
178 static int c4x_O_constant PARAMS ((rtx));
179 static int c4x_R_indirect PARAMS ((rtx));
180 static int c4x_S_indirect PARAMS ((rtx));
181 static void c4x_S_address_parse PARAMS ((rtx , int *, int *, int *, int *));
182 static int c4x_valid_operands PARAMS ((enum rtx_code, rtx *,
183                                        enum machine_mode, int));
184 static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int));
185 static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));
186 static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));
187 static int c4x_r11_set_p PARAMS ((rtx));
188 static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
189 static int c4x_label_ref_used_p PARAMS ((rtx, rtx));
190 static tree c4x_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
191 const struct attribute_spec c4x_attribute_table[];
192 static void c4x_insert_attributes PARAMS ((tree, tree *));
193 static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
194 static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
195 static void c4x_encode_section_info PARAMS ((tree, int));
196 \f
197 /* Initialize the GCC target structure.  */
198 #undef TARGET_ASM_BYTE_OP
199 #define TARGET_ASM_BYTE_OP "\t.word\t"
200 #undef TARGET_ASM_ALIGNED_HI_OP
201 #define TARGET_ASM_ALIGNED_HI_OP NULL
202 #undef TARGET_ASM_ALIGNED_SI_OP
203 #define TARGET_ASM_ALIGNED_SI_OP NULL
204
205 #undef TARGET_ATTRIBUTE_TABLE
206 #define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
207
208 #undef TARGET_INSERT_ATTRIBUTES
209 #define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
210
211 #undef TARGET_INIT_BUILTINS
212 #define TARGET_INIT_BUILTINS c4x_init_builtins
213
214 #undef TARGET_EXPAND_BUILTIN
215 #define TARGET_EXPAND_BUILTIN c4x_expand_builtin
216
217 #undef TARGET_SCHED_ADJUST_COST
218 #define TARGET_SCHED_ADJUST_COST c4x_adjust_cost
219
220 #undef TARGET_ENCODE_SECTION_INFO
221 #define TARGET_ENCODE_SECTION_INFO c4x_encode_section_info
222
223 struct gcc_target targetm = TARGET_INITIALIZER;
224 \f
225 /* Override command line options.
226    Called once after all options have been parsed.
227    Mostly we process the processor
228    type and sometimes adjust other TARGET_ options.  */
229
230 void
231 c4x_override_options ()
232 {
233   if (c4x_rpts_cycles_string)
234     c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);
235   else
236     c4x_rpts_cycles = 0;
237
238   if (TARGET_C30)
239     c4x_cpu_version = 30;
240   else if (TARGET_C31)
241     c4x_cpu_version = 31;
242   else if (TARGET_C32)
243     c4x_cpu_version = 32;
244   else if (TARGET_C33)
245     c4x_cpu_version = 33;
246   else if (TARGET_C40)
247     c4x_cpu_version = 40;
248   else if (TARGET_C44)
249     c4x_cpu_version = 44;
250   else
251     c4x_cpu_version = 40;              
252
253   /* -mcpu=xx overrides -m40 etc.  */
254   if (c4x_cpu_version_string)
255     {
256       const char *p = c4x_cpu_version_string;
257       
258       /* Also allow -mcpu=c30 etc.  */
259       if (*p == 'c' || *p == 'C')
260         p++;
261       c4x_cpu_version = atoi (p);
262     }
263
264   target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG |
265                     C40_FLAG | C44_FLAG);
266
267   switch (c4x_cpu_version)
268     {
269     case 30: target_flags |= C30_FLAG; break;
270     case 31: target_flags |= C31_FLAG; break;
271     case 32: target_flags |= C32_FLAG; break;
272     case 33: target_flags |= C33_FLAG; break;
273     case 40: target_flags |= C40_FLAG; break;
274     case 44: target_flags |= C44_FLAG; break;
275     default:
276       warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version);
277       c4x_cpu_version = 40;
278       target_flags |= C40_FLAG;
279     }
280
281   if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33)
282     target_flags |= C3X_FLAG;
283   else
284     target_flags &= ~C3X_FLAG;
285
286   /* Convert foo / 8.0 into foo * 0.125, etc.  */
287   set_fast_math_flags (1);
288
289   /* We should phase out the following at some stage.
290      This provides compatibility with the old -mno-aliases option.  */
291   if (! TARGET_ALIASES && ! flag_argument_noalias)
292     flag_argument_noalias = 1;
293 }
294
295
296 /* This is called before c4x_override_options.  */
297
298 void
299 c4x_optimization_options (level, size)
300      int level ATTRIBUTE_UNUSED;
301      int size ATTRIBUTE_UNUSED;
302 {
303   /* Scheduling before register allocation can screw up global
304      register allocation, especially for functions that use MPY||ADD
305      instructions.  The benefit we gain we get by scheduling before
306      register allocation is probably marginal anyhow.  */
307   flag_schedule_insns = 0;
308 }
309
310
311 /* Write an ASCII string.  */
312
313 #define C4X_ASCII_LIMIT 40
314
315 void
316 c4x_output_ascii (stream, ptr, len)
317      FILE *stream;
318      const char *ptr;
319      int len;
320 {
321   char sbuf[C4X_ASCII_LIMIT + 1];
322   int s, l, special, first = 1, onlys;
323
324   if (len)
325       fprintf (stream, "\t.byte\t");
326
327   for (s = l = 0; len > 0; --len, ++ptr)
328     {
329       onlys = 0;
330
331       /* Escape " and \ with a \".  */
332       special = *ptr == '\"' || *ptr == '\\';
333
334       /* If printable - add to buff.  */
335       if ((! TARGET_TI || ! special) && *ptr >= 0x20 && *ptr < 0x7f)
336         {
337           if (special)
338             sbuf[s++] = '\\';
339           sbuf[s++] = *ptr;
340           if (s < C4X_ASCII_LIMIT - 1)
341             continue;
342           onlys = 1;
343         }
344       if (s)
345         {
346           if (first)
347             first = 0;
348           else
349             {
350               fputc (',', stream);
351               l++;
352             }
353
354           sbuf[s] = 0;
355           fprintf (stream, "\"%s\"", sbuf);
356           l += s + 2;
357           if (TARGET_TI && l >= 80 && len > 1)
358             {
359               fprintf (stream, "\n\t.byte\t");
360               first = 1;
361               l = 0;
362             }
363         
364           s = 0;
365         }
366       if (onlys)
367         continue;
368
369       if (first)
370         first = 0;
371       else
372         {
373           fputc (',', stream);
374           l++;
375         }
376
377       fprintf (stream, "%d", *ptr);
378       l += 3;
379       if (TARGET_TI && l >= 80 && len > 1)
380         {
381           fprintf (stream, "\n\t.byte\t");
382           first = 1;
383           l = 0;
384         }
385     }
386   if (s)
387     {
388       if (! first)
389         fputc (',', stream);
390
391       sbuf[s] = 0;
392       fprintf (stream, "\"%s\"", sbuf);
393       s = 0;
394     }
395   fputc ('\n', stream);
396 }
397
398
399 int
400 c4x_hard_regno_mode_ok (regno, mode)
401      unsigned int regno;
402      enum machine_mode mode;
403 {
404   switch (mode)
405     {
406 #if Pmode != QImode
407     case Pmode:                 /* Pointer (24/32 bits).  */
408 #endif
409     case QImode:                /* Integer (32 bits).  */
410       return IS_INT_REGNO (regno);
411
412     case QFmode:                /* Float, Double (32 bits).  */
413     case HFmode:                /* Long Double (40 bits).  */
414       return IS_EXT_REGNO (regno);
415
416     case CCmode:                /* Condition Codes.  */
417     case CC_NOOVmode:           /* Condition Codes.  */
418       return IS_ST_REGNO (regno);
419
420     case HImode:                /* Long Long (64 bits).  */
421       /* We need two registers to store long longs.  Note that 
422          it is much easier to constrain the first register
423          to start on an even boundary.  */
424       return IS_INT_REGNO (regno)
425         && IS_INT_REGNO (regno + 1)
426         && (regno & 1) == 0;
427
428     default:
429       return 0;                 /* We don't support these modes.  */
430     }
431
432   return 0;
433 }
434
435 /* Return non-zero if REGNO1 can be renamed to REGNO2.  */
436 int
437 c4x_hard_regno_rename_ok (regno1, regno2)
438      unsigned int regno1;
439      unsigned int regno2;
440 {
441   /* We can not copy call saved registers from mode QI into QF or from
442      mode QF into QI.  */
443   if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2))
444     return 0;
445   if (IS_INT_CALL_SAVED_REGNO (regno1) && IS_FLOAT_CALL_SAVED_REGNO (regno2))
446     return 0;
447   /* We cannot copy from an extended (40 bit) register to a standard
448      (32 bit) register because we only set the condition codes for
449      extended registers.  */
450   if (IS_EXT_REGNO (regno1) && ! IS_EXT_REGNO (regno2))
451     return 0;
452   if (IS_EXT_REGNO (regno2) && ! IS_EXT_REGNO (regno1))
453     return 0;
454   return 1;
455 }
456
457 /* The TI C3x C compiler register argument runtime model uses 6 registers,
458    AR2, R2, R3, RC, RS, RE.
459
460    The first two floating point arguments (float, double, long double)
461    that are found scanning from left to right are assigned to R2 and R3.
462
463    The remaining integer (char, short, int, long) or pointer arguments
464    are assigned to the remaining registers in the order AR2, R2, R3,
465    RC, RS, RE when scanning left to right, except for the last named
466    argument prior to an ellipsis denoting variable number of
467    arguments.  We don't have to worry about the latter condition since
468    function.c treats the last named argument as anonymous (unnamed).
469
470    All arguments that cannot be passed in registers are pushed onto
471    the stack in reverse order (right to left).  GCC handles that for us.
472
473    c4x_init_cumulative_args() is called at the start, so we can parse
474    the args to see how many floating point arguments and how many
475    integer (or pointer) arguments there are.  c4x_function_arg() is
476    then called (sometimes repeatedly) for each argument (parsed left
477    to right) to obtain the register to pass the argument in, or zero
478    if the argument is to be passed on the stack.  Once the compiler is
479    happy, c4x_function_arg_advance() is called.
480
481    Don't use R0 to pass arguments in, we use 0 to indicate a stack
482    argument.  */
483
484 static const int c4x_int_reglist[3][6] =
485 {
486   {AR2_REGNO, R2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO},
487   {AR2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0},
488   {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0}
489 };
490
491 static const int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
492
493
494 /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a
495    function whose data type is FNTYPE.
496    For a library call, FNTYPE is  0.  */
497
498 void
499 c4x_init_cumulative_args (cum, fntype, libname)
500      CUMULATIVE_ARGS *cum;      /* Argument info to initialize.  */
501      tree fntype;               /* Tree ptr for function decl.  */
502      rtx libname;               /* SYMBOL_REF of library name or 0.  */
503 {
504   tree param, next_param;
505
506   cum->floats = cum->ints = 0;
507   cum->init = 0;
508   cum->var = 0;
509   cum->args = 0;
510
511   if (TARGET_DEBUG)
512     {
513       fprintf (stderr, "\nc4x_init_cumulative_args (");
514       if (fntype)
515         {
516           tree ret_type = TREE_TYPE (fntype);
517
518           fprintf (stderr, "fntype code = %s, ret code = %s",
519                    tree_code_name[(int) TREE_CODE (fntype)],
520                    tree_code_name[(int) TREE_CODE (ret_type)]);
521         }
522       else
523         fprintf (stderr, "no fntype");
524
525       if (libname)
526         fprintf (stderr, ", libname = %s", XSTR (libname, 0));
527     }
528
529   cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
530
531   for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
532        param; param = next_param)
533     {
534       tree type;
535
536       next_param = TREE_CHAIN (param);
537
538       type = TREE_VALUE (param);
539       if (type && type != void_type_node)
540         {
541           enum machine_mode mode;
542
543           /* If the last arg doesn't have void type then we have
544              variable arguments.  */
545           if (! next_param)
546             cum->var = 1;
547
548           if ((mode = TYPE_MODE (type)))
549             {
550               if (! MUST_PASS_IN_STACK (mode, type))
551                 {
552                   /* Look for float, double, or long double argument.  */
553                   if (mode == QFmode || mode == HFmode)
554                     cum->floats++;
555                   /* Look for integer, enumeral, boolean, char, or pointer
556                      argument.  */
557                   else if (mode == QImode || mode == Pmode)
558                     cum->ints++;
559                 }
560             }
561           cum->args++;
562         }
563     }
564
565   if (TARGET_DEBUG)
566     fprintf (stderr, "%s%s, args = %d)\n",
567              cum->prototype ? ", prototype" : "",
568              cum->var ? ", variable args" : "",
569              cum->args);
570 }
571
572
573 /* Update the data in CUM to advance over an argument
574    of mode MODE and data type TYPE.
575    (TYPE is null for libcalls where that information may not be available.)  */
576
577 void
578 c4x_function_arg_advance (cum, mode, type, named)
579      CUMULATIVE_ARGS *cum;      /* Current arg information.  */
580      enum machine_mode mode;    /* Current arg mode.  */
581      tree type;                 /* Type of the arg or 0 if lib support.  */
582      int named;                 /* Whether or not the argument was named.  */
583 {
584   if (TARGET_DEBUG)
585     fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n",
586              GET_MODE_NAME (mode), named);
587   if (! TARGET_MEMPARM 
588       && named
589       && type
590       && ! MUST_PASS_IN_STACK (mode, type))
591     {
592       /* Look for float, double, or long double argument.  */
593       if (mode == QFmode || mode == HFmode)
594         cum->floats++;
595       /* Look for integer, enumeral, boolean, char, or pointer argument.  */
596       else if (mode == QImode || mode == Pmode)
597         cum->ints++;
598     }
599   else if (! TARGET_MEMPARM && ! type)
600     {
601       /* Handle libcall arguments.  */
602       if (mode == QFmode || mode == HFmode)
603         cum->floats++;
604       else if (mode == QImode || mode == Pmode)
605         cum->ints++;
606     }
607   return;
608 }
609
610
611 /* Define where to put the arguments to a function.  Value is zero to
612    push the argument on the stack, or a hard register in which to
613    store the argument.
614
615    MODE is the argument's machine mode.
616    TYPE is the data type of the argument (as a tree).
617    This is null for libcalls where that information may
618    not be available.
619    CUM is a variable of type CUMULATIVE_ARGS which gives info about
620    the preceding args and about the function being called.
621    NAMED is nonzero if this argument is a named parameter
622    (otherwise it is an extra parameter matching an ellipsis).  */
623
624 struct rtx_def *
625 c4x_function_arg (cum, mode, type, named)
626      CUMULATIVE_ARGS *cum;      /* Current arg information.  */
627      enum machine_mode mode;    /* Current arg mode.  */
628      tree type;                 /* Type of the arg or 0 if lib support.  */
629      int named;                 /* != 0 for normal args, == 0 for ... args.  */
630 {
631   int reg = 0;                  /* Default to passing argument on stack.  */
632
633   if (! cum->init)
634     {
635       /* We can handle at most 2 floats in R2, R3.  */
636       cum->maxfloats = (cum->floats > 2) ? 2 : cum->floats;
637
638       /* We can handle at most 6 integers minus number of floats passed 
639          in registers.  */
640       cum->maxints = (cum->ints > 6 - cum->maxfloats) ? 
641         6 - cum->maxfloats : cum->ints;
642
643       /* If there is no prototype, assume all the arguments are integers.  */
644       if (! cum->prototype)
645         cum->maxints = 6;
646
647       cum->ints = cum->floats = 0;
648       cum->init = 1;
649     }
650
651   /* This marks the last argument.  We don't need to pass this through
652      to the call insn.  */
653   if (type == void_type_node)
654     return 0;
655
656   if (! TARGET_MEMPARM 
657       && named 
658       && type
659       && ! MUST_PASS_IN_STACK (mode, type))
660     {
661       /* Look for float, double, or long double argument.  */
662       if (mode == QFmode || mode == HFmode)
663         {
664           if (cum->floats < cum->maxfloats)
665             reg = c4x_fp_reglist[cum->floats];
666         }
667       /* Look for integer, enumeral, boolean, char, or pointer argument.  */
668       else if (mode == QImode || mode == Pmode)
669         {
670           if (cum->ints < cum->maxints)
671             reg = c4x_int_reglist[cum->maxfloats][cum->ints];
672         }
673     }
674   else if (! TARGET_MEMPARM && ! type)
675     {
676       /* We could use a different argument calling model for libcalls,
677          since we're only calling functions in libgcc.  Thus we could
678          pass arguments for long longs in registers rather than on the
679          stack.  In the meantime, use the odd TI format.  We make the
680          assumption that we won't have more than two floating point
681          args, six integer args, and that all the arguments are of the
682          same mode.  */
683       if (mode == QFmode || mode == HFmode)
684         reg = c4x_fp_reglist[cum->floats];
685       else if (mode == QImode || mode == Pmode)
686         reg = c4x_int_reglist[0][cum->ints];
687     }
688
689   if (TARGET_DEBUG)
690     {
691       fprintf (stderr, "c4x_function_arg(mode=%s, named=%d",
692                GET_MODE_NAME (mode), named);
693       if (reg)
694         fprintf (stderr, ", reg=%s", reg_names[reg]);
695       else
696         fprintf (stderr, ", stack");
697       fprintf (stderr, ")\n");
698     }
699   if (reg)
700     return gen_rtx_REG (mode, reg);
701   else
702     return NULL_RTX;
703 }
704
705 /* C[34]x arguments grow in weird ways (downwards) that the standard
706    varargs stuff can't handle..  */
707 rtx
708 c4x_va_arg (valist, type)
709      tree valist, type;
710 {
711   tree t;
712
713   t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
714              build_int_2 (int_size_in_bytes (type), 0));
715   TREE_SIDE_EFFECTS (t) = 1;
716
717   return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
718 }
719
720
721 static int
722 c4x_isr_reg_used_p (regno)
723      unsigned int regno;
724 {
725   /* Don't save/restore FP or ST, we handle them separately.  */
726   if (regno == FRAME_POINTER_REGNUM
727       || IS_ST_REGNO (regno))
728     return 0;
729
730   /* We could be a little smarter abut saving/restoring DP.
731      We'll only save if for the big memory model or if
732      we're paranoid. ;-)  */
733   if (IS_DP_REGNO (regno))
734     return ! TARGET_SMALL || TARGET_PARANOID;
735
736   /* Only save/restore regs in leaf function that are used.  */
737   if (c4x_leaf_function)
738     return regs_ever_live[regno] && fixed_regs[regno] == 0;
739
740   /* Only save/restore regs that are used by the ISR and regs
741      that are likely to be used by functions the ISR calls
742      if they are not fixed.  */
743   return IS_EXT_REGNO (regno)
744     || ((regs_ever_live[regno] || call_used_regs[regno]) 
745         && fixed_regs[regno] == 0);
746 }
747
748
749 static int
750 c4x_leaf_function_p ()
751 {
752   /* A leaf function makes no calls, so we only need
753      to save/restore the registers we actually use.
754      For the global variable leaf_function to be set, we need
755      to define LEAF_REGISTERS and all that it entails.
756      Let's check ourselves...   */
757
758   if (lookup_attribute ("leaf_pretend",
759                         TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
760     return 1;
761
762   /* Use the leaf_pretend attribute at your own risk.  This is a hack
763      to speed up ISRs that call a function infrequently where the
764      overhead of saving and restoring the additional registers is not
765      warranted.  You must save and restore the additional registers
766      required by the called function.  Caveat emptor.  Here's enough
767      rope...  */
768
769   if (leaf_function_p ())
770     return 1;
771
772   return 0;
773 }
774
775
776 static int
777 c4x_assembler_function_p ()
778 {
779   tree type;
780
781   type = TREE_TYPE (current_function_decl);
782   return (lookup_attribute ("assembler", TYPE_ATTRIBUTES (type)) != NULL)
783     || (lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL);
784 }
785
786
787 int
788 c4x_interrupt_function_p ()
789 {
790   if (lookup_attribute ("interrupt",
791                         TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
792     return 1;
793
794   /* Look for TI style c_intnn.  */
795   return current_function_name[0] == 'c'
796     && current_function_name[1] == '_'
797     && current_function_name[2] == 'i'
798     && current_function_name[3] == 'n' 
799     && current_function_name[4] == 't'
800     && ISDIGIT (current_function_name[5])
801     && ISDIGIT (current_function_name[6]);
802 }
803
804 void
805 c4x_expand_prologue ()
806 {
807   unsigned int regno;
808   int size = get_frame_size ();
809   rtx insn;
810
811   /* In functions where ar3 is not used but frame pointers are still
812      specified, frame pointers are not adjusted (if >= -O2) and this
813      is used so it won't needlessly push the frame pointer.  */
814   int dont_push_ar3;
815
816   /* For __assembler__ function don't build a prologue.  */
817   if (c4x_assembler_function_p ())
818     {
819       return;
820     }
821   
822   /* For __interrupt__ function build specific prologue.  */
823   if (c4x_interrupt_function_p ())
824     {
825       c4x_leaf_function = c4x_leaf_function_p ();
826       
827       insn = emit_insn (gen_push_st ());
828       RTX_FRAME_RELATED_P (insn) = 1;
829       if (size)
830         {
831           insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
832           RTX_FRAME_RELATED_P (insn) = 1;
833           insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
834                                        gen_rtx_REG (QImode, SP_REGNO)));
835           RTX_FRAME_RELATED_P (insn) = 1;
836           /* We require that an ISR uses fewer than 32768 words of
837              local variables, otherwise we have to go to lots of
838              effort to save a register, load it with the desired size,
839              adjust the stack pointer, and then restore the modified
840              register.  Frankly, I think it is a poor ISR that
841              requires more than 32767 words of local temporary
842              storage!  */
843           if (size > 32767)
844             error ("ISR %s requires %d words of local vars, max is 32767",
845                    current_function_name, size);
846
847           insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
848                                         gen_rtx_REG (QImode, SP_REGNO),
849                                         GEN_INT (size)));
850           RTX_FRAME_RELATED_P (insn) = 1;
851         }
852       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
853         {
854           if (c4x_isr_reg_used_p (regno))
855             {
856               if (regno == DP_REGNO)
857                 {
858                   insn = emit_insn (gen_push_dp ());
859                   RTX_FRAME_RELATED_P (insn) = 1;
860                 }
861               else
862                 {
863                   insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno)));
864                   RTX_FRAME_RELATED_P (insn) = 1;
865                   if (IS_EXT_REGNO (regno))
866                     {
867                       insn = emit_insn (gen_pushqf
868                                         (gen_rtx_REG (QFmode, regno)));
869                       RTX_FRAME_RELATED_P (insn) = 1;
870                     }
871                 }
872             }
873         }
874       /* We need to clear the repeat mode flag if the ISR is
875          going to use a RPTB instruction or uses the RC, RS, or RE
876          registers.  */
877       if (regs_ever_live[RC_REGNO] 
878           || regs_ever_live[RS_REGNO] 
879           || regs_ever_live[RE_REGNO])
880         {
881           insn = emit_insn (gen_andn_st (GEN_INT(~0x100)));
882           RTX_FRAME_RELATED_P (insn) = 1;
883         }
884
885       /* Reload DP reg if we are paranoid about some turkey
886          violating small memory model rules.  */
887       if (TARGET_SMALL && TARGET_PARANOID)
888         {
889           insn = emit_insn (gen_set_ldp_prologue
890                             (gen_rtx_REG (QImode, DP_REGNO),
891                              gen_rtx_SYMBOL_REF (QImode, "data_sec")));
892           RTX_FRAME_RELATED_P (insn) = 1;
893         }
894     }
895   else
896     {
897       if (frame_pointer_needed)
898         {
899           if ((size != 0)
900               || (current_function_args_size != 0)
901               || (optimize < 2))
902             {
903               insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
904               RTX_FRAME_RELATED_P (insn) = 1;
905               insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
906                                            gen_rtx_REG (QImode, SP_REGNO)));
907               RTX_FRAME_RELATED_P (insn) = 1;
908               dont_push_ar3 = 1;
909             }
910           else
911             {
912               /* Since ar3 is not used, we don't need to push it.  */
913               dont_push_ar3 = 1;
914             }
915         }
916       else
917         {
918           /* If we use ar3, we need to push it.   */
919           dont_push_ar3 = 0;
920           if ((size != 0) || (current_function_args_size != 0))
921             {
922               /* If we are omitting the frame pointer, we still have
923                  to make space for it so the offsets are correct
924                  unless we don't use anything on the stack at all.  */
925               size += 1;
926             }
927         }
928       
929       if (size > 32767)
930         {
931           /* Local vars are too big, it will take multiple operations
932              to increment SP.  */
933           if (TARGET_C3X)
934             {
935               insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
936                                            GEN_INT(size >> 16)));
937               RTX_FRAME_RELATED_P (insn) = 1;
938               insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R1_REGNO),
939                                              gen_rtx_REG (QImode, R1_REGNO),
940                                              GEN_INT(-16)));
941               RTX_FRAME_RELATED_P (insn) = 1;
942             }
943           else
944             {
945               insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
946                                            GEN_INT(size & ~0xffff)));
947               RTX_FRAME_RELATED_P (insn) = 1;
948             }
949           insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R1_REGNO),
950                                         gen_rtx_REG (QImode, R1_REGNO),
951                                         GEN_INT(size & 0xffff)));
952           RTX_FRAME_RELATED_P (insn) = 1;
953           insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
954                                         gen_rtx_REG (QImode, SP_REGNO),
955                                         gen_rtx_REG (QImode, R1_REGNO)));
956           RTX_FRAME_RELATED_P (insn) = 1;
957         }
958       else if (size != 0)
959         {
960           /* Local vars take up less than 32767 words, so we can directly
961              add the number.  */
962           insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
963                                         gen_rtx_REG (QImode, SP_REGNO),
964                                         GEN_INT (size)));
965           RTX_FRAME_RELATED_P (insn) = 1;
966         }
967       
968       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
969         {
970           if (regs_ever_live[regno] && ! call_used_regs[regno])
971             {
972               if (IS_FLOAT_CALL_SAVED_REGNO (regno))
973                 {
974                   if (TARGET_PRESERVE_FLOAT)
975                     {
976                       insn = emit_insn (gen_pushqi
977                                         (gen_rtx_REG (QImode, regno)));
978                       RTX_FRAME_RELATED_P (insn) = 1;
979                     }
980                   insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno)));
981                   RTX_FRAME_RELATED_P (insn) = 1;
982                 }
983               else if ((! dont_push_ar3) || (regno != AR3_REGNO))
984                 {
985                   insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno)));
986                   RTX_FRAME_RELATED_P (insn) = 1;
987                 }
988             }
989         }
990     }
991 }
992
993
994 void
995 c4x_expand_epilogue()
996 {
997   int regno;
998   int jump = 0;
999   int dont_pop_ar3;
1000   rtx insn;
1001   int size = get_frame_size ();
1002   
1003   /* For __assembler__ function build no epilogue.  */
1004   if (c4x_assembler_function_p ())
1005     {
1006       insn = emit_jump_insn (gen_return_from_epilogue ());
1007       RTX_FRAME_RELATED_P (insn) = 1;
1008       return;
1009     }
1010
1011   /* For __interrupt__ function build specific epilogue.  */
1012   if (c4x_interrupt_function_p ())
1013     {
1014       for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1015         {
1016           if (! c4x_isr_reg_used_p (regno))
1017             continue;
1018           if (regno == DP_REGNO)
1019             {
1020               insn = emit_insn (gen_pop_dp ());
1021               RTX_FRAME_RELATED_P (insn) = 1;
1022             }
1023           else
1024             {
1025               /* We have to use unspec because the compiler will delete insns
1026                  that are not call-saved.  */
1027               if (IS_EXT_REGNO (regno))
1028                 {
1029                   insn = emit_insn (gen_popqf_unspec
1030                                     (gen_rtx_REG (QFmode, regno)));
1031                   RTX_FRAME_RELATED_P (insn) = 1;
1032                 }
1033               insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno)));
1034               RTX_FRAME_RELATED_P (insn) = 1;
1035             }
1036         }
1037       if (size)
1038         {
1039           insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
1040                                         gen_rtx_REG (QImode, SP_REGNO),
1041                                         GEN_INT(size)));
1042           RTX_FRAME_RELATED_P (insn) = 1;
1043           insn = emit_insn (gen_popqi
1044                             (gen_rtx_REG (QImode, AR3_REGNO)));
1045           RTX_FRAME_RELATED_P (insn) = 1;
1046         }
1047       insn = emit_insn (gen_pop_st ());
1048       RTX_FRAME_RELATED_P (insn) = 1;
1049       insn = emit_jump_insn (gen_return_from_interrupt_epilogue ());
1050       RTX_FRAME_RELATED_P (insn) = 1;
1051     }
1052   else
1053     {
1054       if (frame_pointer_needed)
1055         {
1056           if ((size != 0) 
1057               || (current_function_args_size != 0) 
1058               || (optimize < 2))
1059             {
1060               insn = emit_insn
1061                 (gen_movqi (gen_rtx_REG (QImode, R2_REGNO),
1062                             gen_rtx_MEM (QImode,
1063                                          gen_rtx_PLUS 
1064                                          (QImode, gen_rtx_REG (QImode,
1065                                                                AR3_REGNO),
1066                                           GEN_INT(-1)))));
1067               RTX_FRAME_RELATED_P (insn) = 1;
1068               
1069               /* We already have the return value and the fp,
1070                  so we need to add those to the stack.  */
1071               size += 2;
1072               jump = 1;
1073               dont_pop_ar3 = 1;
1074             }
1075           else
1076             {
1077               /* Since ar3 is not used for anything, we don't need to
1078                  pop it.  */
1079               dont_pop_ar3 = 1;
1080             }
1081         }
1082       else
1083         {
1084           dont_pop_ar3 = 0;     /* If we use ar3, we need to pop it.  */
1085           if (size || current_function_args_size)
1086             {
1087               /* If we are ommitting the frame pointer, we still have
1088                  to make space for it so the offsets are correct
1089                  unless we don't use anything on the stack at all.  */
1090               size += 1;
1091             }
1092         }
1093       
1094       /* Now restore the saved registers, putting in the delayed branch
1095          where required.  */
1096       for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
1097         {
1098           if (regs_ever_live[regno] && ! call_used_regs[regno])
1099             {
1100               if (regno == AR3_REGNO && dont_pop_ar3)
1101                 continue;
1102               
1103               if (IS_FLOAT_CALL_SAVED_REGNO (regno))
1104                 {
1105                   insn = emit_insn (gen_popqf_unspec
1106                                     (gen_rtx_REG (QFmode, regno)));
1107                   RTX_FRAME_RELATED_P (insn) = 1;
1108                   if (TARGET_PRESERVE_FLOAT)
1109                     {
1110                       insn = emit_insn (gen_popqi_unspec
1111                                         (gen_rtx_REG (QImode, regno)));
1112                       RTX_FRAME_RELATED_P (insn) = 1;
1113                     }
1114                 }
1115               else
1116                 {
1117                   insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno)));
1118                   RTX_FRAME_RELATED_P (insn) = 1;
1119                 }
1120             }
1121         }
1122       
1123       if (frame_pointer_needed)
1124         {
1125           if ((size != 0)
1126               || (current_function_args_size != 0)
1127               || (optimize < 2))
1128             {
1129               /* Restore the old FP.  */
1130               insn = emit_insn 
1131                 (gen_movqi 
1132                  (gen_rtx_REG (QImode, AR3_REGNO),
1133                   gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO))));
1134               
1135               RTX_FRAME_RELATED_P (insn) = 1;
1136             }
1137         }
1138       
1139       if (size > 32767)
1140         {
1141           /* Local vars are too big, it will take multiple operations
1142              to decrement SP.  */
1143           if (TARGET_C3X)
1144             {
1145               insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
1146                                            GEN_INT(size >> 16)));
1147               RTX_FRAME_RELATED_P (insn) = 1;
1148               insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO),
1149                                              gen_rtx_REG (QImode, R3_REGNO),
1150                                              GEN_INT(-16)));
1151               RTX_FRAME_RELATED_P (insn) = 1;
1152             }
1153           else
1154             {
1155               insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
1156                                            GEN_INT(size & ~0xffff)));
1157               RTX_FRAME_RELATED_P (insn) = 1;
1158             }
1159           insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO),
1160                                         gen_rtx_REG (QImode, R3_REGNO),
1161                                         GEN_INT(size & 0xffff)));
1162           RTX_FRAME_RELATED_P (insn) = 1;
1163           insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
1164                                         gen_rtx_REG (QImode, SP_REGNO),
1165                                         gen_rtx_REG (QImode, R3_REGNO)));
1166           RTX_FRAME_RELATED_P (insn) = 1;
1167         }
1168       else if (size != 0)
1169         {
1170           /* Local vars take up less than 32768 words, so we can directly
1171              subtract the number.  */
1172           insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
1173                                         gen_rtx_REG (QImode, SP_REGNO),
1174                                         GEN_INT(size)));
1175           RTX_FRAME_RELATED_P (insn) = 1;
1176         }
1177       
1178       if (jump)
1179         {
1180           insn = emit_jump_insn (gen_return_indirect_internal
1181                                  (gen_rtx_REG (QImode, R2_REGNO)));
1182           RTX_FRAME_RELATED_P (insn) = 1;
1183         }
1184       else
1185         {
1186           insn = emit_jump_insn (gen_return_from_epilogue ());
1187           RTX_FRAME_RELATED_P (insn) = 1;
1188         }
1189     }
1190 }
1191
1192
1193 int
1194 c4x_null_epilogue_p ()
1195 {
1196   int regno;
1197
1198   if (reload_completed
1199       && ! c4x_assembler_function_p ()
1200       && ! c4x_interrupt_function_p ()
1201       && ! current_function_calls_alloca
1202       && ! current_function_args_size
1203       && ! (optimize < 2)
1204       && ! get_frame_size ())
1205     {
1206       for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
1207         if (regs_ever_live[regno] && ! call_used_regs[regno]
1208             && (regno != AR3_REGNO))
1209           return 0;
1210       return 1;
1211     }
1212   return 0;
1213 }
1214
1215
1216 int
1217 c4x_emit_move_sequence (operands, mode)
1218      rtx *operands;
1219      enum machine_mode mode;     
1220 {
1221   rtx op0 = operands[0];
1222   rtx op1 = operands[1];
1223
1224   if (! reload_in_progress
1225       && ! REG_P (op0) 
1226       && ! REG_P (op1)
1227       && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode)))
1228     op1 = force_reg (mode, op1);
1229
1230   if (GET_CODE (op1) == LO_SUM
1231       && GET_MODE (op1) == Pmode
1232       && dp_reg_operand (XEXP (op1, 0), mode))
1233     {
1234       /* expand_increment will sometimes create a LO_SUM immediate
1235          address.  */
1236       op1 = XEXP (op1, 1);
1237     }
1238   else if (symbolic_address_operand (op1, mode))
1239     {
1240       if (TARGET_LOAD_ADDRESS)
1241         {
1242           /* Alias analysis seems to do a better job if we force
1243              constant addresses to memory after reload.  */
1244           emit_insn (gen_load_immed_address (op0, op1));
1245           return 1;
1246         }
1247       else
1248         {
1249           /* Stick symbol or label address into the constant pool.  */
1250           op1 = force_const_mem (Pmode, op1);
1251         }
1252     }
1253   else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
1254     {
1255       /* We could be a lot smarter about loading some of these
1256          constants...  */
1257       op1 = force_const_mem (mode, op1);
1258     }
1259
1260   /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF)))
1261      and emit associated (HIGH (SYMREF)) if large memory model.  
1262      c4x_legitimize_address could be used to do this,
1263      perhaps by calling validize_address.  */
1264   if (TARGET_EXPOSE_LDP
1265       && ! (reload_in_progress || reload_completed)
1266       && GET_CODE (op1) == MEM
1267       && symbolic_address_operand (XEXP (op1, 0), Pmode))
1268     {
1269       rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
1270       if (! TARGET_SMALL)
1271         emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0)));
1272       op1 = change_address (op1, mode,
1273                             gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0)));
1274     }
1275
1276   if (TARGET_EXPOSE_LDP
1277       && ! (reload_in_progress || reload_completed)
1278       && GET_CODE (op0) == MEM 
1279       && symbolic_address_operand (XEXP (op0, 0), Pmode))
1280     {
1281       rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
1282       if (! TARGET_SMALL)
1283         emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0)));
1284       op0 = change_address (op0, mode,
1285                             gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0)));
1286     }
1287
1288   if (GET_CODE (op0) == SUBREG
1289       && mixed_subreg_operand (op0, mode))
1290     {
1291       /* We should only generate these mixed mode patterns
1292          during RTL generation.  If we need do it later on
1293          then we'll have to emit patterns that won't clobber CC.  */
1294       if (reload_in_progress || reload_completed)
1295         abort ();
1296       if (GET_MODE (SUBREG_REG (op0)) == QImode)
1297         op0 = SUBREG_REG (op0);
1298       else if (GET_MODE (SUBREG_REG (op0)) == HImode)
1299         {
1300           op0 = copy_rtx (op0);
1301           PUT_MODE (op0, QImode);
1302         }
1303       else
1304         abort ();
1305
1306       if (mode == QFmode)
1307         emit_insn (gen_storeqf_int_clobber (op0, op1));
1308       else
1309         abort ();
1310       return 1;
1311     }
1312
1313   if (GET_CODE (op1) == SUBREG
1314       && mixed_subreg_operand (op1, mode))
1315     {
1316       /* We should only generate these mixed mode patterns
1317          during RTL generation.  If we need do it later on
1318          then we'll have to emit patterns that won't clobber CC.  */
1319       if (reload_in_progress || reload_completed)
1320         abort ();
1321       if (GET_MODE (SUBREG_REG (op1)) == QImode)
1322         op1 = SUBREG_REG (op1);
1323       else if (GET_MODE (SUBREG_REG (op1)) == HImode)
1324         {
1325           op1 = copy_rtx (op1);
1326           PUT_MODE (op1, QImode);
1327         }
1328       else
1329         abort ();
1330
1331       if (mode == QFmode)
1332         emit_insn (gen_loadqf_int_clobber (op0, op1));
1333       else
1334         abort ();
1335       return 1;
1336     }
1337
1338   if (mode == QImode
1339       && reg_operand (op0, mode)
1340       && const_int_operand (op1, mode)
1341       && ! IS_INT16_CONST (INTVAL (op1))
1342       && ! IS_HIGH_CONST (INTVAL (op1)))
1343     {
1344       emit_insn (gen_loadqi_big_constant (op0, op1));
1345       return 1;
1346     }
1347
1348   if (mode == HImode
1349       && reg_operand (op0, mode)
1350       && const_int_operand (op1, mode))
1351     {
1352       emit_insn (gen_loadhi_big_constant (op0, op1));
1353       return 1;
1354     }
1355
1356   /* Adjust operands in case we have modified them.  */
1357   operands[0] = op0;
1358   operands[1] = op1;
1359
1360   /* Emit normal pattern.  */
1361   return 0;
1362 }
1363
1364
1365 void
1366 c4x_emit_libcall (libcall, code, dmode, smode, noperands, operands)
1367      rtx libcall;
1368      enum rtx_code code;
1369      enum machine_mode dmode;
1370      enum machine_mode smode;
1371      int noperands;
1372      rtx *operands;
1373 {
1374   rtx ret;
1375   rtx insns;
1376   rtx equiv;
1377
1378   start_sequence ();
1379   switch (noperands)
1380     {
1381     case 2:
1382       ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
1383                                      operands[1], smode);
1384       equiv = gen_rtx (code, dmode, operands[1]);
1385       break;
1386
1387     case 3:
1388       ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2,
1389                                      operands[1], smode, operands[2], smode);
1390       equiv = gen_rtx (code, dmode, operands[1], operands[2]);
1391       break;
1392
1393     default:
1394       abort ();
1395     }
1396
1397   insns = get_insns ();
1398   end_sequence ();
1399   emit_libcall_block (insns, operands[0], ret, equiv);
1400 }
1401
1402
1403 void
1404 c4x_emit_libcall3 (libcall, code, mode, operands)
1405      rtx libcall;
1406      enum rtx_code code;
1407      enum machine_mode mode;
1408      rtx *operands;
1409 {
1410   c4x_emit_libcall (libcall, code, mode, mode, 3, operands);
1411 }
1412
1413
1414 void
1415 c4x_emit_libcall_mulhi (libcall, code, mode, operands)
1416      rtx libcall;
1417      enum rtx_code code;
1418      enum machine_mode mode;
1419      rtx *operands;
1420 {
1421   rtx ret;
1422   rtx insns;
1423   rtx equiv;
1424
1425   start_sequence ();
1426   ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2,
1427                                  operands[1], mode, operands[2], mode);
1428   equiv = gen_rtx_TRUNCATE (mode,
1429                    gen_rtx_LSHIFTRT (HImode,
1430                             gen_rtx_MULT (HImode,
1431                                      gen_rtx (code, HImode, operands[1]),
1432                                      gen_rtx (code, HImode, operands[2])),
1433                                      GEN_INT (32)));
1434   insns = get_insns ();
1435   end_sequence ();
1436   emit_libcall_block (insns, operands[0], ret, equiv);
1437 }
1438
1439
1440 /* Set the SYMBOL_REF_FLAG for a function decl.  However, wo do not
1441    yet use this info.  */
1442
1443 static void
1444 c4x_encode_section_info (decl, first)
1445      tree decl;
1446      int first ATTRIBUTE_UNUSED;
1447 {
1448   if (TREE_CODE (decl) == FUNCTION_DECL)   
1449     SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
1450 }
1451
1452
1453 int
1454 c4x_check_legit_addr (mode, addr, strict)
1455      enum machine_mode mode;
1456      rtx addr;
1457      int strict;
1458 {
1459   rtx base = NULL_RTX;          /* Base register (AR0-AR7).  */
1460   rtx indx = NULL_RTX;          /* Index register (IR0,IR1).  */
1461   rtx disp = NULL_RTX;          /* Displacement.  */
1462   enum rtx_code code;
1463
1464   code = GET_CODE (addr);
1465   switch (code)
1466     {
1467       /* Register indirect with auto increment/decrement.  We don't
1468          allow SP here---push_operand should recognise an operand
1469          being pushed on the stack.  */
1470
1471     case PRE_DEC:
1472     case PRE_INC:
1473     case POST_DEC:
1474       if (mode != QImode && mode != QFmode)
1475         return 0;
1476
1477     case POST_INC:
1478       base = XEXP (addr, 0);
1479       if (! REG_P (base))
1480         return 0;
1481       break;
1482
1483     case PRE_MODIFY:
1484     case POST_MODIFY:
1485       {
1486         rtx op0 = XEXP (addr, 0);
1487         rtx op1 = XEXP (addr, 1);
1488
1489         if (mode != QImode && mode != QFmode)
1490           return 0;
1491
1492         if (! REG_P (op0) 
1493             || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS))
1494           return 0;
1495         base = XEXP (op1, 0);
1496         if (base != op0)
1497           return 0;
1498         if (REG_P (XEXP (op1, 1)))
1499           indx = XEXP (op1, 1);
1500         else
1501           disp = XEXP (op1, 1);
1502       }
1503       break;
1504         
1505       /* Register indirect.  */
1506     case REG:
1507       base = addr;
1508       break;
1509
1510       /* Register indirect with displacement or index.  */
1511     case PLUS:
1512       {
1513         rtx op0 = XEXP (addr, 0);
1514         rtx op1 = XEXP (addr, 1);
1515         enum rtx_code code0 = GET_CODE (op0);
1516
1517         switch (code0)
1518           {
1519           case REG:
1520             if (REG_P (op1))
1521               {
1522                 base = op0;     /* Base + index.  */
1523                 indx = op1;
1524                 if (IS_INDEX_REG (base) || IS_ADDR_REG (indx))
1525                   {
1526                     base = op1;
1527                     indx = op0;
1528                   }
1529               }
1530             else
1531               {
1532                 base = op0;     /* Base + displacement.  */
1533                 disp = op1;
1534               }
1535             break;
1536
1537           default:
1538             return 0;
1539           }
1540       }
1541       break;
1542
1543       /* Direct addressing with DP register.  */
1544     case LO_SUM:
1545       {
1546         rtx op0 = XEXP (addr, 0);
1547         rtx op1 = XEXP (addr, 1);
1548
1549         /* HImode and HFmode direct memory references aren't truly
1550            offsettable (consider case at end of data page).  We
1551            probably get better code by loading a pointer and using an
1552            indirect memory reference.  */
1553         if (mode == HImode || mode == HFmode)
1554           return 0;
1555
1556         if (!REG_P (op0) || REGNO (op0) != DP_REGNO)
1557           return 0;
1558
1559         if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF))
1560           return 1;
1561
1562         if (GET_CODE (op1) == CONST)
1563           return 1;
1564         return 0;
1565       }
1566       break;
1567
1568       /* Direct addressing with some work for the assembler...  */
1569     case CONST:
1570       /* Direct addressing.  */
1571     case LABEL_REF:
1572     case SYMBOL_REF:
1573       if (! TARGET_EXPOSE_LDP && ! strict && mode != HFmode && mode != HImode)
1574         return 1;
1575       /* These need to be converted to a LO_SUM (...). 
1576          LEGITIMIZE_RELOAD_ADDRESS will do this during reload.  */
1577       return 0;
1578
1579       /* Do not allow direct memory access to absolute addresses.
1580          This is more pain than it's worth, especially for the
1581          small memory model where we can't guarantee that
1582          this address is within the data page---we don't want
1583          to modify the DP register in the small memory model,
1584          even temporarily, since an interrupt can sneak in....  */
1585     case CONST_INT:
1586       return 0;
1587
1588       /* Indirect indirect addressing.  */
1589     case MEM:
1590       return 0;
1591
1592     case CONST_DOUBLE:
1593       fatal_insn ("using CONST_DOUBLE for address", addr);
1594
1595     default:
1596       return 0;
1597     }
1598
1599   /* Validate the base register.  */
1600   if (base)
1601     {
1602       /* Check that the address is offsettable for HImode and HFmode.  */
1603       if (indx && (mode == HImode || mode == HFmode))
1604         return 0;
1605
1606       /* Handle DP based stuff.  */
1607       if (REGNO (base) == DP_REGNO)
1608         return 1;
1609       if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base)))
1610         return 0;
1611       else if (! strict && ! IS_ADDR_OR_PSEUDO_REG (base))
1612         return 0;
1613     }
1614
1615   /* Now validate the index register.  */
1616   if (indx)
1617     {
1618       if (GET_CODE (indx) != REG)
1619         return 0;
1620       if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx)))
1621         return 0;
1622       else if (! strict && ! IS_INDEX_OR_PSEUDO_REG (indx))
1623         return 0;
1624     }
1625
1626   /* Validate displacement.  */
1627   if (disp)
1628     {
1629       if (GET_CODE (disp) != CONST_INT)
1630         return 0;
1631       if (mode == HImode || mode == HFmode)
1632         {
1633           /* The offset displacement must be legitimate.  */
1634           if (! IS_DISP8_OFF_CONST (INTVAL (disp)))
1635             return 0;
1636         }
1637       else
1638         {
1639           if (! IS_DISP8_CONST (INTVAL (disp)))
1640             return 0;
1641         }
1642       /* Can't add an index with a disp.  */
1643       if (indx)
1644         return 0;               
1645     }
1646   return 1;
1647 }
1648
1649
1650 rtx
1651 c4x_legitimize_address (orig, mode)
1652      rtx orig ATTRIBUTE_UNUSED;
1653      enum machine_mode mode ATTRIBUTE_UNUSED;
1654 {
1655   if (GET_CODE (orig) == SYMBOL_REF
1656       || GET_CODE (orig) == LABEL_REF)
1657     {
1658       if (mode == HImode || mode == HFmode)
1659         {
1660           /* We need to force the address into
1661              a register so that it is offsettable.  */
1662           rtx addr_reg = gen_reg_rtx (Pmode);
1663           emit_move_insn (addr_reg, orig);
1664           return addr_reg;
1665         }
1666       else
1667         {
1668           rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
1669           
1670           if (! TARGET_SMALL)
1671             emit_insn (gen_set_ldp (dp_reg, orig));
1672           
1673           return gen_rtx_LO_SUM (Pmode, dp_reg, orig);
1674         }
1675     }
1676
1677   return NULL_RTX;
1678 }
1679
1680
1681 /* Provide the costs of an addressing mode that contains ADDR.
1682    If ADDR is not a valid address, its cost is irrelevant.  
1683    This is used in cse and loop optimisation to determine
1684    if it is worthwhile storing a common address into a register. 
1685    Unfortunately, the C4x address cost depends on other operands.  */
1686
1687 int 
1688 c4x_address_cost (addr)
1689      rtx addr;
1690 {
1691   switch (GET_CODE (addr))
1692     {
1693     case REG:
1694       return 1;
1695
1696     case POST_INC:
1697     case POST_DEC:
1698     case PRE_INC:
1699     case PRE_DEC:
1700       return 1;
1701       
1702       /* These shouldn't be directly generated.  */
1703     case SYMBOL_REF:
1704     case LABEL_REF:
1705     case CONST:
1706       return 10;
1707
1708     case LO_SUM:
1709       {
1710         rtx op1 = XEXP (addr, 1);
1711
1712         if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF)
1713           return TARGET_SMALL ? 3 : 4;
1714         
1715         if (GET_CODE (op1) == CONST)
1716           {
1717             rtx offset = const0_rtx;
1718             
1719             op1 = eliminate_constant_term (op1, &offset);
1720             
1721             /* ??? These costs need rethinking...  */
1722             if (GET_CODE (op1) == LABEL_REF)
1723               return 3;
1724             
1725             if (GET_CODE (op1) != SYMBOL_REF)
1726               return 4;
1727             
1728             if (INTVAL (offset) == 0)
1729               return 3;
1730
1731             return 4;
1732           }
1733         fatal_insn ("c4x_address_cost: Invalid addressing mode", addr);
1734       }
1735       break;
1736       
1737     case PLUS:
1738       {
1739         register rtx op0 = XEXP (addr, 0);
1740         register rtx op1 = XEXP (addr, 1);
1741         
1742         if (GET_CODE (op0) != REG)
1743           break;
1744         
1745         switch (GET_CODE (op1))
1746           {
1747           default:
1748             break;
1749
1750           case REG:
1751             /* This cost for REG+REG must be greater than the cost
1752                for REG if we want autoincrement addressing modes.  */
1753             return 2;
1754
1755           case CONST_INT:
1756             /* The following tries to improve GIV combination
1757                in strength reduce but appears not to help.  */
1758             if (TARGET_DEVEL && IS_UINT5_CONST (INTVAL (op1)))
1759               return 1;
1760
1761             if (IS_DISP1_CONST (INTVAL (op1)))
1762               return 1;
1763
1764             if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1)))
1765               return 2;
1766
1767             return 3;
1768           }
1769       }
1770     default:
1771       break;
1772     }
1773   
1774   return 4;
1775 }
1776
1777
1778 rtx
1779 c4x_gen_compare_reg (code, x, y)
1780      enum rtx_code code;
1781      rtx x, y;
1782 {
1783   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
1784   rtx cc_reg;
1785
1786   if (mode == CC_NOOVmode
1787       && (code == LE || code == GE || code == LT || code == GT))
1788     return NULL_RTX;
1789
1790   cc_reg = gen_rtx_REG (mode, ST_REGNO);
1791   emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1792                           gen_rtx_COMPARE (mode, x, y)));
1793   return cc_reg;
1794 }
1795
1796 char *
1797 c4x_output_cbranch (form, seq)
1798      const char *form;
1799      rtx seq;
1800 {
1801   int delayed = 0;
1802   int annultrue = 0;
1803   int annulfalse = 0;
1804   rtx delay;
1805   char *cp;
1806   static char str[100];
1807   
1808   if (final_sequence)
1809     {
1810       delay = XVECEXP (final_sequence, 0, 1);
1811       delayed = ! INSN_ANNULLED_BRANCH_P (seq);
1812       annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay);
1813       annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay);
1814     }
1815   strcpy (str, form);
1816   cp = &str [strlen (str)];
1817   if (delayed)
1818     {
1819       *cp++ = '%';
1820       *cp++ = '#';
1821     }
1822   if (annultrue)
1823     {
1824       *cp++ = 'a';
1825       *cp++ = 't';
1826     }
1827   if (annulfalse)
1828     {
1829       *cp++ = 'a'; 
1830       *cp++ = 'f';
1831     }
1832   *cp++ = '\t';
1833   *cp++ = '%'; 
1834   *cp++ = 'l';
1835   *cp++ = '1';
1836   *cp = 0;
1837   return str;
1838 }
1839
1840 void
1841 c4x_print_operand (file, op, letter)
1842      FILE *file;                /* File to write to.  */
1843      rtx op;                    /* Operand to print.  */
1844      int letter;                /* %<letter> or 0.  */
1845 {
1846   rtx op1;
1847   enum rtx_code code;
1848
1849   switch (letter)
1850     {
1851     case '#':                   /* Delayed.  */
1852       if (final_sequence)
1853         fprintf (file, "d");
1854       return;
1855     }
1856
1857   code = GET_CODE (op);
1858   switch (letter)
1859     {
1860     case 'A':                   /* Direct address.  */
1861       if (code == CONST_INT || code == SYMBOL_REF || code == CONST)
1862         fprintf (file, "@");
1863       break;
1864
1865     case 'H':                   /* Sethi.  */
1866       output_addr_const (file, op);
1867       return;
1868
1869     case 'I':                   /* Reversed condition.  */
1870       code = reverse_condition (code);
1871       break;
1872
1873     case 'L':                   /* Log 2 of constant.  */
1874       if (code != CONST_INT)
1875         fatal_insn ("c4x_print_operand: %%L inconsistency", op);
1876       fprintf (file, "%d", exact_log2 (INTVAL (op)));
1877       return;
1878
1879     case 'N':                   /* Ones complement of small constant.  */
1880       if (code != CONST_INT)
1881         fatal_insn ("c4x_print_operand: %%N inconsistency", op);
1882       fprintf (file, "%d", ~INTVAL (op));
1883       return;
1884
1885     case 'K':                   /* Generate ldp(k) if direct address.  */
1886       if (! TARGET_SMALL
1887           && code == MEM
1888           && GET_CODE (XEXP (op, 0)) == LO_SUM
1889           && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1890           && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO)
1891         {
1892           op1 = XEXP (XEXP (op, 0), 1);
1893           if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF)
1894             {
1895               fprintf (file, "\t%s\t@", TARGET_C3X ? "ldp" : "ldpk");
1896               output_address (XEXP (adjust_address (op, VOIDmode, 1), 0));
1897               fprintf (file, "\n");
1898             }
1899         }
1900       return;
1901
1902     case 'M':                   /* Generate ldp(k) if direct address.  */
1903       if (! TARGET_SMALL        /* Only used in asm statements.  */
1904           && code == MEM
1905           && (GET_CODE (XEXP (op, 0)) == CONST
1906               || GET_CODE (XEXP (op, 0)) == SYMBOL_REF))
1907         {
1908           fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk");
1909           output_address (XEXP (op, 0));
1910           fprintf (file, "\n\t");
1911         }
1912       return;
1913
1914     case 'O':                   /* Offset address.  */
1915       if (code == MEM && c4x_autoinc_operand (op, Pmode))
1916         break;
1917       else if (code == MEM)
1918         output_address (XEXP (adjust_address (op, VOIDmode, 1), 0));
1919       else if (code == REG)
1920         fprintf (file, "%s", reg_names[REGNO (op) + 1]);
1921       else
1922         fatal_insn ("c4x_print_operand: %%O inconsistency", op);
1923       return;
1924
1925     case 'C':                   /* Call.  */
1926       break;
1927
1928     case 'U':                   /* Call/callu.  */
1929       if (code != SYMBOL_REF)
1930         fprintf (file, "u");
1931       return;
1932
1933     default:
1934       break;
1935     }
1936   
1937   switch (code)
1938     {
1939     case REG:
1940       if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1941           && ! TARGET_TI)
1942         fprintf (file, "%s", float_reg_names[REGNO (op)]);
1943       else
1944         fprintf (file, "%s", reg_names[REGNO (op)]);
1945       break;
1946       
1947     case MEM:
1948       output_address (XEXP (op, 0));
1949       break;
1950       
1951     case CONST_DOUBLE:
1952       {
1953         char str[30];
1954         REAL_VALUE_TYPE r;
1955         
1956         REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1957         REAL_VALUE_TO_DECIMAL (r, "%20f", str);
1958         fprintf (file, "%s", str);
1959       }
1960       break;
1961       
1962     case CONST_INT:
1963       fprintf (file, "%d", INTVAL (op));
1964       break;
1965       
1966     case NE:
1967       fprintf (file, "ne");
1968       break;
1969       
1970     case EQ:
1971       fprintf (file, "eq");
1972       break;
1973       
1974     case GE:
1975       fprintf (file, "ge");
1976       break;
1977
1978     case GT:
1979       fprintf (file, "gt");
1980       break;
1981
1982     case LE:
1983       fprintf (file, "le");
1984       break;
1985
1986     case LT:
1987       fprintf (file, "lt");
1988       break;
1989
1990     case GEU:
1991       fprintf (file, "hs");
1992       break;
1993
1994     case GTU:
1995       fprintf (file, "hi");
1996       break;
1997
1998     case LEU:
1999       fprintf (file, "ls");
2000       break;
2001
2002     case LTU:
2003       fprintf (file, "lo");
2004       break;
2005
2006     case SYMBOL_REF:
2007       output_addr_const (file, op);
2008       break;
2009
2010     case CONST:
2011       output_addr_const (file, XEXP (op, 0));
2012       break;
2013
2014     case CODE_LABEL:
2015       break;
2016
2017     default:
2018       fatal_insn ("c4x_print_operand: Bad operand case", op);
2019       break;
2020     }
2021 }
2022
2023
2024 void
2025 c4x_print_operand_address (file, addr)
2026      FILE *file;
2027      rtx addr;
2028 {
2029   switch (GET_CODE (addr))
2030     {
2031     case REG:
2032       fprintf (file, "*%s", reg_names[REGNO (addr)]);
2033       break;
2034
2035     case PRE_DEC:
2036       fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]);
2037       break;
2038
2039     case POST_INC:
2040       fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
2041       break;
2042
2043     case POST_MODIFY:
2044       {
2045         rtx op0 = XEXP (XEXP (addr, 1), 0);
2046         rtx op1 = XEXP (XEXP (addr, 1), 1);
2047         
2048         if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
2049           fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)],
2050                    reg_names[REGNO (op1)]);
2051         else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
2052           fprintf (file, "*%s++(%d)", reg_names[REGNO (op0)],
2053                    INTVAL (op1));
2054         else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
2055           fprintf (file, "*%s--(%d)", reg_names[REGNO (op0)],
2056                    -INTVAL (op1));
2057         else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
2058           fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)],
2059                    reg_names[REGNO (op1)]);
2060         else
2061           fatal_insn ("c4x_print_operand_address: Bad post_modify", addr);
2062       }
2063       break;
2064       
2065     case PRE_MODIFY:
2066       {
2067         rtx op0 = XEXP (XEXP (addr, 1), 0);
2068         rtx op1 = XEXP (XEXP (addr, 1), 1);
2069         
2070         if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
2071           fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)],
2072                    reg_names[REGNO (op1)]);
2073         else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
2074           fprintf (file, "*++%s(%d)", reg_names[REGNO (op0)],
2075                    INTVAL (op1));
2076         else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
2077           fprintf (file, "*--%s(%d)", reg_names[REGNO (op0)],
2078                    -INTVAL (op1));
2079         else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
2080           fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)],
2081                    reg_names[REGNO (op1)]);
2082         else
2083           fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr);
2084       }
2085       break;
2086       
2087     case PRE_INC:
2088       fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]);
2089       break;
2090
2091     case POST_DEC:
2092       fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
2093       break;
2094
2095     case PLUS:                  /* Indirect with displacement.  */
2096       {
2097         rtx op0 = XEXP (addr, 0);
2098         rtx op1 = XEXP (addr, 1);
2099
2100         if (REG_P (op0))
2101           {
2102             if (REG_P (op1))
2103               {
2104                 if (IS_INDEX_REG (op0))
2105                   {
2106                     fprintf (file, "*+%s(%s)",
2107                              reg_names[REGNO (op1)],
2108                              reg_names[REGNO (op0)]);   /* Index + base.  */
2109                   }
2110                 else
2111                   {
2112                     fprintf (file, "*+%s(%s)",
2113                              reg_names[REGNO (op0)],
2114                              reg_names[REGNO (op1)]);   /* Base + index.  */
2115                   }
2116               }
2117             else if (INTVAL (op1) < 0)
2118               {
2119                 fprintf (file, "*-%s(%d)",
2120                          reg_names[REGNO (op0)],
2121                          -INTVAL (op1));        /* Base - displacement.  */
2122               }
2123             else
2124               {
2125                 fprintf (file, "*+%s(%d)",
2126                          reg_names[REGNO (op0)],
2127                          INTVAL (op1)); /* Base + displacement.  */
2128               }
2129           }
2130         else
2131           fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
2132       }
2133       break;
2134
2135     case LO_SUM:
2136       {
2137         rtx op0 = XEXP (addr, 0);
2138         rtx op1 = XEXP (addr, 1);
2139           
2140         if (REG_P (op0) && REGNO (op0) == DP_REGNO)
2141           c4x_print_operand_address (file, op1);
2142         else
2143           fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
2144       }
2145       break;
2146
2147     case CONST:
2148     case SYMBOL_REF:
2149     case LABEL_REF:
2150       fprintf (file, "@");
2151       output_addr_const (file, addr);
2152       break;
2153
2154       /* We shouldn't access CONST_INT addresses.  */
2155     case CONST_INT:
2156
2157     default:
2158       fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
2159       break;
2160     }
2161 }
2162
2163
2164 /* Return nonzero if the floating point operand will fit
2165    in the immediate field.  */
2166
2167 static int
2168 c4x_immed_float_p (op)
2169      rtx op;
2170 {
2171   long convval[2];
2172   int exponent;
2173   REAL_VALUE_TYPE r;
2174
2175   REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2176   if (GET_MODE (op) == HFmode)
2177     REAL_VALUE_TO_TARGET_DOUBLE (r, convval);
2178   else
2179     {
2180       REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]);
2181       convval[1] = 0;
2182     }
2183
2184   /* Sign extend exponent.  */
2185   exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80;
2186   if (exponent == -128)
2187     return 1;                   /* 0.0  */
2188   if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0)
2189     return 0;                   /* Precision doesn't fit.  */
2190   return (exponent <= 7)        /* Positive exp.  */
2191     && (exponent >= -7);        /* Negative exp.  */
2192 }
2193
2194
2195 /* The last instruction in a repeat block cannot be a Bcond, DBcound,
2196    CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS.
2197
2198    None of the last four instructions from the bottom of the block can
2199    be a BcondD, BRD, DBcondD, RPTBD, LAJ, LAJcond, LATcond, BcondAF,
2200    BcondAT or RETIcondD.
2201
2202    This routine scans the four previous insns for a jump insn, and if
2203    one is found, returns 1 so that we bung in a nop instruction.
2204    This simple minded strategy will add a nop, when it may not
2205    be required.  Say when there is a JUMP_INSN near the end of the
2206    block that doesn't get converted into a delayed branch.
2207
2208    Note that we cannot have a call insn, since we don't generate
2209    repeat loops with calls in them (although I suppose we could, but
2210    there's no benefit.)  
2211
2212    !!! FIXME.  The rptb_top insn may be sucked into a SEQUENCE.  */
2213
2214 int
2215 c4x_rptb_nop_p (insn)
2216      rtx insn;
2217 {
2218   rtx start_label;
2219   int i;
2220
2221   /* Extract the start label from the jump pattern (rptb_end).  */
2222   start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
2223
2224   /* If there is a label at the end of the loop we must insert
2225      a NOP.  */
2226   do {
2227     insn = previous_insn (insn);
2228   } while (GET_CODE (insn) == NOTE
2229            || GET_CODE (insn) == USE
2230            || GET_CODE (insn) == CLOBBER);
2231   if (GET_CODE (insn) == CODE_LABEL)
2232     return 1;
2233
2234   for (i = 0; i < 4; i++)
2235     {
2236       /* Search back for prev non-note and non-label insn.  */
2237       while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL
2238              || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER)
2239         {
2240           if (insn == start_label)
2241             return i == 0;
2242
2243           insn = previous_insn (insn);
2244         };
2245
2246       /* If we have a jump instruction we should insert a NOP. If we
2247          hit repeat block top we should only insert a NOP if the loop
2248          is empty.  */
2249       if (GET_CODE (insn) == JUMP_INSN)
2250         return 1;
2251       insn = previous_insn (insn);
2252     }
2253   return 0;
2254 }
2255
2256
2257 /* The C4x looping instruction needs to be emitted at the top of the
2258   loop.  Emitting the true RTL for a looping instruction at the top of
2259   the loop can cause problems with flow analysis.  So instead, a dummy
2260   doloop insn is emitted at the end of the loop.  This routine checks
2261   for the presence of this doloop insn and then searches back to the
2262   top of the loop, where it inserts the true looping insn (provided
2263   there are no instructions in the loop which would cause problems).
2264   Any additional labels can be emitted at this point.  In addition, if
2265   the desired loop count register was not allocated, this routine does
2266   nothing. 
2267
2268   Before we can create a repeat block looping instruction we have to
2269   verify that there are no jumps outside the loop and no jumps outside
2270   the loop go into this loop. This can happen in the basic blocks reorder
2271   pass. The C4x cpu can not handle this.  */
2272
2273 static int
2274 c4x_label_ref_used_p (x, code_label)
2275      rtx x, code_label;
2276 {
2277   enum rtx_code code;
2278   int i, j;
2279   const char *fmt;
2280
2281   if (x == 0)
2282     return 0;
2283
2284   code = GET_CODE (x);
2285   if (code == LABEL_REF)
2286     return INSN_UID (XEXP (x,0)) == INSN_UID (code_label);
2287
2288   fmt = GET_RTX_FORMAT (code);
2289   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2290     {
2291       if (fmt[i] == 'e')
2292         {
2293           if (c4x_label_ref_used_p (XEXP (x, i), code_label))
2294             return 1;
2295         }
2296       else if (fmt[i] == 'E')
2297         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
2298           if (c4x_label_ref_used_p (XVECEXP (x, i, j), code_label))
2299             return 1;
2300     }
2301   return 0;
2302 }
2303
2304
2305 static int
2306 c4x_rptb_valid_p (insn, start_label)
2307      rtx insn, start_label;
2308 {
2309   rtx end = insn;
2310   rtx start;
2311   rtx tmp;
2312
2313   /* Find the start label.  */
2314   for (; insn; insn = PREV_INSN (insn))
2315     if (insn == start_label)
2316       break;
2317
2318   /* Note found then we can not use a rptb or rpts.  The label was
2319      probably moved by the basic block reorder pass.  */
2320   if (! insn)
2321     return 0;
2322
2323   start = insn;
2324   /* If any jump jumps inside this block then we must fail.  */
2325   for (insn = PREV_INSN (start); insn; insn = PREV_INSN (insn))
2326     {
2327       if (GET_CODE (insn) == CODE_LABEL)
2328         {
2329           for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
2330             if (GET_CODE (tmp) == JUMP_INSN
2331                 && c4x_label_ref_used_p (tmp, insn))
2332               return 0;
2333         }
2334     }
2335   for (insn = NEXT_INSN (end); insn; insn = NEXT_INSN (insn))
2336     {
2337       if (GET_CODE (insn) == CODE_LABEL)
2338         {
2339           for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
2340             if (GET_CODE (tmp) == JUMP_INSN
2341                 && c4x_label_ref_used_p (tmp, insn))
2342               return 0;
2343         }
2344     }
2345   /* If any jump jumps outside this block then we must fail.  */
2346   for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn))
2347     {
2348       if (GET_CODE (insn) == CODE_LABEL)
2349         {
2350           for (tmp = NEXT_INSN (end); tmp; tmp = NEXT_INSN(tmp))
2351             if (GET_CODE (tmp) == JUMP_INSN
2352                 && c4x_label_ref_used_p (tmp, insn))
2353               return 0;
2354           for (tmp = PREV_INSN (start); tmp; tmp = PREV_INSN(tmp))
2355             if (GET_CODE (tmp) == JUMP_INSN
2356                 && c4x_label_ref_used_p (tmp, insn))
2357               return 0;
2358         }
2359     }
2360
2361   /* All checks OK.  */
2362   return 1;
2363 }
2364
2365
2366 void
2367 c4x_rptb_insert (insn)
2368      rtx insn;
2369 {
2370   rtx end_label;
2371   rtx start_label;
2372   rtx new_start_label;
2373   rtx count_reg;
2374
2375   /* If the count register has not been allocated to RC, say if
2376      there is a movstr pattern in the loop, then do not insert a
2377      RPTB instruction.  Instead we emit a decrement and branch
2378      at the end of the loop.  */
2379   count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0);
2380   if (REGNO (count_reg) != RC_REGNO)
2381     return;
2382
2383   /* Extract the start label from the jump pattern (rptb_end).  */
2384   start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
2385   
2386   if (! c4x_rptb_valid_p (insn, start_label))
2387     {
2388       /* We can not use the rptb insn.  Replace it so reorg can use
2389          the delay slots of the jump insn.  */
2390       emit_insn_before (gen_addqi3 (count_reg, count_reg, GEN_INT (-1)), insn);
2391       emit_insn_before (gen_cmpqi (count_reg, GEN_INT (0)), insn);
2392       emit_insn_before (gen_bge (start_label), insn);
2393       LABEL_NUSES (start_label)++;
2394       delete_insn (insn);
2395       return;
2396     }
2397
2398   end_label = gen_label_rtx ();
2399   LABEL_NUSES (end_label)++;
2400   emit_label_after (end_label, insn);
2401
2402   new_start_label = gen_label_rtx ();
2403   LABEL_NUSES (new_start_label)++;
2404
2405   for (; insn; insn = PREV_INSN (insn))
2406     {
2407       if (insn == start_label)
2408          break;
2409       if (GET_CODE (insn) == JUMP_INSN &&
2410           JUMP_LABEL (insn) == start_label)
2411         redirect_jump (insn, new_start_label, 0);
2412     }
2413   if (! insn)
2414     fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label);
2415
2416   emit_label_after (new_start_label, insn);
2417
2418   if (TARGET_RPTS && c4x_rptb_rpts_p (PREV_INSN (insn), 0))
2419     emit_insn_after (gen_rpts_top (new_start_label, end_label), insn);
2420   else
2421     emit_insn_after (gen_rptb_top (new_start_label, end_label), insn);
2422   if (LABEL_NUSES (start_label) == 0)
2423     delete_insn (start_label);
2424 }
2425
2426
2427 /* This function is a C4x special called immediately before delayed
2428    branch scheduling.  We fix up RTPB style loops that didn't get RC
2429    allocated as the loop counter.  */
2430
2431 void
2432 c4x_process_after_reload (first)
2433      rtx first;
2434 {
2435   rtx insn;
2436
2437   for (insn = first; insn; insn = NEXT_INSN (insn))
2438     {
2439       /* Look for insn.  */
2440       if (INSN_P (insn))
2441         {
2442           int insn_code_number;
2443           rtx old;
2444
2445           insn_code_number = recog_memoized (insn);
2446
2447           if (insn_code_number < 0)
2448             continue;
2449
2450           /* Insert the RTX for RPTB at the top of the loop
2451              and a label at the end of the loop.  */
2452           if (insn_code_number == CODE_FOR_rptb_end)
2453             c4x_rptb_insert(insn);
2454
2455           /* We need to split the insn here. Otherwise the calls to
2456              force_const_mem will not work for load_immed_address.  */
2457           old = insn;
2458
2459           /* Don't split the insn if it has been deleted.  */
2460           if (! INSN_DELETED_P (old))
2461             insn = try_split (PATTERN(old), old, 1);
2462
2463           /* When not optimizing, the old insn will be still left around
2464              with only the 'deleted' bit set.  Transform it into a note
2465              to avoid confusion of subsequent processing.  */
2466           if (INSN_DELETED_P (old))
2467             {
2468               PUT_CODE (old, NOTE);
2469               NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
2470               NOTE_SOURCE_FILE (old) = 0;
2471             }
2472         }
2473     }
2474 }
2475
2476
2477 static int
2478 c4x_a_register (op)
2479      rtx op;
2480 {
2481   return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op);
2482 }
2483
2484
2485 static int
2486 c4x_x_register (op)
2487      rtx op;
2488 {
2489   return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op);
2490 }
2491
2492
2493 static int
2494 c4x_immed_int_constant (op)
2495      rtx op;
2496 {
2497   if (GET_CODE (op) != CONST_INT)
2498     return 0;
2499
2500   return GET_MODE (op) == VOIDmode
2501     || GET_MODE_CLASS (op) == MODE_INT
2502     || GET_MODE_CLASS (op) == MODE_PARTIAL_INT;
2503 }
2504
2505
2506 static int
2507 c4x_immed_float_constant (op)
2508      rtx op;
2509 {
2510   if (GET_CODE (op) != CONST_DOUBLE)
2511     return 0;
2512
2513   /* Do not check if the CONST_DOUBLE is in memory. If there is a MEM
2514      present this only means that a MEM rtx has been generated. It does
2515      not mean the rtx is really in memory.  */
2516
2517   return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;
2518 }
2519
2520
2521 int
2522 c4x_shiftable_constant (op)
2523      rtx op;
2524 {
2525   int i;
2526   int mask;
2527   int val = INTVAL (op);
2528
2529   for (i = 0; i < 16; i++)
2530     {
2531       if (val & (1 << i))
2532         break;
2533     }
2534   mask = ((0xffff >> i) << 16) | 0xffff;
2535   if (IS_INT16_CONST (val & (1 << 31) ? (val >> i) | ~mask
2536                                       : (val >> i) & mask))
2537     return i;
2538   return -1;
2539
2540
2541
2542 int
2543 c4x_H_constant (op)
2544      rtx op;
2545 {
2546   return c4x_immed_float_constant (op) && c4x_immed_float_p (op);
2547 }
2548
2549
2550 int
2551 c4x_I_constant (op)
2552      rtx op;
2553 {
2554   return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op));
2555 }
2556
2557
2558 int
2559 c4x_J_constant (op)
2560      rtx op;
2561 {
2562   if (TARGET_C3X)
2563     return 0;
2564   return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op));
2565 }
2566
2567
2568 static int
2569 c4x_K_constant (op)
2570      rtx op;
2571 {
2572   if (TARGET_C3X || ! c4x_immed_int_constant (op))
2573     return 0;
2574   return IS_INT5_CONST (INTVAL (op));
2575 }
2576
2577
2578 int
2579 c4x_L_constant (op)
2580      rtx op;
2581 {
2582   return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
2583 }
2584
2585
2586 static int
2587 c4x_N_constant (op)
2588      rtx op;
2589 {
2590   return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
2591 }
2592
2593
2594 static int
2595 c4x_O_constant (op)
2596      rtx op;
2597 {
2598   return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
2599 }
2600
2601
2602 /* The constraints do not have to check the register class,
2603    except when needed to discriminate between the constraints.
2604    The operand has been checked by the predicates to be valid.  */
2605
2606 /* ARx + 9-bit signed const or IRn
2607    *ARx, *+ARx(n), *-ARx(n), *+ARx(IRn), *-Arx(IRn) for -256 < n < 256
2608    We don't include the pre/post inc/dec forms here since
2609    they are handled by the <> constraints.  */
2610
2611 int
2612 c4x_Q_constraint (op)
2613      rtx op;
2614 {
2615   enum machine_mode mode = GET_MODE (op);
2616
2617   if (GET_CODE (op) != MEM)
2618     return 0;
2619   op = XEXP (op, 0);
2620   switch (GET_CODE (op))
2621     {
2622     case REG:
2623       return 1;
2624
2625     case PLUS:
2626       {
2627         rtx op0 = XEXP (op, 0);
2628         rtx op1 = XEXP (op, 1);
2629
2630         if (! REG_P (op0))
2631           return 0;
2632
2633         if (REG_P (op1))
2634           return 1;
2635
2636         if (GET_CODE (op1) != CONST_INT)
2637           return 0;
2638
2639         /* HImode and HFmode must be offsettable.  */
2640         if (mode == HImode || mode == HFmode)
2641           return IS_DISP8_OFF_CONST (INTVAL (op1));
2642         
2643         return IS_DISP8_CONST (INTVAL (op1));
2644       }
2645       break;
2646
2647     default:
2648       break;
2649     }
2650   return 0;
2651 }
2652
2653
2654 /* ARx + 5-bit unsigned const
2655    *ARx, *+ARx(n) for n < 32.  */
2656
2657 int
2658 c4x_R_constraint (op)
2659      rtx op;
2660 {
2661   enum machine_mode mode = GET_MODE (op);
2662
2663   if (TARGET_C3X)
2664     return 0;
2665   if (GET_CODE (op) != MEM)
2666     return 0;
2667   op = XEXP (op, 0);
2668   switch (GET_CODE (op))
2669     {
2670     case REG:
2671       return 1;
2672
2673     case PLUS:
2674       {
2675         rtx op0 = XEXP (op, 0);
2676         rtx op1 = XEXP (op, 1);
2677
2678         if (! REG_P (op0))
2679           return 0;
2680
2681         if (GET_CODE (op1) != CONST_INT)
2682           return 0;
2683
2684         /* HImode and HFmode must be offsettable.  */
2685         if (mode == HImode || mode == HFmode)
2686           return IS_UINT5_CONST (INTVAL (op1) + 1);
2687         
2688         return IS_UINT5_CONST (INTVAL (op1));
2689       }
2690       break;
2691
2692     default:
2693       break;
2694     }
2695   return 0;
2696 }
2697
2698
2699 static int
2700 c4x_R_indirect (op)
2701      rtx op;
2702 {
2703   enum machine_mode mode = GET_MODE (op);
2704
2705   if (TARGET_C3X || GET_CODE (op) != MEM)
2706     return 0;
2707
2708   op = XEXP (op, 0);
2709   switch (GET_CODE (op))
2710     {
2711     case REG:
2712       return IS_ADDR_OR_PSEUDO_REG (op);
2713
2714     case PLUS:
2715       {
2716         rtx op0 = XEXP (op, 0);
2717         rtx op1 = XEXP (op, 1);
2718
2719         /* HImode and HFmode must be offsettable.  */
2720         if (mode == HImode || mode == HFmode)
2721           return IS_ADDR_OR_PSEUDO_REG (op0)
2722             && GET_CODE (op1) == CONST_INT 
2723             && IS_UINT5_CONST (INTVAL (op1) + 1);
2724
2725         return REG_P (op0)
2726           && IS_ADDR_OR_PSEUDO_REG (op0)
2727           && GET_CODE (op1) == CONST_INT
2728           && IS_UINT5_CONST (INTVAL (op1));
2729       }
2730       break;
2731
2732     default:
2733       break;
2734     }
2735   return 0;
2736 }
2737
2738
2739 /* ARx + 1-bit unsigned const or IRn
2740    *ARx, *+ARx(1), *-ARx(1), *+ARx(IRn), *-Arx(IRn)
2741    We don't include the pre/post inc/dec forms here since
2742    they are handled by the <> constraints.  */
2743
2744 int
2745 c4x_S_constraint (op)
2746      rtx op;
2747 {
2748   enum machine_mode mode = GET_MODE (op);
2749   if (GET_CODE (op) != MEM)
2750     return 0;
2751   op = XEXP (op, 0);
2752   switch (GET_CODE (op))
2753     {
2754     case REG:
2755       return 1;
2756
2757     case PRE_MODIFY:
2758     case POST_MODIFY:
2759       {
2760         rtx op0 = XEXP (op, 0);
2761         rtx op1 = XEXP (op, 1);
2762         
2763         if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
2764             || (op0 != XEXP (op1, 0)))
2765           return 0;
2766         
2767         op0 = XEXP (op1, 0);
2768         op1 = XEXP (op1, 1);
2769         return REG_P (op0) && REG_P (op1);
2770         /* Pre or post_modify with a displacement of 0 or 1 
2771            should not be generated.  */
2772       }
2773       break;
2774
2775     case PLUS:
2776       {
2777         rtx op0 = XEXP (op, 0);
2778         rtx op1 = XEXP (op, 1);
2779
2780         if (!REG_P (op0))
2781           return 0;
2782
2783         if (REG_P (op1))
2784           return 1;
2785
2786         if (GET_CODE (op1) != CONST_INT)
2787           return 0;
2788         
2789         /* HImode and HFmode must be offsettable.  */
2790         if (mode == HImode || mode == HFmode)
2791           return IS_DISP1_OFF_CONST (INTVAL (op1));
2792         
2793         return IS_DISP1_CONST (INTVAL (op1));
2794       }
2795       break;
2796
2797     default:
2798       break;
2799     }
2800   return 0;
2801 }
2802
2803
2804 static int
2805 c4x_S_indirect (op)
2806      rtx op;
2807 {
2808   enum machine_mode mode = GET_MODE (op);
2809   if (GET_CODE (op) != MEM)
2810     return 0;
2811
2812   op = XEXP (op, 0);
2813   switch (GET_CODE (op))
2814     {
2815     case PRE_DEC:
2816     case POST_DEC:
2817       if (mode != QImode && mode != QFmode)
2818         return 0;
2819     case PRE_INC:
2820     case POST_INC:
2821       op = XEXP (op, 0);
2822
2823     case REG:
2824       return IS_ADDR_OR_PSEUDO_REG (op);
2825
2826     case PRE_MODIFY:
2827     case POST_MODIFY:
2828       {
2829         rtx op0 = XEXP (op, 0);
2830         rtx op1 = XEXP (op, 1);
2831         
2832         if (mode != QImode && mode != QFmode)
2833           return 0;
2834
2835         if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
2836             || (op0 != XEXP (op1, 0)))
2837           return 0;
2838         
2839         op0 = XEXP (op1, 0);
2840         op1 = XEXP (op1, 1);
2841         return REG_P (op0) && IS_ADDR_OR_PSEUDO_REG (op0)
2842           && REG_P (op1) && IS_INDEX_OR_PSEUDO_REG (op1);
2843         /* Pre or post_modify with a displacement of 0 or 1 
2844            should not be generated.  */
2845       }
2846
2847     case PLUS:
2848       {
2849         rtx op0 = XEXP (op, 0);
2850         rtx op1 = XEXP (op, 1);
2851
2852         if (REG_P (op0))
2853           {
2854             /* HImode and HFmode must be offsettable.  */
2855             if (mode == HImode || mode == HFmode)
2856               return IS_ADDR_OR_PSEUDO_REG (op0)
2857                 && GET_CODE (op1) == CONST_INT 
2858                 && IS_DISP1_OFF_CONST (INTVAL (op1));
2859
2860             if (REG_P (op1))
2861               return (IS_INDEX_OR_PSEUDO_REG (op1)
2862                       && IS_ADDR_OR_PSEUDO_REG (op0))
2863                 || (IS_ADDR_OR_PSEUDO_REG (op1)
2864                     && IS_INDEX_OR_PSEUDO_REG (op0));
2865             
2866             return IS_ADDR_OR_PSEUDO_REG (op0)
2867               && GET_CODE (op1) == CONST_INT 
2868               && IS_DISP1_CONST (INTVAL (op1));
2869           }
2870       }
2871       break;
2872
2873     default:
2874       break;
2875     }
2876   return 0;
2877 }
2878
2879
2880 /* Direct memory operand.  */
2881
2882 int
2883 c4x_T_constraint (op)
2884      rtx op;
2885 {
2886   if (GET_CODE (op) != MEM)
2887     return 0;
2888   op = XEXP (op, 0);
2889
2890   if (GET_CODE (op) != LO_SUM)
2891     {
2892       /* Allow call operands.  */
2893       return GET_CODE (op) == SYMBOL_REF
2894         && GET_MODE (op) == Pmode
2895         && SYMBOL_REF_FLAG (op);
2896     }
2897
2898   /* HImode and HFmode are not offsettable.  */
2899   if (GET_MODE (op) == HImode || GET_CODE (op) == HFmode)
2900     return 0;
2901
2902   if ((GET_CODE (XEXP (op, 0)) == REG)
2903       && (REGNO (XEXP (op, 0)) == DP_REGNO))
2904     return c4x_U_constraint (XEXP (op, 1));
2905   
2906   return 0;
2907 }
2908
2909
2910 /* Symbolic operand.  */
2911
2912 int
2913 c4x_U_constraint (op)
2914      rtx op;
2915 {
2916   /* Don't allow direct addressing to an arbitrary constant.  */
2917   return GET_CODE (op) == CONST
2918          || GET_CODE (op) == SYMBOL_REF
2919          || GET_CODE (op) == LABEL_REF;
2920 }
2921
2922
2923 int
2924 c4x_autoinc_operand (op, mode)
2925      rtx op;
2926      enum machine_mode mode ATTRIBUTE_UNUSED;
2927 {
2928   if (GET_CODE (op) == MEM)
2929     {
2930       enum rtx_code code = GET_CODE (XEXP (op, 0));
2931       
2932       if (code == PRE_INC
2933           || code == PRE_DEC
2934           || code == POST_INC
2935           || code == POST_DEC
2936           || code == PRE_MODIFY
2937           || code == POST_MODIFY
2938           )
2939         return 1;
2940     }
2941   return 0;
2942 }
2943
2944
2945 /* Match any operand.  */
2946
2947 int
2948 any_operand (op, mode)
2949      register rtx op ATTRIBUTE_UNUSED;
2950      enum machine_mode mode ATTRIBUTE_UNUSED;
2951 {
2952   return 1;
2953 }
2954
2955
2956 /* Nonzero if OP is a floating point value with value 0.0.  */
2957
2958 int
2959 fp_zero_operand (op, mode)
2960      rtx op;
2961      enum machine_mode mode ATTRIBUTE_UNUSED;
2962 {
2963   REAL_VALUE_TYPE r;
2964
2965   if (GET_CODE (op) != CONST_DOUBLE)
2966     return 0;
2967   REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2968   return REAL_VALUES_EQUAL (r, dconst0);
2969 }
2970
2971
2972 int
2973 const_operand (op, mode)
2974      register rtx op;
2975      register enum machine_mode mode;
2976 {
2977   switch (mode)
2978     {
2979     case QFmode:
2980     case HFmode:
2981       if (GET_CODE (op) != CONST_DOUBLE
2982           || GET_MODE (op) != mode
2983           || GET_MODE_CLASS (mode) != MODE_FLOAT)
2984         return 0;
2985
2986       return c4x_immed_float_p (op);
2987
2988 #if Pmode != QImode
2989     case Pmode:
2990 #endif
2991     case QImode:
2992       if (GET_CODE (op) == CONSTANT_P_RTX)
2993         return 1;
2994
2995       if (GET_CODE (op) != CONST_INT
2996           || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
2997           || GET_MODE_CLASS (mode) != MODE_INT)
2998         return 0;
2999
3000       return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
3001
3002     case HImode:
3003       return 0;
3004
3005     default:
3006       return 0;
3007     }
3008 }
3009
3010
3011 int
3012 stik_const_operand (op, mode)
3013      rtx op;
3014      enum machine_mode mode ATTRIBUTE_UNUSED;
3015 {
3016   return c4x_K_constant (op);
3017 }
3018
3019
3020 int
3021 not_const_operand (op, mode)
3022      rtx op;
3023      enum machine_mode mode ATTRIBUTE_UNUSED;
3024 {
3025   return c4x_N_constant (op);
3026 }
3027
3028
3029 int
3030 reg_operand (op, mode)
3031      rtx op;
3032      enum machine_mode mode;
3033 {
3034   if (GET_CODE (op) == SUBREG
3035       && GET_MODE (op) == QFmode)
3036     return 0;
3037   return register_operand (op, mode);
3038 }
3039
3040
3041 int
3042 mixed_subreg_operand (op, mode)
3043      rtx op;
3044      enum machine_mode mode ATTRIBUTE_UNUSED;
3045 {
3046   /* Allow (subreg:HF (reg:HI)) that be generated for a union of an
3047      int and a long double.  */
3048   if (GET_CODE (op) == SUBREG
3049       && (GET_MODE (op) == QFmode)
3050       && (GET_MODE (SUBREG_REG (op)) == QImode
3051           || GET_MODE (SUBREG_REG (op)) == HImode))
3052     return 1;
3053   return 0;
3054 }
3055
3056
3057 int
3058 reg_imm_operand (op, mode)
3059      rtx op;
3060      enum machine_mode mode ATTRIBUTE_UNUSED;
3061 {
3062   if (REG_P (op) || CONSTANT_P (op))
3063     return 1;
3064   return 0;
3065 }
3066
3067
3068 int
3069 not_modify_reg (op, mode)
3070      rtx op;
3071      enum machine_mode mode ATTRIBUTE_UNUSED;
3072 {
3073   if (REG_P (op) || CONSTANT_P (op))
3074     return 1;
3075   if (GET_CODE (op) != MEM)
3076     return 0;
3077   op = XEXP (op, 0);
3078   switch (GET_CODE (op))
3079     {
3080     case REG:
3081       return 1;
3082
3083     case PLUS:
3084       {
3085         rtx op0 = XEXP (op, 0);
3086         rtx op1 = XEXP (op, 1);
3087
3088         if (! REG_P (op0))
3089           return 0;
3090         
3091         if (REG_P (op1) || GET_CODE (op1) == CONST_INT)
3092           return 1;
3093       }
3094
3095     case LO_SUM:
3096       {
3097         rtx op0 = XEXP (op, 0);
3098           
3099         if (REG_P (op0) && REGNO (op0) == DP_REGNO)
3100           return 1;
3101       }
3102       break;
3103      
3104     case CONST:
3105     case SYMBOL_REF:
3106     case LABEL_REF:
3107       return 1;
3108
3109     default:
3110       break;
3111     }
3112   return 0;
3113 }
3114
3115
3116 int
3117 not_rc_reg (op, mode)
3118      rtx op;
3119      enum machine_mode mode ATTRIBUTE_UNUSED;
3120 {
3121   if (REG_P (op) && REGNO (op) == RC_REGNO)
3122     return 0;
3123   return 1;
3124 }
3125
3126
3127 /* Extended precision register R0-R1.  */
3128
3129 int
3130 r0r1_reg_operand (op, mode)
3131      rtx op;
3132      enum machine_mode mode;
3133 {
3134   if (! reg_operand (op, mode))
3135     return 0;
3136   if (GET_CODE (op) == SUBREG)
3137     op = SUBREG_REG (op);
3138   return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
3139 }
3140
3141
3142 /* Extended precision register R2-R3.  */
3143
3144 int
3145 r2r3_reg_operand (op, mode)
3146      rtx op;
3147      enum machine_mode mode;
3148 {
3149   if (! reg_operand (op, mode))
3150     return 0;
3151   if (GET_CODE (op) == SUBREG)
3152     op = SUBREG_REG (op);
3153   return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
3154 }
3155
3156
3157 /* Low extended precision register R0-R7.  */
3158
3159 int
3160 ext_low_reg_operand (op, mode)
3161      rtx op;
3162      enum machine_mode mode;
3163 {
3164   if (! reg_operand (op, mode))
3165     return 0;
3166   if (GET_CODE (op) == SUBREG)
3167     op = SUBREG_REG (op);
3168   return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
3169 }
3170
3171
3172 /* Extended precision register.  */
3173
3174 int
3175 ext_reg_operand (op, mode)
3176      rtx op;
3177      enum machine_mode mode;
3178 {
3179   if (! reg_operand (op, mode))
3180     return 0;
3181   if (GET_CODE (op) == SUBREG)
3182     op = SUBREG_REG (op);
3183   if (! REG_P (op))
3184     return 0;
3185   return IS_EXT_OR_PSEUDO_REG (op);
3186 }
3187
3188
3189 /* Standard precision register.  */
3190
3191 int
3192 std_reg_operand (op, mode)
3193      rtx op;
3194      enum machine_mode mode;
3195 {
3196   if (! reg_operand (op, mode))
3197     return 0;
3198   if (GET_CODE (op) == SUBREG)
3199     op = SUBREG_REG (op);
3200   return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
3201 }
3202
3203 /* Standard precision or normal register.  */
3204
3205 int
3206 std_or_reg_operand (op, mode)
3207      rtx op;
3208      enum machine_mode mode;
3209 {
3210   if (reload_in_progress)
3211     return std_reg_operand (op, mode);
3212   return reg_operand (op, mode);
3213 }
3214
3215 /* Address register.  */
3216
3217 int
3218 addr_reg_operand (op, mode)
3219      rtx op;
3220      enum machine_mode mode;
3221 {
3222   if (! reg_operand (op, mode))
3223     return 0;
3224   return c4x_a_register (op);
3225 }
3226
3227
3228 /* Index register.  */
3229
3230 int
3231 index_reg_operand (op, mode)
3232      rtx op;
3233      enum machine_mode mode;
3234 {
3235   if (! reg_operand (op, mode))
3236     return 0;
3237   if (GET_CODE (op) == SUBREG)
3238     op = SUBREG_REG (op);
3239   return c4x_x_register (op);
3240 }
3241
3242
3243 /* DP register.  */
3244
3245 int
3246 dp_reg_operand (op, mode)
3247      rtx op;
3248      enum machine_mode mode ATTRIBUTE_UNUSED;
3249 {
3250   return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
3251 }
3252
3253
3254 /* SP register.  */
3255
3256 int
3257 sp_reg_operand (op, mode)
3258      rtx op;
3259      enum machine_mode mode ATTRIBUTE_UNUSED;
3260 {
3261   return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
3262 }
3263
3264
3265 /* ST register.  */
3266
3267 int
3268 st_reg_operand (op, mode)
3269      register rtx op;
3270      enum machine_mode mode ATTRIBUTE_UNUSED;
3271 {
3272   return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
3273 }
3274
3275
3276 /* RC register.  */
3277
3278 int
3279 rc_reg_operand (op, mode)
3280      register rtx op;
3281      enum machine_mode mode ATTRIBUTE_UNUSED;
3282 {
3283   return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
3284 }
3285
3286
3287 int
3288 call_address_operand (op, mode)
3289      rtx op;
3290      enum machine_mode mode ATTRIBUTE_UNUSED;
3291 {
3292   return (REG_P (op) || symbolic_address_operand (op, mode));
3293 }
3294
3295
3296 /* Symbolic address operand.  */
3297
3298 int
3299 symbolic_address_operand (op, mode)
3300      register rtx op;
3301      enum machine_mode mode ATTRIBUTE_UNUSED;
3302 {
3303   switch (GET_CODE (op))
3304     {
3305     case CONST:
3306     case SYMBOL_REF:
3307     case LABEL_REF:
3308       return 1;
3309     default:
3310       return 0;
3311     }
3312 }
3313
3314
3315 /* Check dst operand of a move instruction.  */
3316
3317 int
3318 dst_operand (op, mode)
3319      rtx op;
3320      enum machine_mode mode;
3321 {
3322   if (GET_CODE (op) == SUBREG
3323       && mixed_subreg_operand (op, mode))
3324     return 0;
3325
3326   if (REG_P (op))
3327     return reg_operand (op, mode);
3328
3329   return nonimmediate_operand (op, mode);
3330 }
3331
3332
3333 /* Check src operand of two operand arithmetic instructions.  */
3334
3335 int
3336 src_operand (op, mode)
3337      rtx op;
3338      enum machine_mode mode;
3339 {
3340   if (GET_CODE (op) == SUBREG
3341       && mixed_subreg_operand (op, mode))
3342     return 0;
3343
3344   if (REG_P (op))
3345     return reg_operand (op, mode);
3346
3347   if (mode == VOIDmode)
3348     mode = GET_MODE (op);
3349
3350   if (GET_CODE (op) == CONST_INT)
3351     return (mode == QImode || mode == Pmode || mode == HImode)
3352       && c4x_I_constant (op);
3353
3354   /* We don't like CONST_DOUBLE integers.  */
3355   if (GET_CODE (op) == CONST_DOUBLE)
3356     return c4x_H_constant (op);
3357
3358   /* Disallow symbolic addresses.  Only the predicate
3359      symbolic_address_operand will match these.  */
3360   if (GET_CODE (op) == SYMBOL_REF
3361       || GET_CODE (op) == LABEL_REF
3362       || GET_CODE (op) == CONST)
3363     return 0;
3364
3365   /* If TARGET_LOAD_DIRECT_MEMS is non-zero, disallow direct memory
3366      access to symbolic addresses.  These operands will get forced
3367      into a register and the movqi expander will generate a
3368      HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is non-zero.  */
3369   if (GET_CODE (op) == MEM
3370       && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3371            || GET_CODE (XEXP (op, 0)) == LABEL_REF
3372            || GET_CODE (XEXP (op, 0)) == CONST)))
3373     return ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
3374
3375   return general_operand (op, mode);
3376 }
3377
3378
3379 int
3380 src_hi_operand (op, mode)
3381      rtx op;
3382      enum machine_mode mode;
3383 {
3384   if (c4x_O_constant (op))
3385     return 1;
3386   return src_operand (op, mode);
3387 }
3388
3389
3390 /* Check src operand of two operand logical instructions.  */
3391
3392 int
3393 lsrc_operand (op, mode)
3394      rtx op;
3395      enum machine_mode mode;
3396 {
3397   if (mode == VOIDmode)
3398     mode = GET_MODE (op);
3399
3400   if (mode != QImode && mode != Pmode)
3401     fatal_insn ("mode not QImode", op);
3402
3403   if (GET_CODE (op) == CONST_INT)
3404     return c4x_L_constant (op) || c4x_J_constant (op);
3405
3406   return src_operand (op, mode);
3407 }
3408
3409
3410 /* Check src operand of two operand tricky instructions.  */
3411
3412 int
3413 tsrc_operand (op, mode)
3414      rtx op;
3415      enum machine_mode mode;
3416 {
3417   if (mode == VOIDmode)
3418     mode = GET_MODE (op);
3419
3420   if (mode != QImode && mode != Pmode)
3421     fatal_insn ("mode not QImode", op);
3422
3423   if (GET_CODE (op) == CONST_INT)
3424     return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
3425
3426   return src_operand (op, mode);
3427 }
3428
3429
3430 /* Check src operand of two operand non immedidate instructions.  */
3431
3432 int
3433 nonimmediate_src_operand (op, mode)
3434      rtx op;
3435      enum machine_mode mode;
3436 {
3437   if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
3438     return 0;
3439
3440   return src_operand (op, mode);
3441 }
3442
3443
3444 /* Check logical src operand of two operand non immedidate instructions.  */
3445
3446 int
3447 nonimmediate_lsrc_operand (op, mode)
3448      rtx op;
3449      enum machine_mode mode;
3450 {
3451   if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
3452     return 0;
3453
3454   return lsrc_operand (op, mode);
3455 }
3456
3457
3458 int
3459 reg_or_const_operand (op, mode)
3460      rtx op;
3461      enum machine_mode mode;
3462 {
3463   return reg_operand (op, mode) || const_operand (op, mode);
3464 }
3465
3466
3467 /* Check for indirect operands allowable in parallel instruction.  */
3468
3469 int
3470 par_ind_operand (op, mode)
3471      rtx op;
3472      enum machine_mode mode;
3473 {
3474   if (mode != VOIDmode && mode != GET_MODE (op))
3475     return 0;
3476
3477   return c4x_S_indirect (op);
3478 }
3479
3480
3481 /* Check for operands allowable in parallel instruction.  */
3482
3483 int
3484 parallel_operand (op, mode)
3485      rtx op;
3486      enum machine_mode mode;
3487 {
3488   return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
3489 }
3490
3491
3492 static void 
3493 c4x_S_address_parse (op, base, incdec, index, disp)
3494      rtx op;
3495      int *base;
3496      int *incdec;
3497      int *index;
3498      int *disp;
3499 {
3500   *base = 0;
3501   *incdec = 0;
3502   *index = 0;
3503   *disp = 0;
3504        
3505   if (GET_CODE (op) != MEM)
3506     fatal_insn ("invalid indirect memory address", op);
3507   
3508   op = XEXP (op, 0);
3509   switch (GET_CODE (op))
3510     {
3511     case PRE_DEC:
3512       *base = REGNO (XEXP (op, 0));
3513       *incdec = 1;
3514       *disp = -1;
3515       return;
3516
3517     case POST_DEC:
3518       *base = REGNO (XEXP (op, 0));
3519       *incdec = 1;
3520       *disp = 0;
3521       return;
3522
3523     case PRE_INC:
3524       *base = REGNO (XEXP (op, 0));
3525       *incdec = 1;
3526       *disp = 1;
3527       return;
3528
3529     case POST_INC:
3530       *base = REGNO (XEXP (op, 0));
3531       *incdec = 1;
3532       *disp = 0;
3533       return;
3534
3535     case POST_MODIFY:
3536       *base = REGNO (XEXP (op, 0));
3537       if (REG_P (XEXP (XEXP (op, 1), 1)))
3538         {
3539           *index = REGNO (XEXP (XEXP (op, 1), 1));
3540           *disp = 0;            /* ??? */
3541         }
3542       else
3543           *disp = INTVAL (XEXP (XEXP (op, 1), 1));
3544       *incdec = 1;
3545       return;
3546
3547     case PRE_MODIFY:
3548       *base = REGNO (XEXP (op, 0));
3549       if (REG_P (XEXP (XEXP (op, 1), 1)))
3550         {
3551           *index = REGNO (XEXP (XEXP (op, 1), 1));
3552           *disp = 1;            /* ??? */
3553         }
3554       else
3555           *disp = INTVAL (XEXP (XEXP (op, 1), 1));
3556       *incdec = 1;
3557
3558       return;
3559
3560     case REG:
3561       *base = REGNO (op);
3562       return;
3563
3564     case PLUS:
3565       {
3566         rtx op0 = XEXP (op, 0);
3567         rtx op1 = XEXP (op, 1);
3568
3569         if (c4x_a_register (op0))
3570           {
3571             if (c4x_x_register (op1))
3572               {
3573                 *base = REGNO (op0);
3574                 *index = REGNO (op1);
3575                 return;
3576               }
3577             else if ((GET_CODE (op1) == CONST_INT 
3578                       && IS_DISP1_CONST (INTVAL (op1))))
3579               {
3580                 *base = REGNO (op0);
3581                 *disp = INTVAL (op1);
3582                 return;
3583               }
3584           }
3585         else if (c4x_x_register (op0) && c4x_a_register (op1))
3586           {
3587             *base = REGNO (op1);
3588             *index = REGNO (op0);
3589             return;
3590           }
3591       }
3592       /* Fallthrough.  */
3593
3594     default:
3595       fatal_insn ("invalid indirect (S) memory address", op);
3596     }
3597 }
3598
3599
3600 int
3601 c4x_address_conflict (op0, op1, store0, store1)
3602      rtx op0;
3603      rtx op1;
3604      int store0;
3605      int store1;
3606 {
3607   int base0;
3608   int base1;
3609   int incdec0;
3610   int incdec1;
3611   int index0;
3612   int index1;
3613   int disp0;
3614   int disp1;
3615   
3616   if (MEM_VOLATILE_P (op0) && MEM_VOLATILE_P (op1))
3617     return 1;
3618
3619   c4x_S_address_parse (op0, &base0, &incdec0, &index0, &disp0);
3620   c4x_S_address_parse (op1, &base1, &incdec1, &index1, &disp1);
3621
3622   if (store0 && store1)
3623     {
3624       /* If we have two stores in parallel to the same address, then
3625          the C4x only executes one of the stores.  This is unlikely to
3626          cause problems except when writing to a hardware device such
3627          as a FIFO since the second write will be lost.  The user
3628          should flag the hardware location as being volatile so that
3629          we don't do this optimisation.  While it is unlikely that we
3630          have an aliased address if both locations are not marked
3631          volatile, it is probably safer to flag a potential conflict
3632          if either location is volatile.  */
3633       if (! flag_argument_noalias)
3634         {
3635           if (MEM_VOLATILE_P (op0) || MEM_VOLATILE_P (op1))
3636             return 1;
3637         }
3638     }
3639
3640   /* If have a parallel load and a store to the same address, the load
3641      is performed first, so there is no conflict.  Similarly, there is
3642      no conflict if have parallel loads from the same address.  */
3643
3644   /* Cannot use auto increment or auto decrement twice for same
3645      base register.  */
3646   if (base0 == base1 && incdec0 && incdec0)
3647     return 1;
3648
3649   /* It might be too confusing for GCC if we have use a base register
3650      with a side effect and a memory reference using the same register
3651      in parallel.  */
3652   if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1))
3653     return 1;
3654
3655   /* We can not optimize the case where op1 and op2 refer to the same
3656      address.  */
3657   if (base0 == base1 && disp0 == disp1 && index0 == index1)
3658     return 1;
3659
3660   /* No conflict.  */
3661   return 0;
3662 }
3663
3664
3665 /* Check for while loop inside a decrement and branch loop.  */
3666
3667 int
3668 c4x_label_conflict (insn, jump, db)
3669      rtx insn;
3670      rtx jump;
3671      rtx db;
3672 {
3673   while (insn)
3674     {
3675       if (GET_CODE (insn) == CODE_LABEL)
3676         {
3677           if (CODE_LABEL_NUMBER (jump) == CODE_LABEL_NUMBER (insn))
3678             return 1;
3679           if (CODE_LABEL_NUMBER (db) == CODE_LABEL_NUMBER (insn))
3680             return 0;
3681         }
3682       insn = PREV_INSN (insn);
3683     }
3684   return 1;
3685 }
3686
3687
3688 /* Validate combination of operands for parallel load/store instructions.  */
3689
3690 int
3691 valid_parallel_load_store (operands, mode)
3692      rtx *operands;
3693      enum machine_mode mode ATTRIBUTE_UNUSED;
3694 {
3695   rtx op0 = operands[0];
3696   rtx op1 = operands[1];
3697   rtx op2 = operands[2];
3698   rtx op3 = operands[3];
3699
3700   if (GET_CODE (op0) == SUBREG)
3701     op0 = SUBREG_REG (op0);
3702   if (GET_CODE (op1) == SUBREG)
3703     op1 = SUBREG_REG (op1);
3704   if (GET_CODE (op2) == SUBREG)
3705     op2 = SUBREG_REG (op2);
3706   if (GET_CODE (op3) == SUBREG)
3707     op3 = SUBREG_REG (op3);
3708
3709   /* The patterns should only allow ext_low_reg_operand() or
3710      par_ind_operand() operands.  Thus of the 4 operands, only 2
3711      should be REGs and the other 2 should be MEMs.  */
3712
3713   /* This test prevents the multipack pass from using this pattern if
3714      op0 is used as an index or base register in op2 or op3, since
3715      this combination will require reloading.  */
3716   if (GET_CODE (op0) == REG
3717       && ((GET_CODE (op2) == MEM && reg_mentioned_p (op0, XEXP (op2, 0)))
3718           || (GET_CODE (op3) == MEM && reg_mentioned_p (op0, XEXP (op3, 0)))))
3719     return 0;
3720
3721   /* LDI||LDI.  */
3722   if (GET_CODE (op0) == REG && GET_CODE (op2) == REG)
3723     return (REGNO (op0) != REGNO (op2))
3724       && GET_CODE (op1) == MEM && GET_CODE (op3) == MEM
3725       && ! c4x_address_conflict (op1, op3, 0, 0);
3726
3727   /* STI||STI.  */
3728   if (GET_CODE (op1) == REG && GET_CODE (op3) == REG)
3729     return GET_CODE (op0) == MEM && GET_CODE (op2) == MEM
3730       && ! c4x_address_conflict (op0, op2, 1, 1);
3731
3732   /* LDI||STI.  */
3733   if (GET_CODE (op0) == REG && GET_CODE (op3) == REG)
3734     return GET_CODE (op1) == MEM && GET_CODE (op2) == MEM
3735       && ! c4x_address_conflict (op1, op2, 0, 1);
3736
3737   /* STI||LDI.  */
3738   if (GET_CODE (op1) == REG && GET_CODE (op2) == REG)
3739     return GET_CODE (op0) == MEM && GET_CODE (op3) == MEM
3740       && ! c4x_address_conflict (op0, op3, 1, 0);
3741
3742   return 0;
3743 }
3744
3745
3746 int
3747 valid_parallel_operands_4 (operands, mode)
3748      rtx *operands;
3749      enum machine_mode mode ATTRIBUTE_UNUSED;
3750 {
3751   rtx op0 = operands[0];
3752   rtx op2 = operands[2];
3753
3754   if (GET_CODE (op0) == SUBREG)
3755     op0 = SUBREG_REG (op0);
3756   if (GET_CODE (op2) == SUBREG)
3757     op2 = SUBREG_REG (op2);
3758
3759   /* This test prevents the multipack pass from using this pattern if
3760      op0 is used as an index or base register in op2, since this combination
3761      will require reloading.  */
3762   if (GET_CODE (op0) == REG
3763       && GET_CODE (op2) == MEM
3764       && reg_mentioned_p (op0, XEXP (op2, 0)))
3765     return 0;
3766
3767   return 1;
3768 }
3769
3770
3771 int
3772 valid_parallel_operands_5 (operands, mode)
3773      rtx *operands;
3774      enum machine_mode mode ATTRIBUTE_UNUSED;
3775 {
3776   int regs = 0;
3777   rtx op0 = operands[0];
3778   rtx op1 = operands[1];
3779   rtx op2 = operands[2];
3780   rtx op3 = operands[3];
3781
3782   if (GET_CODE (op0) == SUBREG)
3783     op0 = SUBREG_REG (op0);
3784   if (GET_CODE (op1) == SUBREG)
3785     op1 = SUBREG_REG (op1);
3786   if (GET_CODE (op2) == SUBREG)
3787     op2 = SUBREG_REG (op2);
3788
3789   /* The patterns should only allow ext_low_reg_operand() or
3790      par_ind_operand() operands.  Operands 1 and 2 may be commutative
3791      but only one of them can be a register.  */
3792   if (GET_CODE (op1) == REG)
3793     regs++;
3794   if (GET_CODE (op2) == REG)
3795     regs++;
3796
3797   if (regs != 1)
3798     return 0;
3799
3800   /* This test prevents the multipack pass from using this pattern if
3801      op0 is used as an index or base register in op3, since this combination
3802      will require reloading.  */
3803   if (GET_CODE (op0) == REG
3804       && GET_CODE (op3) == MEM
3805       && reg_mentioned_p (op0, XEXP (op3, 0)))
3806     return 0;
3807
3808   return 1;
3809 }
3810
3811
3812 int
3813 valid_parallel_operands_6 (operands, mode)
3814      rtx *operands;
3815      enum machine_mode mode ATTRIBUTE_UNUSED;
3816 {
3817   int regs = 0;
3818   rtx op0 = operands[0];
3819   rtx op1 = operands[1];
3820   rtx op2 = operands[2];
3821   rtx op4 = operands[4];
3822   rtx op5 = operands[5];
3823
3824   if (GET_CODE (op1) == SUBREG)
3825     op1 = SUBREG_REG (op1);
3826   if (GET_CODE (op2) == SUBREG)
3827     op2 = SUBREG_REG (op2);
3828   if (GET_CODE (op4) == SUBREG)
3829     op4 = SUBREG_REG (op4);
3830   if (GET_CODE (op5) == SUBREG)
3831     op5 = SUBREG_REG (op5);
3832
3833   /* The patterns should only allow ext_low_reg_operand() or
3834      par_ind_operand() operands.  Thus of the 4 input operands, only 2
3835      should be REGs and the other 2 should be MEMs.  */
3836
3837   if (GET_CODE (op1) == REG)
3838     regs++;
3839   if (GET_CODE (op2) == REG)
3840     regs++;
3841   if (GET_CODE (op4) == REG)
3842     regs++;
3843   if (GET_CODE (op5) == REG)
3844     regs++;
3845
3846   /* The new C30/C40 silicon dies allow 3 regs of the 4 input operands. 
3847      Perhaps we should count the MEMs as well?  */
3848   if (regs != 2)
3849     return 0;
3850
3851   /* This test prevents the multipack pass from using this pattern if
3852      op0 is used as an index or base register in op4 or op5, since
3853      this combination will require reloading.  */
3854   if (GET_CODE (op0) == REG
3855       && ((GET_CODE (op4) == MEM && reg_mentioned_p (op0, XEXP (op4, 0)))
3856           || (GET_CODE (op5) == MEM && reg_mentioned_p (op0, XEXP (op5, 0)))))
3857     return 0;
3858
3859   return 1;
3860 }
3861
3862
3863 /* Validate combination of src operands.  Note that the operands have
3864    been screened by the src_operand predicate.  We just have to check
3865    that the combination of operands is valid.  If FORCE is set, ensure
3866    that the destination regno is valid if we have a 2 operand insn.  */
3867
3868 static int
3869 c4x_valid_operands (code, operands, mode, force)
3870      enum rtx_code code;
3871      rtx *operands;
3872      enum machine_mode mode ATTRIBUTE_UNUSED;
3873      int force;
3874 {
3875   rtx op1;
3876   rtx op2;
3877   enum rtx_code code1;
3878   enum rtx_code code2;
3879
3880   if (code == COMPARE)
3881     {
3882       op1 = operands[0];
3883       op2 = operands[1];
3884     }
3885   else
3886     {
3887       op1 = operands[1];
3888       op2 = operands[2];
3889     }
3890
3891   if (GET_CODE (op1) == SUBREG)
3892     op1 = SUBREG_REG (op1);
3893   if (GET_CODE (op2) == SUBREG)
3894     op2 = SUBREG_REG (op2);
3895
3896   code1 = GET_CODE (op1);
3897   code2 = GET_CODE (op2);
3898
3899   if (code1 == REG && code2 == REG)
3900     return 1;
3901
3902   if (code1 == MEM && code2 == MEM)
3903     {
3904       if (c4x_S_indirect (op1) && c4x_S_indirect (op2))
3905         return 1;
3906       return c4x_R_indirect (op1) && c4x_R_indirect (op2);
3907     }
3908
3909   if (code1 == code2)
3910     return 0;
3911
3912   if (code1 == REG)
3913     {
3914       switch (code2)
3915         {
3916         case CONST_INT:
3917           if (c4x_J_constant (op2) && c4x_R_indirect (op1))
3918             return 1;
3919           break;
3920           
3921         case CONST_DOUBLE:
3922           if (! c4x_H_constant (op2))
3923             return 0;
3924           break;
3925
3926           /* Any valid memory operand screened by src_operand is OK.  */
3927         case MEM:
3928           
3929           /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
3930              into a stack slot memory address comprising a PLUS and a
3931              constant.  */
3932         case ADDRESSOF:
3933           break;
3934           
3935         default:
3936           fatal_insn ("c4x_valid_operands: Internal error", op2);
3937           break;
3938         }
3939       
3940       /* Check that we have a valid destination register for a two operand
3941          instruction.  */
3942       return ! force || code == COMPARE || REGNO (op1) == REGNO (operands[0]);
3943     }
3944
3945   /* We assume MINUS is commutative since the subtract patterns
3946      also support the reverse subtract instructions.  Since op1
3947      is not a register, and op2 is a register, op1 can only
3948      be a restricted memory operand for a shift instruction.  */
3949   if (code == ASHIFTRT || code == LSHIFTRT
3950       || code == ASHIFT || code == COMPARE)
3951     return code2 == REG
3952       && (c4x_S_indirect (op1) || c4x_R_indirect (op1));
3953   
3954   switch (code1)
3955     {
3956     case CONST_INT:
3957       if (c4x_J_constant (op1) && c4x_R_indirect (op2))
3958         return 1;
3959       break;
3960       
3961     case CONST_DOUBLE:
3962       if (! c4x_H_constant (op1))
3963         return 0;
3964       break;
3965
3966       /* Any valid memory operand screened by src_operand is OK.  */      
3967     case MEM:
3968 #if 0
3969       if (code2 != REG)
3970         return 0;
3971 #endif
3972       break;
3973
3974       /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
3975          into a stack slot memory address comprising a PLUS and a
3976          constant.  */
3977     case ADDRESSOF:
3978       break;
3979       
3980     default:
3981       abort ();
3982       break;
3983     }
3984       
3985   /* Check that we have a valid destination register for a two operand
3986      instruction.  */
3987   return ! force || REGNO (op1) == REGNO (operands[0]);
3988 }
3989
3990
3991 int valid_operands (code, operands, mode)
3992      enum rtx_code code;
3993      rtx *operands;
3994      enum machine_mode mode;
3995 {
3996
3997   /* If we are not optimizing then we have to let anything go and let
3998      reload fix things up.  instantiate_decl in function.c can produce
3999      invalid insns by changing the offset of a memory operand from a
4000      valid one into an invalid one, when the second operand is also a
4001      memory operand.  The alternative is not to allow two memory
4002      operands for an insn when not optimizing.  The problem only rarely
4003      occurs, for example with the C-torture program DFcmp.c.  */
4004
4005   return ! optimize || c4x_valid_operands (code, operands, mode, 0);
4006 }
4007
4008
4009 int
4010 legitimize_operands (code, operands, mode)
4011      enum rtx_code code;
4012      rtx *operands;
4013      enum machine_mode mode;
4014 {
4015   /* Compare only has 2 operands.  */
4016   if (code == COMPARE)
4017     {
4018       /* During RTL generation, force constants into pseudos so that
4019          they can get hoisted out of loops.  This will tie up an extra
4020          register but can save an extra cycle.  Only do this if loop
4021          optimisation enabled.  (We cannot pull this trick for add and
4022          sub instructions since the flow pass won't find
4023          autoincrements etc.)  This allows us to generate compare
4024          instructions like CMPI R0, *AR0++ where R0 = 42, say, instead
4025          of LDI *AR0++, R0; CMPI 42, R0. 
4026
4027          Note that expand_binops will try to load an expensive constant
4028          into a register if it is used within a loop.  Unfortunately,
4029          the cost mechanism doesn't allow us to look at the other
4030          operand to decide whether the constant is expensive.  */
4031       
4032       if (! reload_in_progress
4033           && TARGET_HOIST
4034           && optimize > 0
4035           && GET_CODE (operands[1]) == CONST_INT 
4036           && preserve_subexpressions_p ()
4037           && rtx_cost (operands[1], code) > 1)
4038         operands[1] = force_reg (mode, operands[1]);
4039       
4040       if (! reload_in_progress
4041           && ! c4x_valid_operands (code, operands, mode, 0))
4042         operands[0] = force_reg (mode, operands[0]);
4043       return 1;
4044     }
4045   
4046   /* We cannot do this for ADDI/SUBI insns since we will
4047      defeat the flow pass from finding autoincrement addressing
4048      opportunities.  */
4049   if (! reload_in_progress
4050       && ! ((code == PLUS || code == MINUS) && mode == Pmode)
4051       && TARGET_HOIST
4052       && optimize > 1
4053       && GET_CODE (operands[2]) == CONST_INT
4054       && preserve_subexpressions_p ()
4055       && rtx_cost (operands[2], code) > 1)
4056     operands[2] = force_reg (mode, operands[2]);
4057
4058   /* We can get better code on a C30 if we force constant shift counts
4059      into a register.  This way they can get hoisted out of loops,
4060      tying up a register, but saving an instruction.  The downside is
4061      that they may get allocated to an address or index register, and
4062      thus we will get a pipeline conflict if there is a nearby
4063      indirect address using an address register. 
4064
4065      Note that expand_binops will not try to load an expensive constant
4066      into a register if it is used within a loop for a shift insn.  */
4067   
4068   if (! reload_in_progress
4069       && ! c4x_valid_operands (code, operands, mode, TARGET_FORCE))
4070     {
4071       /* If the operand combination is invalid, we force operand1 into a
4072          register, preventing reload from having doing to do this at a
4073          later stage.  */
4074       operands[1] = force_reg (mode, operands[1]);
4075       if (TARGET_FORCE)
4076         {
4077           emit_move_insn (operands[0], operands[1]);
4078           operands[1] = copy_rtx (operands[0]);
4079         }
4080       else
4081         {
4082           /* Just in case...  */
4083           if (! c4x_valid_operands (code, operands, mode, 0))
4084             operands[2] = force_reg (mode, operands[2]);
4085         }
4086     }
4087
4088   /* Right shifts require a negative shift count, but GCC expects
4089      a positive count, so we emit a NEG.  */
4090   if ((code == ASHIFTRT || code == LSHIFTRT)
4091       && (GET_CODE (operands[2]) != CONST_INT))
4092     operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2]));
4093   
4094   return 1;
4095 }
4096
4097
4098 /* The following predicates are used for instruction scheduling.  */
4099
4100 int
4101 group1_reg_operand (op, mode)
4102      rtx op;
4103      enum machine_mode mode;
4104 {
4105   if (mode != VOIDmode && mode != GET_MODE (op))
4106     return 0;
4107   if (GET_CODE (op) == SUBREG)
4108     op = SUBREG_REG (op);
4109   return REG_P (op) && (! reload_completed || IS_GROUP1_REG (op));
4110 }
4111
4112
4113 int
4114 group1_mem_operand (op, mode)
4115      rtx op;
4116      enum machine_mode mode;
4117 {
4118   if (mode != VOIDmode && mode != GET_MODE (op))
4119     return 0;
4120
4121   if (GET_CODE (op) == MEM)
4122     {
4123       op = XEXP (op, 0);
4124       if (GET_CODE (op) == PLUS)
4125         {
4126           rtx op0 = XEXP (op, 0);
4127           rtx op1 = XEXP (op, 1);
4128
4129           if ((REG_P (op0) && (! reload_completed || IS_GROUP1_REG (op0)))
4130               || (REG_P (op1) && (! reload_completed || IS_GROUP1_REG (op1))))
4131             return 1;
4132         }
4133       else if ((REG_P (op)) && (! reload_completed || IS_GROUP1_REG (op)))
4134         return 1;
4135     }
4136
4137   return 0;
4138 }
4139
4140
4141 /* Return true if any one of the address registers.  */
4142
4143 int
4144 arx_reg_operand (op, mode)
4145      rtx op;
4146      enum machine_mode mode;
4147 {
4148   if (mode != VOIDmode && mode != GET_MODE (op))
4149     return 0;
4150   if (GET_CODE (op) == SUBREG)
4151     op = SUBREG_REG (op);
4152   return REG_P (op) && (! reload_completed || IS_ADDR_REG (op));
4153 }
4154
4155
4156 static int
4157 c4x_arn_reg_operand (op, mode, regno)
4158      rtx op;
4159      enum machine_mode mode;
4160      unsigned int regno;
4161 {
4162   if (mode != VOIDmode && mode != GET_MODE (op))
4163     return 0;
4164   if (GET_CODE (op) == SUBREG)
4165     op = SUBREG_REG (op);
4166   return REG_P (op) && (! reload_completed || (REGNO (op) == regno));
4167 }
4168
4169
4170 static int
4171 c4x_arn_mem_operand (op, mode, regno)
4172      rtx op;
4173      enum machine_mode mode;
4174      unsigned int regno;
4175 {
4176   if (mode != VOIDmode && mode != GET_MODE (op))
4177     return 0;
4178
4179   if (GET_CODE (op) == MEM)
4180     {
4181       op = XEXP (op, 0);
4182       switch (GET_CODE (op))
4183         {
4184         case PRE_DEC:
4185         case POST_DEC:
4186         case PRE_INC:
4187         case POST_INC:
4188           op = XEXP (op, 0);
4189
4190         case REG:
4191           return REG_P (op) && (! reload_completed || (REGNO (op) == regno));
4192
4193         case PRE_MODIFY:
4194         case POST_MODIFY:
4195           if (REG_P (XEXP (op, 0)) && (! reload_completed 
4196                                        || (REGNO (XEXP (op, 0)) == regno)))
4197             return 1;
4198           if (REG_P (XEXP (XEXP (op, 1), 1))
4199               && (! reload_completed
4200                   || (REGNO (XEXP (XEXP (op, 1), 1)) == regno)))
4201             return 1;
4202           break;
4203
4204         case PLUS:
4205           {
4206             rtx op0 = XEXP (op, 0);
4207             rtx op1 = XEXP (op, 1);
4208
4209             if ((REG_P (op0) && (! reload_completed
4210                                  || (REGNO (op0) == regno)))
4211                 || (REG_P (op1) && (! reload_completed
4212                                     || (REGNO (op1) == regno))))
4213               return 1;
4214           }
4215           break;
4216
4217         default:
4218           break;
4219         }
4220     }
4221   return 0;
4222 }
4223
4224
4225 int
4226 ar0_reg_operand (op, mode)
4227      rtx op;
4228      enum machine_mode mode;
4229 {
4230   return c4x_arn_reg_operand (op, mode, AR0_REGNO);
4231 }
4232
4233
4234 int
4235 ar0_mem_operand (op, mode)
4236      rtx op;
4237      enum machine_mode mode;
4238 {
4239   return c4x_arn_mem_operand (op, mode, AR0_REGNO);
4240 }
4241
4242
4243 int
4244 ar1_reg_operand (op, mode)
4245      rtx op;
4246      enum machine_mode mode;
4247 {
4248   return c4x_arn_reg_operand (op, mode, AR1_REGNO);
4249 }
4250
4251
4252 int
4253 ar1_mem_operand (op, mode)
4254      rtx op;
4255      enum machine_mode mode;
4256 {
4257   return c4x_arn_mem_operand (op, mode, AR1_REGNO);
4258 }
4259
4260
4261 int
4262 ar2_reg_operand (op, mode)
4263      rtx op;
4264      enum machine_mode mode;
4265 {
4266   return c4x_arn_reg_operand (op, mode, AR2_REGNO);
4267 }
4268
4269
4270 int
4271 ar2_mem_operand (op, mode)
4272      rtx op;
4273      enum machine_mode mode;
4274 {
4275   return c4x_arn_mem_operand (op, mode, AR2_REGNO);
4276 }
4277
4278
4279 int
4280 ar3_reg_operand (op, mode)
4281      rtx op;
4282      enum machine_mode mode;
4283 {
4284   return c4x_arn_reg_operand (op, mode, AR3_REGNO);
4285 }
4286
4287
4288 int
4289 ar3_mem_operand (op, mode)
4290      rtx op;
4291      enum machine_mode mode;
4292 {
4293   return c4x_arn_mem_operand (op, mode, AR3_REGNO);
4294 }
4295
4296
4297 int
4298 ar4_reg_operand (op, mode)
4299      rtx op;
4300      enum machine_mode mode;
4301 {
4302   return c4x_arn_reg_operand (op, mode, AR4_REGNO);
4303 }
4304
4305
4306 int
4307 ar4_mem_operand (op, mode)
4308      rtx op;
4309      enum machine_mode mode;
4310 {
4311   return c4x_arn_mem_operand (op, mode, AR4_REGNO);
4312 }
4313
4314
4315 int
4316 ar5_reg_operand (op, mode)
4317      rtx op;
4318      enum machine_mode mode;
4319 {
4320   return c4x_arn_reg_operand (op, mode, AR5_REGNO);
4321 }
4322
4323
4324 int
4325 ar5_mem_operand (op, mode)
4326      rtx op;
4327      enum machine_mode mode;
4328 {
4329   return c4x_arn_mem_operand (op, mode, AR5_REGNO);
4330 }
4331
4332
4333 int
4334 ar6_reg_operand (op, mode)
4335      rtx op;
4336      enum machine_mode mode;
4337 {
4338   return c4x_arn_reg_operand (op, mode, AR6_REGNO);
4339 }
4340
4341
4342 int
4343 ar6_mem_operand (op, mode)
4344      rtx op;
4345      enum machine_mode mode;
4346 {
4347   return c4x_arn_mem_operand (op, mode, AR6_REGNO);
4348 }
4349
4350
4351 int
4352 ar7_reg_operand (op, mode)
4353      rtx op;
4354      enum machine_mode mode;
4355 {
4356   return c4x_arn_reg_operand (op, mode, AR7_REGNO);
4357 }
4358
4359
4360 int
4361 ar7_mem_operand (op, mode)
4362      rtx op;
4363      enum machine_mode mode;
4364 {
4365   return c4x_arn_mem_operand (op, mode, AR7_REGNO);
4366 }
4367
4368
4369 int
4370 ir0_reg_operand (op, mode)
4371      rtx op;
4372      enum machine_mode mode;
4373 {
4374   return c4x_arn_reg_operand (op, mode, IR0_REGNO);
4375 }
4376
4377
4378 int
4379 ir0_mem_operand (op, mode)
4380      rtx op;
4381      enum machine_mode mode;
4382 {
4383   return c4x_arn_mem_operand (op, mode, IR0_REGNO);
4384 }
4385
4386
4387 int
4388 ir1_reg_operand (op, mode)
4389      rtx op;
4390      enum machine_mode mode;
4391 {
4392   return c4x_arn_reg_operand (op, mode, IR1_REGNO);
4393 }
4394
4395
4396 int
4397 ir1_mem_operand (op, mode)
4398      rtx op;
4399      enum machine_mode mode;
4400 {
4401   return c4x_arn_mem_operand (op, mode, IR1_REGNO);
4402 }
4403
4404
4405 /* This is similar to operand_subword but allows autoincrement
4406    addressing.  */
4407
4408 rtx
4409 c4x_operand_subword (op, i, validate_address, mode)
4410      rtx op;
4411      int i;
4412      int validate_address;
4413      enum machine_mode mode;
4414 {
4415   if (mode != HImode && mode != HFmode)
4416     fatal_insn ("c4x_operand_subword: invalid mode", op);
4417
4418   if (mode == HFmode && REG_P (op))
4419     fatal_insn ("c4x_operand_subword: invalid operand", op);
4420
4421   if (GET_CODE (op) == MEM)
4422     {
4423       enum rtx_code code = GET_CODE (XEXP (op, 0));
4424       enum machine_mode mode = GET_MODE (XEXP (op, 0));
4425       enum machine_mode submode;
4426
4427       submode = mode;
4428       if (mode == HImode)
4429         submode = QImode;
4430       else if (mode == HFmode)
4431         submode = QFmode;
4432
4433       switch (code)
4434         {
4435         case POST_INC:
4436         case PRE_INC:
4437           return gen_rtx_MEM (submode, XEXP (op, 0));
4438           
4439         case POST_DEC:
4440         case PRE_DEC:
4441         case PRE_MODIFY:
4442         case POST_MODIFY:
4443           /* We could handle these with some difficulty.
4444              e.g., *p-- => *(p-=2); *(p+1).  */
4445           fatal_insn ("c4x_operand_subword: invalid autoincrement", op);
4446
4447         case SYMBOL_REF:
4448         case LABEL_REF:
4449         case CONST:
4450         case CONST_INT:
4451           fatal_insn ("c4x_operand_subword: invalid address", op);
4452
4453           /* Even though offsettable_address_p considers (MEM
4454              (LO_SUM)) to be offsettable, it is not safe if the
4455              address is at the end of the data page since we also have
4456              to fix up the associated high PART.  In this case where
4457              we are trying to split a HImode or HFmode memory
4458              reference, we would have to emit another insn to reload a
4459              new HIGH value.  It's easier to disable LO_SUM memory references
4460              in HImode or HFmode and we probably get better code.  */
4461         case LO_SUM:
4462           fatal_insn ("c4x_operand_subword: address not offsettable", op);
4463   
4464         default:
4465           break;
4466         }
4467     }
4468   
4469   return operand_subword (op, i, validate_address, mode);
4470 }
4471
4472 struct name_list
4473 {
4474   struct name_list *next;
4475   const char *name;
4476 };
4477
4478 static struct name_list *global_head;
4479 static struct name_list *extern_head;
4480
4481
4482 /* Add NAME to list of global symbols and remove from external list if
4483    present on external list.  */
4484
4485 void
4486 c4x_global_label (name)
4487      const char *name;
4488 {
4489   struct name_list *p, *last;
4490
4491   /* Do not insert duplicate names, so linearly search through list of
4492      existing names.  */
4493   p = global_head;
4494   while (p)
4495     {
4496       if (strcmp (p->name, name) == 0)
4497         return;
4498       p = p->next;
4499     }
4500   p = (struct name_list *) xmalloc (sizeof *p);
4501   p->next = global_head;
4502   p->name = name;
4503   global_head = p;
4504
4505   /* Remove this name from ref list if present.  */
4506   last = NULL;
4507   p = extern_head;
4508   while (p)
4509     {
4510       if (strcmp (p->name, name) == 0)
4511         {
4512           if (last)
4513             last->next = p->next;
4514           else
4515             extern_head = p->next;
4516           break;
4517         }
4518       last = p;
4519       p = p->next;
4520     }
4521 }
4522
4523
4524 /* Add NAME to list of external symbols.  */
4525
4526 void
4527 c4x_external_ref (name)
4528      const char *name;
4529 {
4530   struct name_list *p;
4531
4532   /* Do not insert duplicate names.  */
4533   p = extern_head;
4534   while (p)
4535     {
4536       if (strcmp (p->name, name) == 0)
4537         return;
4538       p = p->next;
4539     }
4540   
4541   /* Do not insert ref if global found.  */
4542   p = global_head;
4543   while (p)
4544     {
4545       if (strcmp (p->name, name) == 0)
4546         return;
4547       p = p->next;
4548     }
4549   p = (struct name_list *) xmalloc (sizeof *p);
4550   p->next = extern_head;
4551   p->name = name;
4552   extern_head = p;
4553 }
4554
4555
4556 void
4557 c4x_file_end (fp)
4558      FILE *fp;
4559 {
4560   struct name_list *p;
4561   
4562   /* Output all external names that are not global.  */
4563   p = extern_head;
4564   while (p)
4565     {
4566       fprintf (fp, "\t.ref\t");
4567       assemble_name (fp, p->name);
4568       fprintf (fp, "\n");
4569       p = p->next;
4570     }
4571   fprintf (fp, "\t.end\n");
4572 }
4573
4574
4575 static void
4576 c4x_check_attribute (attrib, list, decl, attributes)
4577      const char *attrib;
4578      tree list, decl, *attributes;
4579 {
4580   while (list != NULL_TREE
4581          && IDENTIFIER_POINTER (TREE_PURPOSE (list))
4582          != IDENTIFIER_POINTER (DECL_NAME (decl)))
4583     list = TREE_CHAIN (list);
4584   if (list)
4585     *attributes = tree_cons (get_identifier (attrib), TREE_VALUE (list),
4586                              *attributes);
4587 }
4588
4589
4590 static void
4591 c4x_insert_attributes (decl, attributes)
4592      tree decl, *attributes;
4593 {
4594   switch (TREE_CODE (decl))
4595     {
4596     case FUNCTION_DECL:
4597       c4x_check_attribute ("section", code_tree, decl, attributes);
4598       c4x_check_attribute ("const", pure_tree, decl, attributes);
4599       c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes);
4600       c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes);
4601       break;
4602
4603     case VAR_DECL:
4604       c4x_check_attribute ("section", data_tree, decl, attributes);
4605       break;
4606
4607     default:
4608       break;
4609     }
4610 }
4611
4612 /* Table of valid machine attributes.  */
4613 const struct attribute_spec c4x_attribute_table[] =
4614 {
4615   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4616   { "interrupt",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
4617   /* FIXME: code elsewhere in this file treats "naked" as a synonym of
4618      "interrupt"; should it be accepted here?  */
4619   { "assembler",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
4620   { "leaf_pretend", 0, 0, false, true,  true,  c4x_handle_fntype_attribute },
4621   { NULL,           0, 0, false, false, false, NULL }
4622 };
4623
4624 /* Handle an attribute requiring a FUNCTION_TYPE;
4625    arguments as in struct attribute_spec.handler.  */
4626 static tree
4627 c4x_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
4628      tree *node;
4629      tree name;
4630      tree args ATTRIBUTE_UNUSED;
4631      int flags ATTRIBUTE_UNUSED;
4632      bool *no_add_attrs;
4633 {
4634   if (TREE_CODE (*node) != FUNCTION_TYPE)
4635     {
4636       warning ("`%s' attribute only applies to functions",
4637                IDENTIFIER_POINTER (name));
4638       *no_add_attrs = true;
4639     }
4640
4641   return NULL_TREE;
4642 }
4643
4644
4645 /* !!! FIXME to emit RPTS correctly.  */
4646
4647 int
4648 c4x_rptb_rpts_p (insn, op)
4649      rtx insn, op;
4650 {
4651   /* The next insn should be our label marking where the
4652      repeat block starts.  */
4653   insn = NEXT_INSN (insn);
4654   if (GET_CODE (insn) != CODE_LABEL)
4655     {
4656       /* Some insns may have been shifted between the RPTB insn
4657          and the top label... They were probably destined to
4658          be moved out of the loop.  For now, let's leave them
4659          where they are and print a warning.  We should
4660          probably move these insns before the repeat block insn.  */
4661       if (TARGET_DEBUG)
4662         fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n",
4663                    insn);
4664       return 0;
4665     }
4666
4667   /* Skip any notes.  */
4668   insn = next_nonnote_insn (insn);
4669
4670   /* This should be our first insn in the loop.  */
4671   if (! INSN_P (insn))
4672     return 0;
4673
4674   /* Skip any notes.  */
4675   insn = next_nonnote_insn (insn);
4676
4677   if (! INSN_P (insn))
4678     return 0;
4679
4680   if (recog_memoized (insn) != CODE_FOR_rptb_end)
4681     return 0;
4682
4683   if (TARGET_RPTS)
4684     return 1;
4685
4686   return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op));
4687 }
4688
4689
4690 /* Check if register r11 is used as the destination of an insn.  */
4691
4692 static int
4693 c4x_r11_set_p(x)
4694     rtx x;
4695 {
4696   rtx set;
4697   int i, j;
4698   const char *fmt;
4699
4700   if (x == 0)
4701     return 0;
4702
4703   if (INSN_P (x) && GET_CODE (PATTERN (x)) == SEQUENCE)
4704     x = XVECEXP (PATTERN (x), 0, XVECLEN (PATTERN (x), 0) - 1);
4705
4706   if (INSN_P (x) && (set = single_set (x)))
4707     x = SET_DEST (set);
4708
4709   if (GET_CODE (x) == REG && REGNO (x) == R11_REGNO)
4710     return 1;
4711
4712   fmt = GET_RTX_FORMAT (GET_CODE (x));
4713   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
4714     {
4715       if (fmt[i] == 'e')
4716         {
4717           if (c4x_r11_set_p (XEXP (x, i)))
4718             return 1;
4719         }
4720       else if (fmt[i] == 'E')
4721         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
4722           if (c4x_r11_set_p (XVECEXP (x, i, j)))
4723             return 1;
4724     }
4725   return 0;
4726 }
4727
4728
4729 /* The c4x sometimes has a problem when the insn before the laj insn
4730    sets the r11 register.  Check for this situation.  */
4731
4732 int
4733 c4x_check_laj_p (insn)
4734      rtx insn;
4735 {
4736   insn = prev_nonnote_insn (insn);
4737
4738   /* If this is the start of the function no nop is needed.  */
4739   if (insn == 0)
4740     return 0;
4741
4742   /* If the previous insn is a code label we have to insert a nop. This
4743      could be a jump or table jump. We can find the normal jumps by
4744      scanning the function but this will not find table jumps.  */
4745   if (GET_CODE (insn) == CODE_LABEL)
4746     return 1;
4747
4748   /* If the previous insn sets register r11 we have to insert a nop.  */
4749   if (c4x_r11_set_p (insn))
4750     return 1;
4751
4752   /* No nop needed.  */
4753   return 0;
4754 }
4755
4756
4757 /* Adjust the cost of a scheduling dependency.  Return the new cost of
4758    a dependency LINK or INSN on DEP_INSN.  COST is the current cost. 
4759    A set of an address register followed by a use occurs a 2 cycle
4760    stall (reduced to a single cycle on the c40 using LDA), while
4761    a read of an address register followed by a use occurs a single cycle.  */
4762
4763 #define SET_USE_COST    3
4764 #define SETLDA_USE_COST 2
4765 #define READ_USE_COST   2
4766
4767 static int
4768 c4x_adjust_cost (insn, link, dep_insn, cost)
4769      rtx insn;
4770      rtx link;
4771      rtx dep_insn;
4772      int cost;
4773 {
4774   /* Don't worry about this until we know what registers have been
4775      assigned.  */
4776   if (flag_schedule_insns == 0 && ! reload_completed)
4777     return 0;
4778
4779   /* How do we handle dependencies where a read followed by another
4780      read causes a pipeline stall?  For example, a read of ar0 followed
4781      by the use of ar0 for a memory reference.  It looks like we
4782      need to extend the scheduler to handle this case.  */
4783
4784   /* Reload sometimes generates a CLOBBER of a stack slot, e.g.,
4785      (clobber (mem:QI (plus:QI (reg:QI 11 ar3) (const_int 261)))),
4786      so only deal with insns we know about.  */
4787   if (recog_memoized (dep_insn) < 0)
4788     return 0;
4789
4790   if (REG_NOTE_KIND (link) == 0)
4791     {
4792       int max = 0;
4793
4794       /* Data dependency; DEP_INSN writes a register that INSN reads some
4795          cycles later.  */
4796       if (TARGET_C3X)
4797         {
4798           if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn))
4799             max = SET_USE_COST > max ? SET_USE_COST : max;
4800           if (get_attr_readarx (dep_insn) && get_attr_usegroup1 (insn))
4801             max = READ_USE_COST > max ? READ_USE_COST : max;
4802         }
4803       else
4804         {
4805           /* This could be significantly optimized. We should look
4806              to see if dep_insn sets ar0-ar7 or ir0-ir1 and if
4807              insn uses ar0-ar7.  We then test if the same register
4808              is used.  The tricky bit is that some operands will
4809              use several registers...  */
4810           if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn))
4811             max = SET_USE_COST > max ? SET_USE_COST : max;
4812           if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn))
4813             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4814           if (get_attr_readar0 (dep_insn) && get_attr_usear0 (insn))
4815             max = READ_USE_COST > max ? READ_USE_COST : max;
4816
4817           if (get_attr_setar1 (dep_insn) && get_attr_usear1 (insn))
4818             max = SET_USE_COST > max ? SET_USE_COST : max;
4819           if (get_attr_setlda_ar1 (dep_insn) && get_attr_usear1 (insn))
4820             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4821           if (get_attr_readar1 (dep_insn) && get_attr_usear1 (insn))
4822             max = READ_USE_COST > max ? READ_USE_COST : max;
4823
4824           if (get_attr_setar2 (dep_insn) && get_attr_usear2 (insn))
4825             max = SET_USE_COST > max ? SET_USE_COST : max;
4826           if (get_attr_setlda_ar2 (dep_insn) && get_attr_usear2 (insn))
4827             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4828           if (get_attr_readar2 (dep_insn) && get_attr_usear2 (insn))
4829             max = READ_USE_COST > max ? READ_USE_COST : max;
4830
4831           if (get_attr_setar3 (dep_insn) && get_attr_usear3 (insn))
4832             max = SET_USE_COST > max ? SET_USE_COST : max;
4833           if (get_attr_setlda_ar3 (dep_insn) && get_attr_usear3 (insn))
4834             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4835           if (get_attr_readar3 (dep_insn) && get_attr_usear3 (insn))
4836             max = READ_USE_COST > max ? READ_USE_COST : max;
4837
4838           if (get_attr_setar4 (dep_insn) && get_attr_usear4 (insn))
4839             max = SET_USE_COST > max ? SET_USE_COST : max;
4840           if (get_attr_setlda_ar4 (dep_insn) && get_attr_usear4 (insn))
4841             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4842           if (get_attr_readar4 (dep_insn) && get_attr_usear4 (insn))
4843             max = READ_USE_COST > max ? READ_USE_COST : max;
4844
4845           if (get_attr_setar5 (dep_insn) && get_attr_usear5 (insn))
4846             max = SET_USE_COST > max ? SET_USE_COST : max;
4847           if (get_attr_setlda_ar5 (dep_insn) && get_attr_usear5 (insn))
4848             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4849           if (get_attr_readar5 (dep_insn) && get_attr_usear5 (insn))
4850             max = READ_USE_COST > max ? READ_USE_COST : max;
4851
4852           if (get_attr_setar6 (dep_insn) && get_attr_usear6 (insn))
4853             max = SET_USE_COST > max ? SET_USE_COST : max;
4854           if (get_attr_setlda_ar6 (dep_insn) && get_attr_usear6 (insn))
4855             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4856           if (get_attr_readar6 (dep_insn) && get_attr_usear6 (insn))
4857             max = READ_USE_COST > max ? READ_USE_COST : max;
4858
4859           if (get_attr_setar7 (dep_insn) && get_attr_usear7 (insn))
4860             max = SET_USE_COST > max ? SET_USE_COST : max;
4861           if (get_attr_setlda_ar7 (dep_insn) && get_attr_usear7 (insn))
4862             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4863           if (get_attr_readar7 (dep_insn) && get_attr_usear7 (insn))
4864             max = READ_USE_COST > max ? READ_USE_COST : max;
4865
4866           if (get_attr_setir0 (dep_insn) && get_attr_useir0 (insn))
4867             max = SET_USE_COST > max ? SET_USE_COST : max;
4868           if (get_attr_setlda_ir0 (dep_insn) && get_attr_useir0 (insn))
4869             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4870
4871           if (get_attr_setir1 (dep_insn) && get_attr_useir1 (insn))
4872             max = SET_USE_COST > max ? SET_USE_COST : max;
4873           if (get_attr_setlda_ir1 (dep_insn) && get_attr_useir1 (insn))
4874             max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
4875         }
4876
4877       if (max)
4878         cost = max;
4879
4880       /* For other data dependencies, the default cost specified in the
4881          md is correct.  */
4882       return cost;
4883     }
4884   else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
4885     {
4886       /* Anti dependency; DEP_INSN reads a register that INSN writes some
4887          cycles later.  */
4888
4889       /* For c4x anti dependencies, the cost is 0.  */
4890       return 0;
4891     }
4892   else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
4893     {
4894       /* Output dependency; DEP_INSN writes a register that INSN writes some
4895          cycles later.  */
4896
4897       /* For c4x output dependencies, the cost is 0.  */
4898       return 0;
4899     }
4900   else
4901     abort ();
4902 }
4903
4904 void
4905 c4x_init_builtins ()
4906 {
4907   tree endlink = void_list_node;
4908
4909   builtin_function ("fast_ftoi",
4910                     build_function_type 
4911                     (integer_type_node,
4912                      tree_cons (NULL_TREE, double_type_node, endlink)),
4913                     C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
4914   builtin_function ("ansi_ftoi",
4915                     build_function_type 
4916                     (integer_type_node, 
4917                      tree_cons (NULL_TREE, double_type_node, endlink)),
4918                     C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL, NULL_TREE);
4919   if (TARGET_C3X)
4920     builtin_function ("fast_imult",
4921                       build_function_type
4922                       (integer_type_node, 
4923                        tree_cons (NULL_TREE, integer_type_node,
4924                                   tree_cons (NULL_TREE,
4925                                              integer_type_node, endlink))),
4926                       C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL, NULL_TREE);
4927   else
4928     {
4929       builtin_function ("toieee",
4930                         build_function_type 
4931                         (double_type_node,
4932                          tree_cons (NULL_TREE, double_type_node, endlink)),
4933                         C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL, NULL_TREE);
4934       builtin_function ("frieee",
4935                         build_function_type
4936                         (double_type_node, 
4937                          tree_cons (NULL_TREE, double_type_node, endlink)),
4938                         C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL, NULL_TREE);
4939       builtin_function ("fast_invf",
4940                         build_function_type 
4941                         (double_type_node, 
4942                          tree_cons (NULL_TREE, double_type_node, endlink)),
4943                         C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL, NULL_TREE);
4944     }
4945 }
4946
4947
4948 rtx
4949 c4x_expand_builtin (exp, target, subtarget, mode, ignore)
4950      tree exp;
4951      rtx target;
4952      rtx subtarget ATTRIBUTE_UNUSED;
4953      enum machine_mode mode ATTRIBUTE_UNUSED;
4954      int ignore ATTRIBUTE_UNUSED;
4955 {
4956   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4957   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4958   tree arglist = TREE_OPERAND (exp, 1);
4959   tree arg0, arg1;
4960   rtx r0, r1;
4961
4962   switch (fcode)
4963     {
4964     case C4X_BUILTIN_FIX:
4965       arg0 = TREE_VALUE (arglist);
4966       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
4967       r0 = protect_from_queue (r0, 0);
4968       if (! target || ! register_operand (target, QImode))
4969         target = gen_reg_rtx (QImode);
4970       emit_insn (gen_fixqfqi_clobber (target, r0));
4971       return target;
4972
4973     case C4X_BUILTIN_FIX_ANSI:
4974       arg0 = TREE_VALUE (arglist);
4975       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
4976       r0 = protect_from_queue (r0, 0);
4977       if (! target || ! register_operand (target, QImode))
4978         target = gen_reg_rtx (QImode);
4979       emit_insn (gen_fix_truncqfqi2 (target, r0));
4980       return target;
4981
4982     case C4X_BUILTIN_MPYI:
4983       if (! TARGET_C3X)
4984         break;
4985       arg0 = TREE_VALUE (arglist);
4986       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4987       r0 = expand_expr (arg0, NULL_RTX, QImode, 0);
4988       r1 = expand_expr (arg1, NULL_RTX, QImode, 0);
4989       r0 = protect_from_queue (r0, 0);
4990       r1 = protect_from_queue (r1, 0);
4991       if (! target || ! register_operand (target, QImode))
4992         target = gen_reg_rtx (QImode);
4993       emit_insn (gen_mulqi3_24_clobber (target, r0, r1));
4994       return target;
4995
4996     case C4X_BUILTIN_TOIEEE:
4997       if (TARGET_C3X)
4998         break;
4999       arg0 = TREE_VALUE (arglist);
5000       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
5001       r0 = protect_from_queue (r0, 0);
5002       if (! target || ! register_operand (target, QFmode))
5003         target = gen_reg_rtx (QFmode);
5004       emit_insn (gen_toieee (target, r0));
5005       return target;
5006
5007     case C4X_BUILTIN_FRIEEE:
5008       if (TARGET_C3X)
5009         break;
5010       arg0 = TREE_VALUE (arglist);
5011       if (TREE_CODE (arg0) == VAR_DECL || TREE_CODE (arg0) == PARM_DECL)
5012         put_var_into_stack (arg0);
5013       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
5014       r0 = protect_from_queue (r0, 0);
5015       if (register_operand (r0, QFmode))
5016         {
5017           r1 = assign_stack_local (QFmode, GET_MODE_SIZE (QFmode), 0);
5018           emit_move_insn (r1, r0);
5019           r0 = r1;
5020         }
5021       if (! target || ! register_operand (target, QFmode))
5022         target = gen_reg_rtx (QFmode);
5023       emit_insn (gen_frieee (target, r0));
5024       return target;
5025
5026     case C4X_BUILTIN_RCPF:
5027       if (TARGET_C3X)
5028         break;
5029       arg0 = TREE_VALUE (arglist);
5030       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
5031       r0 = protect_from_queue (r0, 0);
5032       if (! target || ! register_operand (target, QFmode))
5033         target = gen_reg_rtx (QFmode);
5034       emit_insn (gen_rcpfqf_clobber (target, r0));
5035       return target;
5036     }
5037   return NULL_RTX;
5038 }
5039
5040 static void
5041 c4x_asm_named_section (name, flags)
5042      const char *name;
5043      unsigned int flags ATTRIBUTE_UNUSED;
5044 {
5045   fprintf (asm_out_file, "\t.sect\t\"%s\"\n", name);
5046 }
5047