af06624e1df6f0eb827efaa163e2dfec80e8d0c9
[platform/upstream/gcc.git] / gcc / config / mmix / mmix.c
1 /* Definitions of target machine for GNU compiler, for MMIX.
2    Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3    Contributed by Hans-Peter Nilsson (hp@bitrange.com)
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "regs.h"
26 #include "hard-reg-set.h"
27 #include "hashtab.h"
28 #include "insn-config.h"
29 #include "output.h"
30 #include "flags.h"
31 #include "tree.h"
32 #include "function.h"
33 #include "expr.h"
34 #include "toplev.h"
35 #include "recog.h"
36 #include "ggc.h"
37 #include "dwarf2.h"
38 #include "debug.h"
39 #include "tm_p.h"
40 #include "integrate.h"
41 #include "target.h"
42 #include "target-def.h"
43
44 /* First some local helper definitions.  */
45 #define MMIX_FIRST_GLOBAL_REGNUM 32
46
47 /* We'd need a current_function_has_landing_pad.  It's marked as such when
48    a nonlocal_goto_receiver is expanded.  Not just a C++ thing, but
49    mostly.  */
50 #define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)
51
52 /* We have no means to tell DWARF 2 about the register stack, so we need
53    to store the return address on the stack if an exception can get into
54    this function.  FIXME: Narrow condition.  */
55 #define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
56  (flag_exceptions && ! leaf_function_p ())
57
58 #define IS_MMIX_EH_RETURN_DATA_REG(REGNO)       \
59  (current_function_calls_eh_return              \
60   && (EH_RETURN_DATA_REGNO (0) == REGNO         \
61       || EH_RETURN_DATA_REGNO (1) == REGNO      \
62       || EH_RETURN_DATA_REGNO (2) == REGNO      \
63       || EH_RETURN_DATA_REGNO (3) == REGNO))
64
65 /* For the default ABI, we rename registers at output-time to fill the gap
66    between the (statically partitioned) saved registers and call-clobbered
67    registers.  In effect this makes unused call-saved registers to be used
68    as call-clobbered registers.  The benefit comes from keeping the number
69    of local registers (value of rL) low, since there's a cost of
70    increasing rL and clearing unused (unset) registers with lower numbers.  */
71 #define MMIX_OUTPUT_REGNO(N)                                    \
72  (TARGET_ABI_GNU                                                \
73   || (N) < MMIX_RETURN_VALUE_REGNUM                             \
74   || (N) > MMIX_LAST_STACK_REGISTER_REGNUM                      \
75   ? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM                       \
76            + cfun->machine->highest_saved_stack_register + 1))
77
78 /* The canonical saved comparison operands for non-cc0 machines, set in
79    the compare expander.  */
80 rtx mmix_compare_op0;
81 rtx mmix_compare_op1;
82
83 /* We ignore some options with arguments.  They are passed to the linker,
84    but also ends up here because they start with "-m".  We tell the driver
85    to store them in a variable we don't inspect.  */
86 const char *mmix_cc1_ignored_option;
87
88 /* Declarations of locals.  */
89
90 /* Intermediate for insn output.  */
91 static int mmix_output_destination_register;
92
93 static void mmix_output_shiftvalue_op_from_str
94   PARAMS ((FILE *, const char *, HOST_WIDEST_INT));
95 static void mmix_output_shifted_value PARAMS ((FILE *, HOST_WIDEST_INT));
96 static void mmix_output_condition PARAMS ((FILE *, rtx, int));
97 static HOST_WIDEST_INT mmix_intval PARAMS ((rtx));
98 static void mmix_output_octa PARAMS ((FILE *, HOST_WIDEST_INT, int));
99 static bool mmix_assemble_integer PARAMS ((rtx, unsigned int, int));
100 static void mmix_init_machine_status PARAMS ((struct function *));
101
102 extern void mmix_target_asm_function_prologue
103   PARAMS ((FILE *, HOST_WIDE_INT));
104 extern void mmix_target_asm_function_epilogue
105   PARAMS ((FILE *, HOST_WIDE_INT));
106
107
108 /* Target structure macros.  Listed by node.  See `Using and Porting GCC'
109    for a general description.  */
110
111 /* Node: Function Entry */
112
113 #undef TARGET_ASM_BYTE_OP
114 #define TARGET_ASM_BYTE_OP NULL
115 #undef TARGET_ASM_ALIGNED_HI_OP
116 #define TARGET_ASM_ALIGNED_HI_OP NULL
117 #undef TARGET_ASM_ALIGNED_SI_OP
118 #define TARGET_ASM_ALIGNED_SI_OP NULL
119 #undef TARGET_ASM_ALIGNED_DI_OP
120 #define TARGET_ASM_ALIGNED_DI_OP NULL
121 #undef TARGET_ASM_INTEGER
122 #define TARGET_ASM_INTEGER mmix_assemble_integer
123
124 #undef TARGET_ASM_FUNCTION_PROLOGUE
125 #define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
126
127 #undef TARGET_ASM_FUNCTION_EPILOGUE
128 #define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
129
130 struct gcc_target targetm = TARGET_INITIALIZER;
131
132 /* Functions that are expansions for target macros.
133    See Target Macros in `Using and Porting GCC'.  */
134
135 /* OVERRIDE_OPTIONS.  */
136
137 void
138 mmix_override_options ()
139 {
140   /* Should we err or should we warn?  Hmm.  At least we must neutralize
141      it.  For example the wrong kind of case-tables will be generated with
142      PIC; we use absolute address items for mmixal compatibility.  FIXME:
143      They could be relative if we just elide them to after all pertinent
144      labels.  */
145   if (flag_pic)
146     {
147       warning ("-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
148       flag_pic = 0;
149     }
150
151   /* All other targets add GC roots from their override_options function,
152      so play along.  */
153   ggc_add_rtx_root (&mmix_compare_op0, 1);
154   ggc_add_rtx_root (&mmix_compare_op1, 1);
155 }
156
157 /* INIT_EXPANDERS.  */
158
159 void
160 mmix_init_expanders ()
161 {
162   init_machine_status = mmix_init_machine_status;
163 }
164
165 /* Set the per-function data.  */
166
167 static void
168 mmix_init_machine_status (f)
169      struct function *f;
170 {
171   f->machine = xcalloc (1, sizeof (struct machine_function));
172 }
173
174 /* DATA_ALIGNMENT.
175    We have trouble getting the address of stuff that is located at other
176    than 32-bit alignments (GETA requirements), so try to give everything
177    at least 32-bit alignment. */
178
179 int
180 mmix_data_alignment (type, basic_align)
181      tree type ATTRIBUTE_UNUSED;
182      int basic_align;
183 {
184   if (basic_align < 32)
185     return 32;
186
187   return basic_align;
188 }
189
190 /* CONSTANT_ALIGNMENT.  */
191
192 int
193 mmix_constant_alignment (constant, basic_align)
194      tree constant ATTRIBUTE_UNUSED;
195      int basic_align;
196 {
197   if (basic_align < 32)
198     return 32;
199
200   return basic_align;
201 }
202
203 /* LOCAL_ALIGNMENT.  */
204
205 int
206 mmix_local_alignment (type, basic_align)
207      tree type ATTRIBUTE_UNUSED;
208      int basic_align;
209 {
210   if (basic_align < 32)
211     return 32;
212
213   return basic_align;
214 }
215
216 /* CONDITIONAL_REGISTER_USAGE.  */
217
218 void
219 mmix_conditional_register_usage ()
220 {
221   int i;
222
223   if (TARGET_ABI_GNU)
224     {
225       static const int gnu_abi_reg_alloc_order[]
226         = MMIX_GNU_ABI_REG_ALLOC_ORDER;
227
228       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
229         reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];
230
231       /* Change the default from the mmixware ABI.  For the GNU ABI,
232          $15..$30 are call-saved just as $0..$14.  There must be one
233          call-clobbered local register for the "hole" describing number of
234          saved local registers saved by PUSHJ/PUSHGO during the function
235          call, receiving the return value at return.  So best is to use
236          the highest, $31.  It's already marked call-clobbered for the
237          mmixware ABI.  */
238       for (i = 15; i <= 30; i++)
239         call_used_regs[i] = 0;
240
241       /* "Unfix" the parameter registers.  */
242       for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
243            i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
244            i++)
245         fixed_regs[i] = 0;
246     }
247
248   /* Step over the ":" in special register names.  */
249   if (! TARGET_TOPLEVEL_SYMBOLS)
250     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
251       if (reg_names[i][0] == ':')
252         reg_names[i]++;
253 }
254
255 /* PREFERRED_RELOAD_CLASS.
256    We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */
257
258 enum reg_class
259 mmix_preferred_reload_class (x, class)
260      rtx x ATTRIBUTE_UNUSED;
261      enum reg_class class;
262 {
263   /* FIXME: Revisit.  */
264   return GET_CODE (x) == MOD && GET_MODE (x) == DImode
265     ? REMAINDER_REG : class;
266 }
267
268 /* PREFERRED_OUTPUT_RELOAD_CLASS.
269    We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */
270
271 enum reg_class
272 mmix_preferred_output_reload_class (x, class)
273      rtx x ATTRIBUTE_UNUSED;
274      enum reg_class class;
275 {
276   /* FIXME: Revisit.  */
277   return GET_CODE (x) == MOD && GET_MODE (x) == DImode
278     ? REMAINDER_REG : class;
279 }
280
281 /* SECONDARY_RELOAD_CLASS.
282    We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere.  */
283
284 enum reg_class
285 mmix_secondary_reload_class (class, mode, x, in_p)
286      enum reg_class class;
287      enum machine_mode mode ATTRIBUTE_UNUSED;
288      rtx x ATTRIBUTE_UNUSED;
289      int in_p ATTRIBUTE_UNUSED;
290 {
291   if (class == REMAINDER_REG
292       || class == HIMULT_REG
293       || class == SYSTEM_REGS)
294     return GENERAL_REGS;
295
296   return NO_REGS;
297 }
298
299 /* CONST_OK_FOR_LETTER_P.  */
300
301 int
302 mmix_const_ok_for_letter_p (value, c)
303      HOST_WIDE_INT value;
304      int c;
305 {
306   return
307     (c == 'I' ? value >= 0 && value <= 255
308      : c == 'J' ? value >= 0 && value <= 65535
309      : c == 'K' ? value <= 0 && value >= -255
310      : c == 'L' ? mmix_shiftable_wyde_value (value)
311      : c == 'M' ? value == 0
312      : c == 'N' ? mmix_shiftable_wyde_value (~value)
313      : c == 'O' ? (value == 3 || value == 5 || value == 9
314                    || value == 17)
315      : 0);
316 }
317
318 /* CONST_DOUBLE_OK_FOR_LETTER_P.  */
319
320 int
321 mmix_const_double_ok_for_letter_p (value, c)
322      rtx value;
323      int c;
324 {
325   return
326     (c == 'G' ? value == CONST0_RTX (GET_MODE (value))
327      : 0);
328 }
329
330 /* EXTRA_CONSTRAINT.
331    We need this since our constants are not always expressible as
332    CONST_INT:s, but rather often as CONST_DOUBLE:s.  */
333
334 int
335 mmix_extra_constraint (x, c, strict)
336      rtx x;
337      int c;
338      int strict;
339 {
340   HOST_WIDEST_INT value;
341
342   /* When checking for an address, we need to handle strict vs. non-strict
343      register checks.  Don't use address_operand, but instead its
344      equivalent (its callee, which it is just a wrapper for),
345      memory_operand_p and the strict-equivalent strict_memory_address_p.  */
346   if (c == 'U')
347     return
348       strict
349       ? strict_memory_address_p (Pmode, x)
350       : memory_address_p (Pmode, x);
351
352   /* R asks whether x is to be loaded with GETA or something else.  Right
353      now, only a SYMBOL_REF and LABEL_REF can fit for
354      TARGET_BASE_ADDRESSES.
355
356      Only constant symbolic addresses apply.  With TARGET_BASE_ADDRESSES,
357      we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG
358      set right now; only function addresses and code labels.  If we change
359      to let SYMBOL_REF_FLAG be set on other symbols, we have to check
360      inside CONST expressions.  When TARGET_BASE_ADDRESSES is not in
361      effect, a "raw" constant check together with mmix_constant_address_p
362      is all that's needed; we want all constant addresses to be loaded
363      with GETA then.  */
364   if (c == 'R')
365     return
366       GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE
367       && mmix_constant_address_p (x)
368       && (! TARGET_BASE_ADDRESSES
369           || (GET_CODE (x) == LABEL_REF
370               || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));
371
372   if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)
373     return 0;
374
375   value = mmix_intval (x);
376
377   /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any
378      more ('U' taken for address_operand, 'R' similarly).  Some letters map
379      outside of CONST_INT, though; we still use 'S' and 'T'.  */
380   if (c == 'S')
381     return mmix_shiftable_wyde_value (value);
382   else if (c == 'T')
383     return mmix_shiftable_wyde_value (~value);
384   return 0;
385 }
386
387 /* DYNAMIC_CHAIN_ADDRESS.  */
388
389 rtx
390 mmix_dynamic_chain_address (frame)
391      rtx frame;
392 {
393   /* FIXME: the frame-pointer is stored at offset -8 from the current
394      frame-pointer.  Unfortunately, the caller assumes that a
395      frame-pointer is present for *all* previous frames.  There should be
396      a way to say that that cannot be done, like for RETURN_ADDR_RTX.  */
397   return plus_constant (frame, -8);
398 }
399
400 /* STARTING_FRAME_OFFSET.  */
401
402 int
403 mmix_starting_frame_offset ()
404 {
405   /* The old frame pointer is in the slot below the new one, so
406      FIRST_PARM_OFFSET does not need to depend on whether the
407      frame-pointer is needed or not.  We have to adjust for the register
408      stack pointer being located below the saved frame pointer.
409      Similarly, we store the return address on the stack too, for
410      exception handling, and always if we save the register stack pointer.  */
411   return
412     (-8
413      + (MMIX_CFUN_HAS_LANDING_PAD
414         ? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0)));
415 }
416
417 /* RETURN_ADDR_RTX.  */
418
419 rtx
420 mmix_return_addr_rtx (count, frame)
421      int count;
422      rtx frame ATTRIBUTE_UNUSED;
423 {
424   return count == 0
425     ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS
426        /* FIXME: Set frame_alias_set on the following.  (Why?)
427           See mmix_initial_elimination_offset for the reason we can't use
428           get_hard_reg_initial_val for both.  Always using a stack slot
429           and not a register would be suboptimal.  */
430        ? validize_mem (gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, -16)))
431        : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
432     : NULL_RTX;
433 }
434
435 /* SETUP_FRAME_ADDRESSES.  */
436
437 void
438 mmix_setup_frame_addresses ()
439 {
440   /* Nothing needed at the moment.  */
441 }
442
443 /* The difference between the (imaginary) frame pointer and the stack
444    pointer.  Used to eliminate the frame pointer.  */
445
446 int
447 mmix_initial_elimination_offset (fromreg, toreg)
448      int fromreg;
449      int toreg;
450 {
451   int regno;
452   int fp_sp_offset
453     = (get_frame_size () + current_function_outgoing_args_size + 7) & ~7;
454
455   /* There is no actual offset between these two virtual values, but for
456      the frame-pointer, we have the old one in the stack position below
457      it, so the offset for the frame-pointer to the stack-pointer is one
458      octabyte larger.  */
459   if (fromreg == MMIX_ARG_POINTER_REGNUM
460       && toreg == MMIX_FRAME_POINTER_REGNUM)
461     return 0;
462
463   /* The difference is the size of local variables plus the size of
464      outgoing function arguments that would normally be passed as
465      registers but must be passed on stack because we're out of
466      function-argument registers.  Only global saved registers are
467      counted; the others go on the register stack.
468
469      The frame-pointer is counted too if it is what is eliminated, as we
470      need to balance the offset for it from STARTING_FRAME_OFFSET.
471
472      Also add in the slot for the register stack pointer we save if we
473      have a landing pad.
474
475      Unfortunately, we can't access $0..$14, from unwinder code easily, so
476      store the return address in a frame slot too.  FIXME: Only for
477      non-leaf functions.  FIXME: Always with a landing pad, because it's
478      hard to know whether we need the other at the time we know we need
479      the offset for one (and have to state it).  It's a kludge until we
480      can express the register stack in the EH frame info.
481
482      We have to do alignment here; get_frame_size will not return a
483      multiple of STACK_BOUNDARY.  FIXME: Add note in manual.  */
484
485   for (regno = MMIX_FIRST_GLOBAL_REGNUM;
486        regno <= 255;
487        regno++)
488     if ((regs_ever_live[regno] && ! call_used_regs[regno])
489         || IS_MMIX_EH_RETURN_DATA_REG (regno))
490       fp_sp_offset += 8;
491
492   return fp_sp_offset
493     + (MMIX_CFUN_HAS_LANDING_PAD
494        ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0))
495     + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8);
496 }
497
498 /* Return an rtx for a function argument to go in a register, and 0 for
499    one that must go on stack.  */
500
501 rtx
502 mmix_function_arg (argsp, mode, type, named, incoming)
503      const CUMULATIVE_ARGS * argsp;
504      enum machine_mode mode;
505      tree type;
506      int named ATTRIBUTE_UNUSED;
507      int incoming;
508 {
509   /* Handling of the positional dummy parameter for varargs gets nasty.
510      Check execute/991216-3 and function.c:assign_params.  We have to say
511      that the dummy parameter goes on stack in order to get the correct
512      offset when va_start and va_arg is applied.  FIXME: Should do TRT by
513      itself in the gcc core.  */
514   if ((! named && incoming && current_function_varargs) || argsp->now_varargs)
515     return NULL_RTX;
516
517   /* Last-argument marker.  */
518   if (type == void_type_node)
519     return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
520       ? gen_rtx_REG (mode,
521                      (incoming
522                       ? MMIX_FIRST_INCOMING_ARG_REGNUM
523                       : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
524       : NULL_RTX;
525
526   return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
527           && !MUST_PASS_IN_STACK (mode, type)
528           && (GET_MODE_BITSIZE (mode) <= 64
529               || argsp->lib
530               || TARGET_LIBFUNC))
531     ? gen_rtx_REG (mode,
532                    (incoming
533                     ? MMIX_FIRST_INCOMING_ARG_REGNUM
534                     : MMIX_FIRST_ARG_REGNUM)
535                    + argsp->regs)
536     : NULL_RTX;
537 }
538
539 /* Returns nonzero for everything that goes by reference, 0 for
540    everything that goes by value.  */
541
542 int
543 mmix_function_arg_pass_by_reference (argsp, mode, type, named)
544      const CUMULATIVE_ARGS * argsp;
545      enum machine_mode mode;
546      tree type;
547      int named ATTRIBUTE_UNUSED;
548 {
549   /* FIXME: Check: I'm not sure the MUST_PASS_IN_STACK check is
550      necessary.  */
551   return
552     MUST_PASS_IN_STACK (mode, type)
553     || (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
554         && !TARGET_LIBFUNC
555         && !argsp->lib);
556 }
557
558 /* Return nonzero if regno is a register number where a parameter is
559    passed, and 0 otherwise.  */
560
561 int
562 mmix_function_arg_regno_p (regno, incoming)
563      int regno;
564      int incoming;
565 {
566   int first_arg_regnum
567     = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM;
568
569   return regno >= first_arg_regnum
570     && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS;
571 }
572
573 /* FUNCTION_OUTGOING_VALUE.  */
574
575 rtx
576 mmix_function_outgoing_value (valtype, func)
577      tree valtype;
578      tree func ATTRIBUTE_UNUSED;
579 {
580   enum machine_mode mode = TYPE_MODE (valtype);
581   enum machine_mode cmode;
582   int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
583   rtx vec[MMIX_MAX_REGS_FOR_VALUE];
584   int i;
585   int nregs;
586
587   /* Return values that fit in a register need no special handling.
588      There's no register hole when parameters are passed in global
589      registers.  */
590   if (TARGET_ABI_GNU
591       || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
592     return
593       gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
594
595   /* A complex type, made up of components.  */
596   cmode = TYPE_MODE (TREE_TYPE (valtype));
597   nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
598
599   /* We need to take care of the effect of the register hole on return
600      values of large sizes; the last register will appear as the first
601      register, with the rest shifted.  (For complex modes, this is just
602      swapped registers.)  */
603
604   if (nregs > MMIX_MAX_REGS_FOR_VALUE)
605     internal_error ("too large function value type, needs %d registers,\
606  have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE);
607
608   /* FIXME: Maybe we should handle structure values like this too
609      (adjusted for BLKmode), perhaps for both ABI:s.  */
610   for (i = 0; i < nregs - 1; i++)
611     vec[i]
612       = gen_rtx_EXPR_LIST (VOIDmode,
613                            gen_rtx_REG (cmode, first_val_regnum + i),
614                            GEN_INT ((i + 1) * BITS_PER_UNIT));
615
616   vec[nregs - 1]
617     = gen_rtx_EXPR_LIST (VOIDmode,
618                          gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
619                          GEN_INT (0));
620
621   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs, vec));
622 }
623
624 /* EH_RETURN_DATA_REGNO. */
625
626 int
627 mmix_eh_return_data_regno (n)
628      int n ATTRIBUTE_UNUSED;
629 {
630   if (n >= 0 && n < 4)
631     return MMIX_EH_RETURN_DATA_REGNO_START + n;
632
633   return INVALID_REGNUM;
634 }
635
636 /* EH_RETURN_STACKADJ_RTX. */
637
638 rtx
639 mmix_eh_return_stackadj_rtx ()
640 {
641   return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM);
642 }
643
644 /* EH_RETURN_HANDLER_RTX.  */
645
646 rtx
647 mmix_eh_return_handler_rtx ()
648 {
649   return
650     gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
651 }
652
653 /* ASM_PREFERRED_EH_DATA_FORMAT. */
654
655 int
656 mmix_asm_preferred_eh_data_format (code, global)
657      int code ATTRIBUTE_UNUSED;
658      int global ATTRIBUTE_UNUSED;
659 {
660   /* This is the default (was at 2001-07-20).  Revisit when needed.  */
661   return DW_EH_PE_absptr;
662 }
663
664 /* Emit the function prologue.  For simplicity while the port is still
665    in a flux, we do it as text rather than the now preferred RTL way,
666    as (define_insn "function_prologue").
667
668    FIXME: Translate to RTL and/or optimize some of the DWARF 2 stuff.  */
669
670 void
671 mmix_target_asm_function_prologue (stream, locals_size)
672      FILE *stream;
673      HOST_WIDE_INT locals_size;
674 {
675   int regno;
676   int stack_space_to_allocate
677     = (current_function_outgoing_args_size
678        + current_function_pretend_args_size
679        + (int) locals_size + 7) & ~7;
680   int offset = -8;
681   int doing_dwarf = dwarf2out_do_frame ();
682   long cfa_offset = 0;
683
684   /* Guard our assumptions.  Very low priority FIXME.  */
685   if (locals_size != (int) locals_size)
686     error ("stack frame too big");
687
688   /* Add room needed to save global non-register-stack registers.  */
689   for (regno = 255;
690        regno >= MMIX_FIRST_GLOBAL_REGNUM;
691        regno--)
692     /* Note that we assume that the frame-pointer-register is one of these
693        registers, in which case we don't count it here.  */
694     if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
695           && regs_ever_live[regno] && !call_used_regs[regno]))
696         || IS_MMIX_EH_RETURN_DATA_REG (regno))
697       stack_space_to_allocate += 8;
698
699   /* If we do have a frame-pointer, add room for it.  */
700   if (frame_pointer_needed)
701     stack_space_to_allocate += 8;
702
703   /* If we have a non-local label, we need to be able to unwind to it, so
704      store the current register stack pointer.  Also store the return
705      address if we do that.  */
706   if (MMIX_CFUN_HAS_LANDING_PAD)
707     stack_space_to_allocate += 16;
708   else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
709     /* If we do have a saved return-address slot, add room for it.  */
710     stack_space_to_allocate += 8;
711
712   /* Make sure we don't get an unaligned stack.  */
713   if ((stack_space_to_allocate % 8) != 0)
714     internal_error ("stack frame not a multiple of 8 bytes: %d",
715                     stack_space_to_allocate);
716
717   if (current_function_pretend_args_size)
718     {
719       int mmix_first_vararg_reg
720         = (MMIX_FIRST_INCOMING_ARG_REGNUM
721            + (MMIX_MAX_ARGS_IN_REGS
722               - current_function_pretend_args_size / 8));
723
724       for (regno
725              = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
726            regno >= mmix_first_vararg_reg;
727            regno--)
728         {
729           if (offset < 0)
730             {
731               int stack_chunk
732                 = stack_space_to_allocate > (256 - 8)
733                 ? (256 - 8) : stack_space_to_allocate;
734
735               fprintf (stream, "\tSUBU %s,%s,%d\n",
736                        reg_names[MMIX_STACK_POINTER_REGNUM],
737                        reg_names[MMIX_STACK_POINTER_REGNUM],
738                        stack_chunk);
739
740               if (doing_dwarf)
741                 {
742                   /* Each call to dwarf2out_def_cfa overrides the previous
743                      setting; they don't accumulate.  We must keep track
744                      of the offset ourselves.  */
745                   cfa_offset += stack_chunk;
746                   if (!frame_pointer_needed)
747                     dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
748                                        cfa_offset);
749                 }
750               offset += stack_chunk;
751               stack_space_to_allocate -= stack_chunk;
752             }
753
754           fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
755                    reg_names[MMIX_STACK_POINTER_REGNUM],
756                    offset);
757
758           /* These registers aren't actually saved (as in "will be
759              restored"), so don't tell DWARF2 they're saved.  */
760
761           offset -= 8;
762         }
763     }
764
765   /* Store the frame-pointer.  */
766
767   if (frame_pointer_needed)
768     {
769       if (offset < 0)
770         {
771           /* Get 8 less than otherwise, since we need to reach offset + 8.  */
772           int stack_chunk
773             = stack_space_to_allocate > (256 - 8 - 8)
774             ? (256 - 8 - 8) : stack_space_to_allocate;
775
776           fprintf (stream, "\tSUBU %s,%s,%d\n",
777                    reg_names[MMIX_STACK_POINTER_REGNUM],
778                    reg_names[MMIX_STACK_POINTER_REGNUM],
779                    stack_chunk);
780           if (doing_dwarf)
781             cfa_offset += stack_chunk;
782           offset += stack_chunk;
783           stack_space_to_allocate -= stack_chunk;
784         }
785
786       fprintf (stream, "\tSTOU %s,%s,%d\n\tADDU %s,%s,%d\n",
787                reg_names[MMIX_FRAME_POINTER_REGNUM],
788                reg_names[MMIX_STACK_POINTER_REGNUM],
789                offset,
790                reg_names[MMIX_FRAME_POINTER_REGNUM],
791                reg_names[MMIX_STACK_POINTER_REGNUM],
792                offset + 8);
793       if (doing_dwarf)
794         {
795           /* If we're using the frame-pointer, then we just need this CFA
796              definition basing on that value (often equal to the CFA).
797              Further changes to the stack-pointer do not affect the
798              frame-pointer, so we conditionalize them below on
799              !frame_pointer_needed.  */
800           dwarf2out_def_cfa ("", MMIX_FRAME_POINTER_REGNUM,
801                              -cfa_offset + offset + 8);
802
803           dwarf2out_reg_save ("", MMIX_FRAME_POINTER_REGNUM,
804                               -cfa_offset + offset);
805         }
806
807       offset -= 8;
808     }
809
810   if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
811     {
812       /* Store the return-address, if one is needed on the stack.  We
813          usually store it in a register when needed, but that doesn't work
814          with -fexceptions.  */
815
816       if (offset < 0)
817         {
818           /* Get 8 less than otherwise, since we need to reach offset + 8.  */
819           int stack_chunk
820             = stack_space_to_allocate > (256 - 8 - 8)
821             ? (256 - 8 - 8) : stack_space_to_allocate;
822
823           fprintf (stream, "\tSUBU %s,%s,%d\n",
824                    reg_names[MMIX_STACK_POINTER_REGNUM],
825                    reg_names[MMIX_STACK_POINTER_REGNUM],
826                    stack_chunk);
827           if (doing_dwarf)
828             {
829               cfa_offset += stack_chunk;
830               if (!frame_pointer_needed)
831                 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
832                                    cfa_offset);
833             }
834           offset += stack_chunk;
835           stack_space_to_allocate -= stack_chunk;
836         }
837
838       fprintf (stream, "\tGET $255,rJ\n\tSTOU $255,%s,%d\n",
839                reg_names[MMIX_STACK_POINTER_REGNUM],
840                offset);
841       if (doing_dwarf)
842         dwarf2out_return_save ("", -cfa_offset + offset);
843       offset -= 8;
844     }
845   else if (MMIX_CFUN_HAS_LANDING_PAD)
846     offset -= 8;
847
848   if (MMIX_CFUN_HAS_LANDING_PAD)
849     {
850       /* Store the register defining the numbering of local registers, so
851          we know how long to unwind the register stack.  */
852
853       if (offset < 0)
854         {
855           /* Get 8 less than otherwise, since we need to reach offset + 8.  */
856           int stack_chunk
857             = stack_space_to_allocate > (256 - 8 - 8)
858             ? (256 - 8 - 8) : stack_space_to_allocate;
859
860           fprintf (stream, "\tSUBU %s,%s,%d\n",
861                    reg_names[MMIX_STACK_POINTER_REGNUM],
862                    reg_names[MMIX_STACK_POINTER_REGNUM],
863                    stack_chunk);
864           offset += stack_chunk;
865           stack_space_to_allocate -= stack_chunk;
866
867           if (doing_dwarf)
868             {
869               cfa_offset += stack_chunk;
870               if (!frame_pointer_needed)
871                 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
872                                  cfa_offset);
873             }
874         }
875
876       /* We don't tell dwarf2 about this one; we just have it to unwind
877          the register stack at landing pads.  FIXME: It's a kludge because
878          we can't describe the effect of the PUSHJ and PUSHGO insns on the
879          register stack at the moment.  Best thing would be to handle it
880          like stack-pointer offsets.  Better: some hook into dwarf2out.c
881          to produce DW_CFA_expression:s that specify the increment of rO,
882          and unwind it at eh_return (preferred) or at the landing pad.
883          Then saves to $0..$G-1 could be specified through that register.  */
884
885       fprintf (stream, "\tGET $255,rO\n\tSTOU $255,%s,%d\n",
886                reg_names[MMIX_STACK_POINTER_REGNUM], offset);
887
888       offset -= 8;
889     }
890
891   /* After the return-address and the frame-pointer, we have the local
892      variables.  They're the ones that may have an "unaligned" size.  */
893   offset -= (locals_size + 7) & ~7;
894
895   /* Now store all registers that are global, i.e. not saved by the
896      register file machinery.
897
898      It is assumed that the frame-pointer is one of these registers, so it
899      is explicitly excluded in the count.  */
900
901   for (regno = 255;
902        regno >= MMIX_FIRST_GLOBAL_REGNUM;
903        regno--)
904     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
905          && regs_ever_live[regno] && ! call_used_regs[regno])
906         || IS_MMIX_EH_RETURN_DATA_REG (regno))
907       {
908         if (offset < 0)
909           {
910             int stack_chunk;
911
912             /* Since the local variables go above, we may get a large
913                offset here.  */
914             if (offset < -248)
915               {
916                 /* We're not going to access the locals area in the
917                    prologue, so we'll just silently subtract the slab we
918                    will not access.  */
919                 stack_chunk =
920                   stack_space_to_allocate > (256 - offset - 8)
921                   ? (256 - offset - 8) : stack_space_to_allocate;
922
923                 mmix_output_register_setting (stream, 255, stack_chunk, 1);
924                 fprintf (stream, "\tSUBU %s,%s,$255\n",
925                          reg_names[MMIX_STACK_POINTER_REGNUM],
926                          reg_names[MMIX_STACK_POINTER_REGNUM]);
927
928                 if (doing_dwarf)
929                   {
930                     cfa_offset += stack_chunk;
931                     if (!frame_pointer_needed)
932                       dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
933                                          cfa_offset);
934                   }
935               }
936             else
937               {
938                 stack_chunk = stack_space_to_allocate > (256 - 8)
939                   ? (256 - 8) : stack_space_to_allocate;
940
941                 fprintf (stream, "\tSUBU %s,%s,%d\n",
942                          reg_names[MMIX_STACK_POINTER_REGNUM],
943                          reg_names[MMIX_STACK_POINTER_REGNUM], stack_chunk);
944                 if (doing_dwarf)
945                   {
946                     cfa_offset += stack_chunk;
947                     if (!frame_pointer_needed)
948                       dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
949                                          cfa_offset);
950                   }
951               }
952
953             offset += stack_chunk;
954             stack_space_to_allocate -= stack_chunk;
955           }
956
957         fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
958                reg_names[MMIX_STACK_POINTER_REGNUM], offset);
959         if (doing_dwarf)
960           dwarf2out_reg_save ("", regno, -cfa_offset + offset);
961         offset -= 8;
962       }
963
964   /* Finally, allocate room for outgoing args and local vars if room
965      wasn't allocated above.  This might be any number of bytes (well, we
966      assume it fits in a host-int).  */
967   if (stack_space_to_allocate)
968     {
969       if (stack_space_to_allocate < 256)
970         {
971           fprintf (stream, "\tSUBU %s,%s,%d\n",
972                    reg_names[MMIX_STACK_POINTER_REGNUM],
973                    reg_names[MMIX_STACK_POINTER_REGNUM],
974                    stack_space_to_allocate);
975         }
976       else
977         {
978           mmix_output_register_setting (stream, 255,
979                                         stack_space_to_allocate, 1);
980           fprintf (stream, "\tSUBU %s,%s,$255\n",
981                    reg_names[MMIX_STACK_POINTER_REGNUM],
982                    reg_names[MMIX_STACK_POINTER_REGNUM]);
983         }
984
985       if (doing_dwarf)
986         {
987           cfa_offset += stack_space_to_allocate;
988           if (!frame_pointer_needed)
989             dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
990                                cfa_offset);
991         }
992     }
993 }
994
995 /* MACHINE_DEPENDENT_REORG.
996    No actual rearrangements done here; just virtually by calculating the
997    highest saved stack register number used to modify the register numbers
998    at output time.  */
999
1000 void
1001 mmix_machine_dependent_reorg (first)
1002      rtx first ATTRIBUTE_UNUSED;
1003 {
1004   int regno;
1005
1006   /* We put the number of the highest saved register-file register in a
1007      location convenient for the call-patterns to output.  Note that we
1008      don't tell dwarf2 about these registers, since it can't restore them
1009      anyway.  */
1010   for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
1011        regno >= 0;
1012        regno--)
1013     if ((regs_ever_live[regno] && !call_used_regs[regno])
1014         || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
1015       break;
1016
1017   /* Regardless of whether they're saved (they might be just read), we
1018      mustn't include registers that carry parameters.  We could scan the
1019      insns to see whether they're actually used (and indeed do other less
1020      trivial register usage analysis and transformations), but it seems
1021      wasteful to optimize for unused parameter registers.  As of
1022      2002-04-30, regs_ever_live[n] seems to be set for only-reads too, but
1023      that might change.  */
1024   if (!TARGET_ABI_GNU && regno < current_function_args_info.regs - 1)
1025     {
1026       regno = current_function_args_info.regs - 1;
1027
1028       /* We don't want to let this cause us to go over the limit and make
1029          incoming parameter registers be misnumbered and treating the last
1030          parameter register and incoming return value register call-saved.
1031          Stop things at the unmodified scheme.  */
1032       if (regno > MMIX_RETURN_VALUE_REGNUM - 1)
1033         regno = MMIX_RETURN_VALUE_REGNUM - 1;
1034     }
1035
1036   cfun->machine->highest_saved_stack_register = regno;
1037 }
1038
1039 /* TARGET_ASM_FUNCTION_EPILOGUE.  */
1040
1041 void
1042 mmix_target_asm_function_epilogue (stream, locals_size)
1043      FILE *stream;
1044      HOST_WIDE_INT locals_size;
1045
1046 {
1047   int regno;
1048   int stack_space_to_deallocate
1049     = (current_function_outgoing_args_size
1050        + current_function_pretend_args_size
1051        + (int) locals_size + 7) & ~7;
1052
1053   /* The assumption that locals_size fits in an int is asserted in
1054      mmix_target_asm_function_prologue.  */
1055
1056   /* The first address to access is beyond the outgoing_args area.  */
1057   int offset = current_function_outgoing_args_size;
1058
1059   /* Add the space for global non-register-stack registers.
1060      It is assumed that the frame-pointer register can be one of these
1061      registers, in which case it is excluded from the count when needed.  */
1062   for (regno = 255;
1063        regno >= MMIX_FIRST_GLOBAL_REGNUM;
1064        regno--)
1065     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1066          && regs_ever_live[regno] && !call_used_regs[regno])
1067         || IS_MMIX_EH_RETURN_DATA_REG (regno))
1068       stack_space_to_deallocate += 8;
1069
1070   /* Add in the space for register stack-pointer.  If so, always add room
1071      for the saved PC.  */
1072   if (MMIX_CFUN_HAS_LANDING_PAD)
1073     stack_space_to_deallocate += 16;
1074   else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
1075     /* If we have a saved return-address slot, add it in.  */
1076     stack_space_to_deallocate += 8;
1077
1078   /* Add in the frame-pointer.  */
1079   if (frame_pointer_needed)
1080     stack_space_to_deallocate += 8;
1081
1082   /* Make sure we don't get an unaligned stack.  */
1083   if ((stack_space_to_deallocate % 8) != 0)
1084     internal_error ("stack frame not a multiple of octabyte: %d",
1085                     stack_space_to_deallocate);
1086
1087   /* We will add back small offsets to the stack pointer as we go.
1088      First, we restore all registers that are global, i.e. not saved by
1089      the register file machinery.  */
1090
1091   for (regno = MMIX_FIRST_GLOBAL_REGNUM;
1092        regno <= 255;
1093        regno++)
1094     if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1095          && regs_ever_live[regno] && !call_used_regs[regno])
1096         || IS_MMIX_EH_RETURN_DATA_REG (regno))
1097       {
1098         if (offset > 255)
1099           {
1100             if (offset > 65535)
1101               {
1102                 /* There's better support for incrementing than
1103                    decrementing, so we might be able to optimize this as
1104                    we see a need.  */
1105                 mmix_output_register_setting (stream, 255, offset, 1);
1106                 fprintf (stream, "\tADDU %s,%s,$255\n",
1107                          reg_names[MMIX_STACK_POINTER_REGNUM],
1108                          reg_names[MMIX_STACK_POINTER_REGNUM]);
1109               }
1110             else
1111               fprintf (stream, "\tINCL %s,%d\n",
1112                        reg_names[MMIX_STACK_POINTER_REGNUM], offset);
1113
1114             stack_space_to_deallocate -= offset;
1115             offset = 0;
1116           }
1117
1118         fprintf (stream, "\tLDOU %s,%s,%d\n",
1119                  reg_names[regno],
1120                  reg_names[MMIX_STACK_POINTER_REGNUM],
1121                  offset);
1122         offset += 8;
1123       }
1124
1125   /* Here is where the local variables were.  As in the prologue, they
1126      might be of an unaligned size.  */
1127   offset += (locals_size + 7) & ~7;
1128
1129
1130   /* The saved register stack pointer is just below the frame-pointer
1131      register.  We don't need to restore it "manually"; the POP
1132      instruction does that.  */
1133   if (MMIX_CFUN_HAS_LANDING_PAD)
1134     offset += 16;
1135   else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
1136     /* The return-address slot is just below the frame-pointer register.
1137        We don't need to restore it because we don't really use it.  */
1138     offset += 8;
1139
1140   /* Get back the old frame-pointer-value.  */
1141   if (frame_pointer_needed)
1142     {
1143       if (offset > 255)
1144         {
1145           if (offset > 65535)
1146             {
1147               /* There's better support for incrementing than
1148                  decrementing, so we might be able to optimize this as
1149                  we see a need.  */
1150               mmix_output_register_setting (stream, 255, offset, 1);
1151               fprintf (stream, "\tADDU %s,%s,$255\n",
1152                        reg_names[MMIX_STACK_POINTER_REGNUM],
1153                        reg_names[MMIX_STACK_POINTER_REGNUM]);
1154             }
1155           else
1156             fprintf (stream, "\tINCL %s,%d\n",
1157                      reg_names[MMIX_STACK_POINTER_REGNUM], offset);
1158
1159           stack_space_to_deallocate -= offset;
1160           offset = 0;
1161         }
1162
1163       fprintf (stream, "\tLDOU %s,%s,%d\n",
1164                reg_names[MMIX_FRAME_POINTER_REGNUM],
1165                reg_names[MMIX_STACK_POINTER_REGNUM],
1166                offset);
1167       offset += 8;
1168     }
1169
1170   /* We do not need to restore pretended incoming args, just add back
1171      offset to sp.  */
1172   if (stack_space_to_deallocate > 65535)
1173     {
1174       /* There's better support for incrementing than decrementing, so
1175          we might be able to optimize this as we see a need.  */
1176       mmix_output_register_setting (stream, 255,
1177                                     stack_space_to_deallocate, 1);
1178       fprintf (stream, "\tADDU %s,%s,$255\n",
1179                reg_names[MMIX_STACK_POINTER_REGNUM],
1180                reg_names[MMIX_STACK_POINTER_REGNUM]);
1181     }
1182   else if (stack_space_to_deallocate != 0)
1183     fprintf (stream, "\tINCL %s,%d\n",
1184              reg_names[MMIX_STACK_POINTER_REGNUM],
1185              stack_space_to_deallocate);
1186
1187   if (current_function_calls_eh_return)
1188     /* Adjustment the (normal) stack-pointer to that of the receiver.
1189        FIXME: It would be nice if we could also adjust the register stack
1190        here, but we need to express it through DWARF 2 too.  */
1191     fprintf (stream, "\tADDU %s,%s,%s\n",
1192              reg_names [MMIX_STACK_POINTER_REGNUM],
1193              reg_names [MMIX_STACK_POINTER_REGNUM],
1194              reg_names [MMIX_EH_RETURN_STACKADJ_REGNUM]);
1195
1196   /* The extra \n is so we have a blank line between the assembly code of
1197      separate functions.  */
1198   fprintf (stream, "\tPOP %d,0\n\n",
1199            (! TARGET_ABI_GNU
1200             && current_function_return_rtx != NULL
1201             && ! current_function_returns_struct)
1202            ? (GET_CODE (current_function_return_rtx) == PARALLEL
1203               ? GET_NUM_ELEM (XVEC (current_function_return_rtx, 0)) : 1)
1204            : 0);
1205 }
1206
1207 /* ASM_OUTPUT_MI_THUNK.  */
1208
1209 void
1210 mmix_asm_output_mi_thunk (stream, fndecl, delta, func)
1211      FILE * stream;
1212      tree fndecl ATTRIBUTE_UNUSED;
1213      int delta;
1214      tree func;
1215 {
1216   /* If you define STRUCT_VALUE to 0, rather than use STRUCT_VALUE_REGNUM,
1217      (i.e. pass location of structure to return as invisible first
1218      argument) you need to tweak this code too.  */
1219   const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
1220
1221   if (delta >= 0 && delta < 65536)
1222     asm_fprintf (stream, "\tINCL %s,%d\n", delta, regname);
1223   else if (delta < 0 && delta >= -255)
1224     asm_fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, -delta);
1225   else
1226     {
1227       mmix_output_register_setting (stream, 255, delta, 1);
1228       asm_fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname);
1229     }
1230
1231   fprintf (stream, "\tJMP ");
1232   assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
1233   fprintf (stream, "\n");
1234 }
1235
1236 /* FUNCTION_PROFILER.  */
1237
1238 void
1239 mmix_function_profiler (stream, labelno)
1240      FILE *stream ATTRIBUTE_UNUSED;
1241      int labelno ATTRIBUTE_UNUSED;
1242 {
1243   sorry ("function_profiler support for MMIX");
1244 }
1245
1246 /* SETUP_INCOMING_VARARGS.  */
1247
1248 void
1249 mmix_setup_incoming_varargs (args_so_farp, mode, vartype, pretend_sizep,
1250                              second_time)
1251      CUMULATIVE_ARGS * args_so_farp;
1252      enum machine_mode mode;
1253      tree vartype;
1254      int * pretend_sizep;
1255      int second_time ATTRIBUTE_UNUSED;
1256 {
1257   /* For stdarg, the last named variable has been handled, but
1258      args_so_farp has not been advanced for it.  For varargs, the current
1259      argument is to be counted to the anonymous ones.  */
1260   if (current_function_stdarg)
1261     {
1262       if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS)
1263         *pretend_sizep
1264           = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8;
1265     }
1266   else if (current_function_varargs)
1267     {
1268       if (args_so_farp->regs < MMIX_MAX_ARGS_IN_REGS)
1269         *pretend_sizep
1270           = (MMIX_MAX_ARGS_IN_REGS - args_so_farp->regs) * 8;
1271
1272       /* For varargs, we get here when we see the last named parameter,
1273          which will actually be passed on stack.  So make the next call
1274          (there will be one) to FUNCTION_ARG return 0, to count it on
1275          stack, so va_arg for it will get right.  FIXME: The GCC core
1276          should provide TRT.  */
1277       args_so_farp->now_varargs = 1;
1278     }
1279   else
1280     internal_error ("neither varargs or stdarg in mmix_setup_incoming_varargs");
1281
1282
1283   /* We assume that one argument takes up one register here.  That should
1284      be true until we start messing with multi-reg parameters.   */
1285   if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1)
1286     internal_error ("MMIX Internal: Last named vararg would not fit in a register");
1287 }
1288
1289 /* EXPAND_BUILTIN_VA_ARG.  */
1290
1291 /* This is modified from the "standard" implementation of va_arg: read the
1292    value from the current (padded) address and increment by the (padded)
1293    size.  The difference for MMIX is that if the type is
1294    pass-by-reference, then perform an indirection.  */
1295
1296 rtx
1297 mmix_expand_builtin_va_arg (valist, type)
1298      tree valist;
1299      tree type;
1300 {
1301   tree ptr_size = size_int (BITS_PER_WORD / BITS_PER_UNIT);
1302   tree addr_tree, type_size = NULL;
1303   tree align, alignm1;
1304   tree rounded_size;
1305   rtx addr;
1306
1307   /* Compute the rounded size of the type.  */
1308
1309   /* Get AP.  */
1310   addr_tree = valist;
1311   align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
1312   alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
1313   if (type == error_mark_node
1314       || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
1315       || TREE_OVERFLOW (type_size))
1316     /* Presumably an error; the size isn't computable.  A message has
1317        supposedly been emitted elsewhere.  */
1318     rounded_size = size_zero_node;
1319   else
1320     rounded_size = fold (build (MULT_EXPR, sizetype,
1321                                 fold (build (TRUNC_DIV_EXPR, sizetype,
1322                                              fold (build (PLUS_EXPR, sizetype,
1323                                                           type_size, alignm1)),
1324                                              align)),
1325                                 align));
1326
1327  if (AGGREGATE_TYPE_P (type)
1328      && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) < 8
1329      && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) != 0)
1330    {
1331      /* Adjust for big-endian the location of aggregates passed in a
1332         register, but where the aggregate is accessed in a shorter mode
1333         than the natural register mode (i.e. it is accessed as SFmode(?),
1334         SImode, HImode or QImode rather than DImode or DFmode(?)).  FIXME:
1335         Or should we adjust the mode in which the aggregate is read, to be
1336         a register size mode?  (Hum, nah, a small offset is generally
1337         cheaper than a wider memory access on MMIX.)  */
1338      addr_tree
1339        = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
1340                 size_int ((BITS_PER_WORD / BITS_PER_UNIT)
1341                           - GET_MODE_UNIT_SIZE (TYPE_MODE (type))));
1342    }
1343  else if (!integer_zerop (rounded_size))
1344    {
1345      if (!really_constant_p (type_size))
1346        /* Varying-size types come in by reference.  */
1347        addr_tree
1348          = build1 (INDIRECT_REF, build_pointer_type (type), addr_tree);
1349      else
1350        {
1351          /* If the size is less than a register, then we need to pad the
1352             address by adding the difference.  */
1353          tree addend
1354            = fold (build (COND_EXPR, sizetype,
1355                           fold (build (GT_EXPR, sizetype,
1356                                        rounded_size,
1357                                        align)),
1358                           size_zero_node,
1359                           fold (build (MINUS_EXPR, sizetype,
1360                                        rounded_size,
1361                                        type_size))));
1362          tree addr_tree1
1363            = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
1364                           addend));
1365
1366          /* If this type is larger than what fits in a register, then it
1367             is passed by reference.  */
1368          addr_tree
1369            = fold (build (COND_EXPR, TREE_TYPE (addr_tree1),
1370                           fold (build (GT_EXPR, sizetype,
1371                                        rounded_size,
1372                                        ptr_size)),
1373                           build1 (INDIRECT_REF, build_pointer_type (type),
1374                                   addr_tree1),
1375                           addr_tree1));
1376        }
1377    }
1378
1379   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
1380   addr = copy_to_reg (addr);
1381
1382   if (!integer_zerop (rounded_size))
1383     {
1384       /* Compute new value for AP.  For MMIX, it is always advanced by the
1385          size of a register.  */
1386       tree t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
1387                       build (PLUS_EXPR, TREE_TYPE (valist), valist,
1388                              ptr_size));
1389       TREE_SIDE_EFFECTS (t) = 1;
1390       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1391     }
1392
1393   return addr;
1394 }
1395
1396 /* TRAMPOLINE_SIZE.  */
1397 /* Four 4-byte insns plus two 8-byte values.  */
1398 int mmix_trampoline_size = 32;
1399
1400
1401 /* TRAMPOLINE_TEMPLATE.  */
1402
1403 void
1404 mmix_trampoline_template (stream)
1405      FILE * stream;
1406 {
1407   /* Read a value into the static-chain register and jump somewhere.  The
1408      static chain is stored at offset 16, and the function address is
1409      stored at offset 24.  */
1410   /* FIXME: GCC copies this using *intsize* (tetra), when it should use
1411      register size (octa).  */
1412   fprintf (stream, "\tGETA $255,1F\n\t");
1413   fprintf (stream, "LDOU %s,$255,0\n\t",
1414            reg_names[MMIX_STATIC_CHAIN_REGNUM]);
1415   fprintf (stream, "LDOU $255,$255,8\n\t");
1416   fprintf (stream, "GO $255,$255,0\n");
1417   fprintf (stream, "1H\tOCTA 0\n\t");
1418   fprintf (stream, "OCTA 0\n");
1419 }
1420
1421 /* INITIALIZE_TRAMPOLINE.  */
1422 /* Set the static chain and function pointer field in the trampoline.
1423    We also SYNCID here to be sure (doesn't matter in the simulator, but
1424    some day it will).  */
1425
1426 void
1427 mmix_initialize_trampoline (trampaddr, fnaddr, static_chain)
1428      rtx trampaddr;
1429      rtx fnaddr;
1430      rtx static_chain;
1431 {
1432   emit_move_insn (gen_rtx_MEM (DImode, plus_constant (trampaddr, 16)),
1433                   static_chain);
1434   emit_move_insn (gen_rtx_MEM (DImode,
1435                                plus_constant (trampaddr, 24)),
1436                   fnaddr);
1437   emit_insn (gen_sync_icache (validize_mem (gen_rtx_MEM (DImode,
1438                                                          trampaddr)),
1439                               GEN_INT (mmix_trampoline_size - 1)));
1440 }
1441
1442 /* We must exclude constant addresses that have an increment that is not a
1443    multiple of four bytes because of restrictions of the GETA
1444    instruction, unless TARGET_BASE_ADDRESSES.  */
1445
1446 int
1447 mmix_constant_address_p (x)
1448      rtx x;
1449 {
1450   RTX_CODE code = GET_CODE (x);
1451   int addend = 0;
1452   /* When using "base addresses", anything constant goes.  */
1453   int constant_ok = TARGET_BASE_ADDRESSES != 0;
1454
1455   if (code == LABEL_REF || code == SYMBOL_REF)
1456     return 1;
1457
1458   if (code == CONSTANT_P_RTX || code == HIGH)
1459     /* FIXME: Don't know how to dissect these.  Avoid them for now.  */
1460     return constant_ok;
1461
1462   switch (code)
1463     {
1464     case LABEL_REF:
1465     case SYMBOL_REF:
1466       return 1;
1467
1468     case CONSTANT_P_RTX:
1469     case HIGH:
1470       /* FIXME: Don't know how to dissect these.  Avoid them for now,
1471          except we know they're constants.  */
1472       return constant_ok;
1473
1474     case CONST_INT:
1475       addend = INTVAL (x);
1476       break;
1477
1478     case CONST_DOUBLE:
1479       if (GET_MODE (x) != VOIDmode)
1480         /* Strange that we got here.  FIXME: Check if we do.  */
1481         return constant_ok;
1482       addend = CONST_DOUBLE_LOW (x);
1483       break;
1484
1485     case CONST:
1486       /* Note that expressions with arithmetic on forward references don't
1487          work in mmixal.  People using gcc assembly code with mmixal might
1488          need to move arrays and such to before the point of use.  */
1489       if (GET_CODE (XEXP (x, 0)) == PLUS)
1490         {
1491           rtx x0 = XEXP (XEXP (x, 0), 0);
1492           rtx x1 = XEXP (XEXP (x, 0), 1);
1493
1494           if ((GET_CODE (x0) == SYMBOL_REF
1495                || GET_CODE (x0) == LABEL_REF)
1496               && (GET_CODE (x1) == CONST_INT
1497                   || (GET_CODE (x1) == CONST_DOUBLE
1498                       && GET_MODE (x1) == VOIDmode)))
1499             addend = mmix_intval (x1);
1500           else
1501             return constant_ok;
1502         }
1503       else
1504         return constant_ok;
1505       break;
1506
1507     default:
1508       return 0;
1509     }
1510
1511   return constant_ok || (addend & 3) == 0;
1512 }
1513
1514 /* Return 1 if the address is OK, otherwise 0.
1515    Used by GO_IF_LEGITIMATE_ADDRESS.  */
1516
1517 int
1518 mmix_legitimate_address (mode, x, strict_checking)
1519      enum machine_mode mode ATTRIBUTE_UNUSED;
1520      rtx x;
1521      int strict_checking;
1522 {
1523 #define MMIX_REG_OK(X)                                                  \
1524   ((strict_checking                                                     \
1525     && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER                         \
1526         || (reg_renumber[REGNO (X)] > 0                                 \
1527             && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER))) \
1528    || (!strict_checking                                                 \
1529        && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER                      \
1530            || REGNO (X) >= FIRST_PSEUDO_REGISTER                        \
1531            || REGNO (X) == ARG_POINTER_REGNUM)))
1532
1533   /* We only accept:
1534      (mem reg)
1535      (mem (plus reg reg))
1536      (mem (plus reg 0..255)).
1537      unless TARGET_BASE_ADDRESSES, in which case we accept all
1538      (mem constant_address) too.  */
1539
1540
1541     /* (mem reg) */
1542   if (REG_P (x) && MMIX_REG_OK (x))
1543     return 1;
1544
1545   if (GET_CODE(x) == PLUS)
1546     {
1547       rtx x1 = XEXP (x, 0);
1548       rtx x2 = XEXP (x, 1);
1549
1550       /* Try swapping the order.  FIXME: Do we need this?  */
1551       if (! REG_P (x1))
1552         {
1553           rtx tem = x1;
1554           x1 = x2;
1555           x2 = tem;
1556         }
1557
1558       /* (mem (plus (reg?) (?))) */
1559       if (!REG_P (x1) || !MMIX_REG_OK (x1))
1560         return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1561
1562       /* (mem (plus (reg) (reg?))) */
1563       if (REG_P (x2) && MMIX_REG_OK (x2))
1564         return 1;
1565
1566       /* (mem (plus (reg) (0..255?))) */
1567       if (GET_CODE (x2) == CONST_INT
1568           && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
1569         return 1;
1570
1571       return 0;
1572     }
1573
1574   return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1575 }
1576
1577 /* LEGITIMATE_CONSTANT_P.  */
1578
1579 int
1580 mmix_legitimate_constant_p (x)
1581      rtx x;
1582 {
1583   RTX_CODE code = GET_CODE (x);
1584
1585   /* We must allow any number due to the way the cse passes works; if we
1586      do not allow any number here, general_operand will fail, and insns
1587      will fatally fail recognition instead of "softly".  */
1588   if (code == CONST_INT || code == CONST_DOUBLE)
1589     return 1;
1590
1591   return CONSTANT_ADDRESS_P (x);
1592 }
1593
1594 /* SELECT_CC_MODE.  */
1595
1596 enum machine_mode
1597 mmix_select_cc_mode (op, x, y)
1598      RTX_CODE op;
1599      rtx x;
1600      rtx y ATTRIBUTE_UNUSED;
1601 {
1602   /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to
1603      output different compare insns.  Note that we do not check the
1604      validity of the comparison here.  */
1605
1606   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
1607     {
1608       if (op == ORDERED || op == UNORDERED || op == UNGE
1609           || op == UNGT || op == UNLE || op == UNLT)
1610         return CC_FUNmode;
1611
1612       if (op == EQ || op == NE)
1613         return CC_FPEQmode;
1614
1615       return CC_FPmode;
1616     }
1617
1618   if (op == GTU || op == LTU || op == GEU || op == LEU)
1619     return CC_UNSmode;
1620
1621   return CCmode;
1622 }
1623
1624 /* CANONICALIZE_COMPARISON.
1625    FIXME: Check if the number adjustments trig.  */
1626
1627 void
1628 mmix_canonicalize_comparison (codep, op0p, op1p)
1629      RTX_CODE * codep;
1630      rtx * op0p ATTRIBUTE_UNUSED;
1631      rtx * op1p;
1632 {
1633   /* Change -1 to zero, if possible.  */
1634   if ((*codep == LE || *codep == GT)
1635       && GET_CODE (*op1p) == CONST_INT
1636       && *op1p == constm1_rtx)
1637     {
1638       *codep = *codep == LE ? LT : GE;
1639       *op1p = const0_rtx;
1640     }
1641
1642   /* Fix up 256 to 255, if possible.  */
1643   if ((*codep == LT || *codep == LTU || *codep == GE || *codep == GEU)
1644       && GET_CODE (*op1p) == CONST_INT
1645       && INTVAL (*op1p) == 256)
1646     {
1647       /* FIXME: Remove when I know this trigs.  */
1648       fatal_insn ("oops, not debugged; fixing up value:", *op1p);
1649       *codep = *codep == LT ? LE : *codep == LTU ? LEU : *codep
1650         == GE ? GT : GTU;
1651       *op1p = GEN_INT (255);
1652     }
1653 }
1654
1655 /* REVERSIBLE_CC_MODE.  */
1656
1657 int
1658 mmix_reversible_cc_mode (mode)
1659      enum machine_mode mode;
1660 {
1661   /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float
1662      cmpares.  */
1663   return mode != CC_FPmode;
1664 }
1665
1666 /* DEFAULT_RTX_COSTS.  */
1667
1668 int
1669 mmix_rtx_cost_recalculated (x, code, outer_code, costp)
1670      rtx x ATTRIBUTE_UNUSED;
1671      RTX_CODE code ATTRIBUTE_UNUSED;
1672      RTX_CODE outer_code ATTRIBUTE_UNUSED;
1673      int *costp ATTRIBUTE_UNUSED;
1674 {
1675   /* For the time being, this is just a stub and we'll accept the
1676      generic calculations, until we can do measurements, at least.
1677      Say we did not modify any calculated costs.  */
1678   return 0;
1679 }
1680
1681 /* ADDRESS_COST.  */
1682
1683 int
1684 mmix_address_cost (addr)
1685      rtx addr ATTRIBUTE_UNUSED;
1686 {
1687   /* There's no difference in the address costs and we have lots of
1688      registers.  Some targets use constant 0, many others use 1 to say
1689      this.  Let's start with 1.  */
1690   return 1;
1691 }
1692
1693 /* REGISTER_MOVE_COST.  */
1694
1695 int
1696 mmix_register_move_cost (mode, from, to)
1697      enum machine_mode mode ATTRIBUTE_UNUSED;
1698      enum reg_class from;
1699      enum reg_class to;
1700 {
1701   return (from == GENERAL_REGS && from == to) ? 2 : 3;
1702 }
1703
1704 /* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a
1705    compile-time constant; it's used in an asm in crtstuff.c, compiled for
1706    the target.  */
1707
1708 /* DATA_SECTION_ASM_OP.  */
1709
1710 const char *
1711 mmix_data_section_asm_op ()
1712 {
1713   return "\t.data ! mmixal:= 8H LOC 9B";
1714 }
1715
1716 /* SELECT_SECTION.
1717    The meat is from elfos.h, which we will eventually consider using.  */
1718
1719 void
1720 mmix_select_section (decl, reloc, align)
1721      tree decl;
1722      int reloc;
1723      int align ATTRIBUTE_UNUSED;
1724 {
1725   if (TREE_CODE (decl) == STRING_CST)
1726     {
1727       if (! flag_writable_strings)
1728         const_section ();
1729       else
1730         data_section ();
1731     }
1732   else if (TREE_CODE (decl) == VAR_DECL)
1733     {
1734       if ((flag_pic && reloc)
1735           || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
1736           || !DECL_INITIAL (decl)
1737           || (DECL_INITIAL (decl) != error_mark_node
1738               && !TREE_CONSTANT (DECL_INITIAL (decl))))
1739         data_section ();
1740       else
1741         const_section ();
1742     }
1743   else if (TREE_CODE (decl) == CONSTRUCTOR)
1744     {
1745       if ((flag_pic && reloc)
1746           || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
1747           || ! TREE_CONSTANT (decl))
1748         data_section ();
1749       else
1750         const_section ();
1751     }
1752   else
1753     const_section ();
1754 }
1755
1756 /* ENCODE_SECTION_INFO.  */
1757
1758 void
1759 mmix_encode_section_info (decl, first)
1760      tree decl;
1761      int first;
1762 {
1763   /* Test for an external declaration, and do nothing if it is one.  */
1764   if ((TREE_CODE (decl) == VAR_DECL
1765        && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))
1766       || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))
1767     ;
1768   else if (first && DECL_P (decl))
1769     {
1770       /* For non-visible declarations, add a "@" prefix, which we skip
1771          when the label is output.  If the label does not have this
1772          prefix, a ":" is output if -mtoplevel-symbols.
1773
1774          Note that this does not work for data that is declared extern and
1775          later defined as static.  If there's code in between, that code
1776          will refer to the extern declaration, and vice versa.  This just
1777          means that when -mtoplevel-symbols is in use, we can just handle
1778          well-behaved ISO-compliant code.  */
1779
1780       const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1781       int len = strlen (str);
1782       char *newstr;
1783
1784       /* Why is the return type of ggc_alloc_string const?  */
1785       newstr = (char *) ggc_alloc_string ("", len + 1);
1786
1787       strcpy (newstr + 1, str);
1788       *newstr = '@';
1789       XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
1790     }
1791
1792   /* Set SYMBOL_REF_FLAG for things that we want to access with GETA.  We
1793      may need different options to reach for different things with GETA.
1794      For now, functions and things we know or have been told are constant.  */
1795   if (TREE_CODE (decl) == FUNCTION_DECL
1796       || TREE_CONSTANT (decl)
1797       || (TREE_CODE (decl) == VAR_DECL
1798           && TREE_READONLY (decl)
1799           && !TREE_SIDE_EFFECTS (decl)
1800           && (!DECL_INITIAL (decl)
1801               || TREE_CONSTANT (DECL_INITIAL (decl)))))
1802     {
1803       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
1804                  ? TREE_CST_RTL (decl) : DECL_RTL (decl));
1805       SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
1806     }
1807 }
1808
1809 /* STRIP_NAME_ENCODING.  */
1810
1811 const char *
1812 mmix_strip_name_encoding (name)
1813      const char *name;
1814 {
1815   for (; (*name == '@' || *name == '*'); name++)
1816     ;
1817
1818   return name;
1819 }
1820
1821 /* UNIQUE_SECTION.
1822    The meat is from elfos.h, which we should consider using.  */
1823
1824 void
1825 mmix_unique_section (decl, reloc)
1826      tree decl;
1827      int reloc;
1828 {
1829   int len;
1830   int sec;
1831   const char *name;
1832   char *string;
1833   const char *prefix;
1834   static const char *const prefixes[4][2] =
1835   {
1836     { ".text.",   ".gnu.linkonce.t." },
1837     { ".rodata.", ".gnu.linkonce.r." },
1838     { ".data.",   ".gnu.linkonce.d." },
1839     { ".bss.",    ".gnu.linkonce.b." }
1840   };
1841
1842   if (TREE_CODE (decl) == FUNCTION_DECL)
1843     sec = 0;
1844   else if (DECL_INITIAL (decl) == 0
1845            || DECL_INITIAL (decl) == error_mark_node)
1846     sec =  3;
1847   else if (DECL_READONLY_SECTION (decl, reloc))
1848     sec = 1;
1849   else
1850     sec = 2;
1851
1852   name   = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1853   /* Strip off any encoding in name.  */
1854   STRIP_NAME_ENCODING (name, name);
1855   prefix = prefixes[sec][DECL_ONE_ONLY (decl)];
1856   len    = strlen (name) + strlen (prefix);
1857   string = alloca (len + 1);
1858
1859   sprintf (string, "%s%s", prefix, name);
1860
1861   DECL_SECTION_NAME (decl) = build_string (len, string);
1862 }
1863
1864 /* ASM_FILE_START.  */
1865
1866 void
1867 mmix_asm_file_start (stream)
1868      FILE * stream;
1869 {
1870   /* We just emit a little comment for the time being.  FIXME: Perhaps add
1871      -mstandalone and some segment and prefix setup here.  */
1872   ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);
1873
1874   fprintf (stream, "! mmixal:= 8H LOC Data_Section\n");
1875
1876   /* Make sure each file starts with the text section. */
1877   text_section ();
1878 }
1879
1880 /* ASM_FILE_END.  */
1881
1882 void
1883 mmix_asm_file_end (stream)
1884      FILE * stream ATTRIBUTE_UNUSED;
1885 {
1886   /* Make sure each file ends with the data section. */
1887   data_section ();
1888 }
1889
1890 /* ASM_OUTPUT_SOURCE_FILENAME.  */
1891
1892 void
1893 mmix_asm_output_source_filename (stream, name)
1894      FILE * stream;
1895      const char * name;
1896 {
1897   fprintf (stream, "# 1 ");
1898   OUTPUT_QUOTED_STRING (stream, name);
1899   fprintf (stream, "\n");
1900 }
1901
1902 /* OUTPUT_QUOTED_STRING.  */
1903
1904 void
1905 mmix_output_quoted_string (stream, string, length)
1906      FILE * stream;
1907      const char * string;
1908      int length;
1909 {
1910   const char * string_end = string + length;
1911   static const char *const unwanted_chars = "\"[]\\";
1912
1913   /* Output "any character except newline and double quote character".  We
1914      play it safe and avoid all control characters too.  We also do not
1915      want [] as characters, should input be passed through m4 with [] as
1916      quotes.  Further, we avoid "\", because the GAS port handles it as a
1917      quoting character.  */
1918   while (string < string_end)
1919     {
1920       if (*string
1921           && (unsigned char) *string < 128
1922           && !ISCNTRL (*string)
1923           && strchr (unwanted_chars, *string) == NULL)
1924         {
1925           fputc ('"', stream);
1926           while (*string
1927                  && (unsigned char) *string < 128
1928                  && !ISCNTRL (*string)
1929                  && strchr (unwanted_chars, *string) == NULL
1930                  && string < string_end)
1931             {
1932               fputc (*string, stream);
1933               string++;
1934             }
1935           fputc ('"', stream);
1936           if (string < string_end)
1937             fprintf (stream, ",");
1938         }
1939       if (string < string_end)
1940         {
1941           fprintf (stream, "#%x", *string & 255);
1942           string++;
1943           if (string < string_end)
1944             fprintf (stream, ",");
1945         }
1946     }
1947 }
1948
1949 /* ASM_OUTPUT_SOURCE_LINE.  */
1950
1951 void
1952 mmix_asm_output_source_line  (stream, lineno)
1953      FILE * stream;
1954      int lineno;
1955 {
1956   fprintf (stream, "# %d ", lineno);
1957   OUTPUT_QUOTED_STRING (stream, main_input_filename);
1958   fprintf (stream, "\n");
1959 }
1960
1961 /* Target hook for assembling integer objects.  Use mmix_print_operand
1962    for WYDE and TETRA.  Use mmix_output_octa to output 8-byte
1963    CONST_DOUBLEs.  */
1964
1965 static bool
1966 mmix_assemble_integer (x, size, aligned_p)
1967      rtx x;
1968      unsigned int size;
1969      int aligned_p;
1970 {
1971   if (aligned_p)
1972     switch (size)
1973       {
1974         /* We handle a limited number of types of operands in here.  But
1975            that's ok, because we can punt to generic functions.  We then
1976            pretend that aligned data isn't needed, so the usual .<pseudo>
1977            syntax is used (which works for aligned data too).  We actually
1978            *must* do that, since we say we don't have simple aligned
1979            pseudos, causing this function to be called.  We just try and
1980            keep as much compatibility as possible with mmixal syntax for
1981            normal cases (i.e. without GNU extensions and C only).  */
1982       case 1:
1983         if (GET_CODE (x) != CONST_INT)
1984           {
1985             aligned_p = 0;
1986             break;
1987           }
1988         fputs ("\tBYTE\t", asm_out_file);
1989         mmix_print_operand (asm_out_file, x, 'B');
1990         fputc ('\n', asm_out_file);
1991         return true;
1992
1993       case 2:
1994         if (GET_CODE (x) != CONST_INT)
1995           {
1996             aligned_p = 0;
1997             break;
1998           }
1999         fputs ("\tWYDE\t", asm_out_file);
2000         mmix_print_operand (asm_out_file, x, 'W');
2001         fputc ('\n', asm_out_file);
2002         return true;
2003
2004       case 4:
2005         if (GET_CODE (x) != CONST_INT)
2006           {
2007             aligned_p = 0;
2008             break;
2009           }
2010         fputs ("\tTETRA\t", asm_out_file);
2011         mmix_print_operand (asm_out_file, x, 'L');
2012         fputc ('\n', asm_out_file);
2013         return true;
2014
2015       case 8:
2016         if (GET_CODE (x) == CONST_DOUBLE)
2017           /* We don't get here anymore for CONST_DOUBLE, because DImode
2018              isn't expressed as CONST_DOUBLE, and DFmode is handled
2019              elsewhere.  */
2020           abort ();
2021         assemble_integer_with_op ("\tOCTA\t", x);
2022         return true;
2023       }
2024   return default_assemble_integer (x, size, aligned_p);
2025 }
2026
2027 /* ASM_OUTPUT_ASCII.  */
2028
2029 void
2030 mmix_asm_output_ascii (stream, string, length)
2031      FILE *stream;
2032      const char *string;
2033      int length;
2034 {
2035   while (length > 0)
2036     {
2037       int chunk_size = length > 60 ? 60 : length;
2038       fprintf (stream, "\tBYTE ");
2039       mmix_output_quoted_string (stream, string, chunk_size);
2040       string += chunk_size;
2041       length -= chunk_size;
2042       fprintf (stream, "\n");
2043     }
2044 }
2045
2046 /* ASM_OUTPUT_ALIGNED_COMMON.  */
2047
2048 void
2049 mmix_asm_output_aligned_common (stream, name, size, align)
2050      FILE *stream;
2051      const char *name;
2052      int size;
2053      int align;
2054 {
2055   /* This is mostly the elfos.h one.  There doesn't seem to be a way to
2056      express this in a mmixal-compatible way.  */
2057   fprintf (stream, "\t.comm\t");
2058   assemble_name (stream, name);
2059   fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",
2060            size, align / BITS_PER_UNIT);
2061 }
2062
2063 /* ASM_OUTPUT_ALIGNED_LOCAL.  */
2064
2065 void
2066 mmix_asm_output_aligned_local (stream, name, size, align)
2067      FILE * stream;
2068      const char * name;
2069      int size;
2070      int align;
2071 {
2072   data_section ();
2073
2074   ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
2075   assemble_name (stream, name);
2076   fprintf (stream, "\tLOC @+%d\n", size);
2077 }
2078
2079 /* ASM_OUTPUT_LABEL.  */
2080
2081 void
2082 mmix_asm_output_label (stream, name)
2083      FILE *stream;
2084      const char * name;
2085 {
2086   assemble_name (stream, name);
2087   fprintf (stream, "\tIS @\n");
2088 }
2089
2090 /* ASM_DECLARE_REGISTER_GLOBAL.  */
2091
2092 void
2093 mmix_asm_declare_register_global (stream, decl, regno, name)
2094      FILE *stream ATTRIBUTE_UNUSED;
2095      tree decl ATTRIBUTE_UNUSED;
2096      int regno ATTRIBUTE_UNUSED;
2097      const char *name ATTRIBUTE_UNUSED;
2098 {
2099   /* Nothing to do here, but there *will* be, therefore the framework is
2100      here.  */
2101 }
2102
2103 /* ASM_GLOBALIZE_LABEL.  */
2104
2105 void
2106 mmix_asm_globalize_label (stream, name)
2107      FILE * stream ATTRIBUTE_UNUSED;
2108      const char * name ATTRIBUTE_UNUSED;
2109 {
2110   asm_fprintf (stream, "\t.global ");
2111   assemble_name (stream, name);
2112   putc ('\n', stream);
2113 }
2114
2115 /* ASM_WEAKEN_LABEL.  */
2116
2117 void
2118 mmix_asm_weaken_label (stream, name)
2119      FILE * stream ATTRIBUTE_UNUSED;
2120      const char * name ATTRIBUTE_UNUSED;
2121 {
2122   asm_fprintf (stream, "\t.weak ");
2123   assemble_name (stream, name);
2124   asm_fprintf (stream, " ! mmixal-incompatible\n");
2125 }
2126
2127 /* MAKE_DECL_ONE_ONLY.  */
2128
2129 void
2130 mmix_make_decl_one_only (decl)
2131      tree decl;
2132 {
2133   DECL_WEAK (decl) = 1;
2134 }
2135
2136 /* ASM_OUTPUT_LABELREF.
2137    Strip GCC's '*' and our own '@'.  No order is assumed.  */
2138
2139 void
2140 mmix_asm_output_labelref (stream, name)
2141      FILE *stream;
2142      const char *name;
2143 {
2144   int is_extern = 1;
2145
2146   for (; (*name == '@' || *name == '*'); name++)
2147     if (*name == '@')
2148       is_extern = 0;
2149
2150   asm_fprintf (stream, "%s%U%s",
2151                is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
2152                name);
2153 }
2154
2155 /* ASM_OUTPUT_INTERNAL_LABEL.  */
2156
2157 void
2158 mmix_asm_output_internal_label (stream, name, num)
2159      FILE * stream;
2160      const char * name;
2161      int num;
2162 {
2163   fprintf (stream, "%s:%d\tIS @\n", name, num);
2164 }
2165
2166 /* ASM_OUTPUT_DEF.  */
2167
2168 void
2169 mmix_asm_output_def (stream, name, value)
2170      FILE * stream;
2171      const char * name;
2172      const char * value;
2173 {
2174   assemble_name (stream, name);
2175   fprintf (stream, "\tIS ");
2176   assemble_name (stream, value);
2177   fputc ('\n', stream);
2178 }
2179
2180 /* ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL.  */
2181
2182 void
2183 mmix_asm_output_define_label_difference_symbol (stream, symbol, hi, lo)
2184      FILE *stream;
2185      const char *symbol;
2186      const char *hi;
2187      const char *lo;
2188 {
2189   assemble_name (stream, symbol);
2190   fprintf (stream, "\tIS\t");
2191   assemble_name (stream, hi);
2192   fputc ('-', stream);
2193   assemble_name (stream, lo);
2194   fprintf (stream, "\n");
2195 }
2196
2197 /* PRINT_OPERAND.  */
2198
2199 void
2200 mmix_print_operand (stream, x, code)
2201      FILE * stream;
2202      rtx x;
2203      int code;
2204 {
2205   /* When we add support for different codes later, we can, when needed,
2206      drop through to the main handler with a modified operand.  */
2207   rtx modified_x = x;
2208   int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
2209
2210   switch (code)
2211     {
2212       /* Unrelated codes are in alphabetic order.  */
2213
2214     case '+':
2215       /* For conditional branches, output "P" for a probable branch.  */
2216       if (TARGET_BRANCH_PREDICT)
2217         {
2218           x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
2219           if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)
2220             putc ('P', stream);
2221         }
2222       return;
2223
2224     case 'B':
2225       if (GET_CODE (x) != CONST_INT)
2226         fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
2227       fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
2228       return;
2229
2230     case 'H':
2231       /* Highpart.  Must be general register, and not the last one, as
2232          that one cannot be part of a consecutive register pair.  */
2233       if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
2234         internal_error ("MMIX Internal: Bad register: %d", regno);
2235
2236       /* This is big-endian, so the high-part is the first one.  */
2237       fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
2238       return;
2239
2240     case 'L':
2241       /* Lowpart.  Must be CONST_INT or general register, and not the last
2242          one, as that one cannot be part of a consecutive register pair.  */
2243       if (GET_CODE (x) == CONST_INT)
2244         {
2245           fprintf (stream, "#%lx",
2246                    (unsigned long) (INTVAL (x)
2247                                     & ((unsigned int) 0x7fffffff * 2 + 1)));
2248           return;
2249         }
2250
2251       if (GET_CODE (x) == SYMBOL_REF)
2252         {
2253           output_addr_const (stream, x);
2254           return;
2255         }
2256
2257       if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
2258         internal_error ("MMIX Internal: Bad register: %d", regno);
2259
2260       /* This is big-endian, so the low-part is + 1.  */
2261       fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
2262       return;
2263
2264       /* Can't use 'a' because that's a generic modifier for address
2265          output.  */
2266     case 'A':
2267       mmix_output_shiftvalue_op_from_str (stream, "ANDN",
2268                                           ~(unsigned HOST_WIDEST_INT)
2269                                           mmix_intval (x));
2270       return;
2271
2272     case 'i':
2273       mmix_output_shiftvalue_op_from_str (stream, "INC",
2274                                           (unsigned HOST_WIDEST_INT)
2275                                           mmix_intval (x));
2276       return;
2277
2278     case 'o':
2279       mmix_output_shiftvalue_op_from_str (stream, "OR",
2280                                           (unsigned HOST_WIDEST_INT)
2281                                           mmix_intval (x));
2282       return;
2283
2284     case 's':
2285       mmix_output_shiftvalue_op_from_str (stream, "SET",
2286                                           (unsigned HOST_WIDEST_INT)
2287                                           mmix_intval (x));
2288       return;
2289
2290     case 'd':
2291     case 'D':
2292       mmix_output_condition (stream, x, (code == 'D'));
2293       return;
2294
2295     case 'e':
2296       /* Output an extra "e" to make fcmpe, fune.  */
2297       if (TARGET_FCMP_EPSILON)
2298         fprintf (stream, "e");
2299       return;
2300
2301     case 'm':
2302       /* Output the number minus 1.  */
2303       if (GET_CODE (x) != CONST_INT)
2304         {
2305           fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
2306                       x);
2307         }
2308       fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
2309                (HOST_WIDEST_INT) (mmix_intval (x) - 1));
2310       return;
2311
2312     case 'p':
2313       /* Store the number of registers we want to save.  This was setup
2314          by the prologue.  The actual operand contains the number of
2315          registers to pass, but we don't use it currently.  Anyway, we
2316          need to output the number of saved registers here.  */
2317       fprintf (stream, "%d",
2318                cfun->machine->highest_saved_stack_register + 1);
2319       return;
2320
2321     case 'r':
2322       /* Store the register to output a constant to.  */
2323       if (! REG_P (x))
2324         fatal_insn ("MMIX Internal: Expected a register, not this", x);
2325       mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
2326       return;
2327
2328     case 'I':
2329       /* Output the constant.  Note that we use this for floats as well.  */
2330       if (GET_CODE (x) != CONST_INT
2331           && (GET_CODE (x) != CONST_DOUBLE
2332               || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
2333                   && GET_MODE (x) != SFmode)))
2334         fatal_insn ("MMIX Internal: Expected a constant, not this", x);
2335       mmix_output_register_setting (stream,
2336                                     mmix_output_destination_register,
2337                                     mmix_intval (x), 0);
2338       return;
2339
2340     case 'U':
2341       /* An U for unsigned, if TARGET_ZERO_EXTEND.  Ignore the operand.  */
2342       if (TARGET_ZERO_EXTEND)
2343         putc ('U', stream);
2344       return;
2345
2346     case 'v':
2347       mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
2348       return;
2349
2350     case 'V':
2351       mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
2352       return;
2353
2354     case 'W':
2355       if (GET_CODE (x) != CONST_INT)
2356         fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
2357       fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
2358       return;
2359
2360     case 0:
2361       /* Nothing to do.  */
2362       break;
2363
2364     default:
2365       /* Presumably there's a missing case above if we get here.  */
2366       internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);
2367     }
2368
2369   switch (GET_CODE (modified_x))
2370     {
2371     case REG:
2372       regno = REGNO (modified_x);
2373       if (regno >= FIRST_PSEUDO_REGISTER)
2374         internal_error ("MMIX Internal: Bad register: %d", regno);
2375       fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
2376       return;
2377
2378     case MEM:
2379       output_address (XEXP (modified_x, 0));
2380       return;
2381
2382     case CONST_INT:
2383       /* For -2147483648, mmixal complains that the constant does not fit
2384          in 4 bytes, so let's output it as hex.  Take care to handle hosts
2385          where HOST_WIDE_INT is longer than an int.
2386
2387          Print small constants +-255 using decimal.  */
2388
2389       if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
2390         fprintf (stream, "%d", (int) (INTVAL (modified_x)));
2391       else
2392         fprintf (stream, "#%x",
2393                  (int) (INTVAL (modified_x)) & (unsigned int) ~0);
2394       return;
2395
2396     case CONST_DOUBLE:
2397       /* Do somewhat as CONST_INT.  */
2398       mmix_output_octa (stream, mmix_intval (modified_x), 0);
2399       return;
2400
2401     case CONST:
2402       output_addr_const (stream, modified_x);
2403       return;
2404
2405     default:
2406       /* No need to test for all strange things.  Let output_addr_const do
2407          it for us.  */
2408       if (CONSTANT_P (modified_x)
2409           /* Strangely enough, this is not included in CONSTANT_P.
2410              FIXME: Ask/check about sanity here.  */
2411           || GET_CODE (modified_x) == CODE_LABEL)
2412         {
2413           output_addr_const (stream, modified_x);
2414           return;
2415         }
2416
2417       /* We need the original here.  */
2418       fatal_insn ("MMIX Internal: Cannot decode this operand", x);
2419     }
2420 }
2421
2422 /* PRINT_OPERAND_PUNCT_VALID_P.  */
2423
2424 int
2425 mmix_print_operand_punct_valid_p (code)
2426      int code ATTRIBUTE_UNUSED;
2427 {
2428   /* A '+' is used for branch prediction, similar to other ports.  */
2429   return code == '+';
2430 }
2431
2432 /* PRINT_OPERAND_ADDRESS.  */
2433
2434 void
2435 mmix_print_operand_address (stream, x)
2436      FILE *stream;
2437      rtx x;
2438 {
2439   if (REG_P (x))
2440     {
2441       /* I find the generated assembly code harder to read without
2442          the ",0".  */
2443       fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
2444       return;
2445     }
2446   else if (GET_CODE (x) == PLUS)
2447     {
2448       rtx x1 = XEXP (x, 0);
2449       rtx x2 = XEXP (x, 1);
2450
2451       /* Try swap the order.  FIXME: Do we need this?  */
2452       if (! REG_P (x1))
2453         {
2454           rtx tem = x1;
2455           x1 = x2;
2456           x2 = tem;
2457         }
2458
2459       if (REG_P (x1))
2460         {
2461           fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
2462
2463           if (REG_P (x2))
2464             {
2465               fprintf (stream, "%s",
2466                        reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
2467               return;
2468             }
2469           else if (GET_CODE (x2) == CONST_INT
2470                    && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
2471             {
2472               output_addr_const (stream, x2);
2473               return;
2474             }
2475         }
2476     }
2477
2478   if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x))
2479     {
2480       output_addr_const (stream, x);
2481       return;
2482     }
2483
2484   fatal_insn ("MMIX Internal: This is not a recognized address", x);
2485 }
2486
2487 /* ASM_OUTPUT_REG_PUSH.  */
2488
2489 void
2490 mmix_asm_output_reg_push (stream, regno)
2491      FILE * stream;
2492      int regno;
2493 {
2494   fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
2495            reg_names[MMIX_STACK_POINTER_REGNUM],
2496            reg_names[MMIX_STACK_POINTER_REGNUM],
2497            reg_names[MMIX_OUTPUT_REGNO (regno)],
2498            reg_names[MMIX_STACK_POINTER_REGNUM]);
2499 }
2500
2501 /* ASM_OUTPUT_REG_POP.  */
2502
2503 void
2504 mmix_asm_output_reg_pop (stream, regno)
2505      FILE * stream;
2506      int regno;
2507 {
2508   fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
2509            reg_names[MMIX_OUTPUT_REGNO (regno)],
2510            reg_names[MMIX_STACK_POINTER_REGNUM],
2511            reg_names[MMIX_STACK_POINTER_REGNUM]);
2512 }
2513
2514 /* ASM_OUTPUT_ADDR_DIFF_ELT.  */
2515
2516 void
2517 mmix_asm_output_addr_diff_elt (stream, body, value, rel)
2518      FILE *stream;
2519      rtx body ATTRIBUTE_UNUSED;
2520      int value;
2521      int rel;
2522 {
2523   fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
2524 }
2525
2526 /* ASM_OUTPUT_ADDR_VEC_ELT.  */
2527
2528 void
2529 mmix_asm_output_addr_vec_elt (stream, value)
2530      FILE *stream;
2531      int value;
2532 {
2533   fprintf (stream, "\tOCTA L:%d\n", value);
2534 }
2535
2536 /* ASM_OUTPUT_SKIP.  */
2537
2538 void
2539 mmix_asm_output_skip (stream, nbytes)
2540      FILE *stream;
2541      int nbytes;
2542 {
2543   fprintf (stream, "\tLOC @+%d\n", nbytes);
2544 }
2545
2546 /* ASM_OUTPUT_ALIGN.  */
2547
2548 void
2549 mmix_asm_output_align (stream, power)
2550      FILE *stream;
2551      int power;
2552 {
2553   /* We need to record the needed alignment of this section in the object,
2554      so we have to output an alignment directive.  Use a .p2align (not
2555      .align) so people will never have to wonder about whether the
2556      argument is in number of bytes or the log2 thereof.  We do it in
2557      addition to the LOC directive, so nothing needs tweaking when
2558      copy-pasting assembly into mmixal.  */
2559  fprintf (stream, "\t.p2align %d\n", power);
2560  fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
2561 }
2562
2563 /* DBX_REGISTER_NUMBER.  */
2564
2565 int
2566 mmix_dbx_register_number (regno)
2567      int regno;
2568 {
2569   /* Adjust the register number to the one it will be output as, dammit.
2570      It'd be nice if we could check the assumption that we're filling a
2571      gap, but every register between the last saved register and parameter
2572      registers might be a valid parameter register.  */
2573   regno = MMIX_OUTPUT_REGNO (regno);
2574
2575   /* We need to renumber registers to get the number of the return address
2576      register in the range 0..255.  It is also space-saving if registers
2577      mentioned in the call-frame information (which uses this function by
2578      defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered
2579      0 .. 63.  So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48.  */
2580   return regno >= 224 ? (regno - 224) : (regno + 48);
2581 }
2582
2583 /* End of target macro support functions.
2584
2585    Now MMIX's own functions.  First the exported ones.  */
2586
2587 /* Output an optimal sequence for setting a register to a specific
2588    constant.  Used in an alternative for const_ints in movdi, and when
2589    using large stack-frame offsets.
2590
2591    Use do_begin_end to say if a line-starting TAB and newline before the
2592    first insn and after the last insn is wanted.  */
2593
2594 void
2595 mmix_output_register_setting (stream, regno, value, do_begin_end)
2596      FILE *stream;
2597      int regno;
2598      HOST_WIDEST_INT value;
2599      int do_begin_end;
2600 {
2601   if (do_begin_end)
2602     fprintf (stream, "\t");
2603
2604   if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
2605     {
2606       /* First, the one-insn cases.  */
2607       mmix_output_shiftvalue_op_from_str (stream, "SET",
2608                                           (unsigned HOST_WIDEST_INT)
2609                                           value);
2610       fprintf (stream, " %s,", reg_names[regno]);
2611       mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
2612     }
2613   else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
2614     {
2615       /* We do this to get a bit more legible assembly code.  The next
2616          alternative is mostly redundant with this.  */
2617
2618       mmix_output_shiftvalue_op_from_str (stream, "SET",
2619                                           -(unsigned HOST_WIDEST_INT)
2620                                           value);
2621       fprintf (stream, " %s,", reg_names[regno]);
2622       mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
2623       fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
2624                reg_names[regno]);
2625     }
2626   else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
2627     {
2628       /* Slightly more expensive, the two-insn cases.  */
2629
2630       /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255)
2631          is shiftable, or any other one-insn transformation of the value.
2632          FIXME: Check first if the value is "shiftable" by two loading
2633          with two insns, since it makes more readable assembly code (if
2634          anyone else cares).  */
2635
2636       mmix_output_shiftvalue_op_from_str (stream, "SET",
2637                                           ~(unsigned HOST_WIDEST_INT)
2638                                           value);
2639       fprintf (stream, " %s,", reg_names[regno]);
2640       mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
2641       fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
2642                reg_names[regno]);
2643     }
2644   else
2645     {
2646       /* The generic case.  2..4 insns.  */
2647       static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
2648       const char *op = "SET";
2649       const char *line_begin = "";
2650       int insns = 0;
2651       int i;
2652       HOST_WIDEST_INT tmpvalue = value;
2653
2654       /* Compute the number of insns needed to output this constant.  */
2655       for (i = 0; i < 4 && tmpvalue != 0; i++)
2656         {
2657           if (tmpvalue & 65535)
2658             insns++;
2659           tmpvalue >>= 16;
2660         }
2661       if (TARGET_BASE_ADDRESSES && insns == 3)
2662         {
2663           /* The number three is based on a static observation on
2664              ghostscript-6.52.  Two and four are excluded because there
2665              are too many such constants, and each unique constant (maybe
2666              offset by 1..255) were used few times compared to other uses,
2667              e.g. addresses.
2668
2669              We use base-plus-offset addressing to force it into a global
2670              register; we just use a "LDA reg,VALUE", which will cause the
2671              assembler and linker to DTRT (for constants as well as
2672              addresses).  */
2673           fprintf (stream, "LDA %s,", reg_names[regno]);
2674           mmix_output_octa (stream, value, 0);
2675         }
2676       else
2677         {
2678           /* Output pertinent parts of the 4-wyde sequence.
2679              Still more to do if we want this to be optimal, but hey...
2680              Note that the zero case has been handled above.  */
2681           for (i = 0; i < 4 && value != 0; i++)
2682             {
2683               if (value & 65535)
2684                 {
2685                   fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
2686                            higher_parts[i], reg_names[regno],
2687                            (int) (value & 65535));
2688                   /* The first one sets the rest of the bits to 0, the next
2689                      ones add set bits.  */
2690                   op = "INC";
2691                   line_begin = "\n\t";
2692                 }
2693
2694               value >>= 16;
2695             }
2696         }
2697     }
2698
2699   if (do_begin_end)
2700     fprintf (stream, "\n");
2701 }
2702
2703 /* Return 1 if value is 0..65535*2**(16*N) for N=0..3.
2704    else return 0.  */
2705
2706 int
2707 mmix_shiftable_wyde_value (value)
2708      unsigned HOST_WIDEST_INT value;
2709 {
2710   /* Shift by 16 bits per group, stop when we've found two groups with
2711      nonzero bits.  */
2712   int i;
2713   int has_candidate = 0;
2714
2715   for (i = 0; i < 4; i++)
2716     {
2717       if (value & 65535)
2718         {
2719           if (has_candidate)
2720             return 0;
2721           else
2722             has_candidate = 1;
2723         }
2724
2725       value >>= 16;
2726     }
2727
2728   return 1;
2729 }
2730
2731 /* True if this is an address_operand or a symbolic operand.  */
2732
2733 int
2734 mmix_symbolic_or_address_operand (op, mode)
2735      rtx op;
2736      enum machine_mode mode;
2737 {
2738   switch (GET_CODE (op))
2739     {
2740     case SYMBOL_REF:
2741     case LABEL_REF:
2742       return 1;
2743     case CONST:
2744       op = XEXP (op, 0);
2745       if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
2746            || GET_CODE (XEXP (op, 0)) == LABEL_REF)
2747           && (GET_CODE (XEXP (op, 1)) == CONST_INT
2748               || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
2749                   && GET_MODE (XEXP (op, 1)) == VOIDmode)))
2750         return 1;
2751       /* FALLTHROUGH */
2752     default:
2753       return address_operand (op, mode);
2754     }
2755 }
2756
2757 /* True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
2758    We could narrow the value down with a couple of predicated, but that
2759    doesn't seem to be worth it at the moment.  */
2760
2761 int
2762 mmix_reg_or_constant_operand (op, mode)
2763      rtx op;
2764      enum machine_mode mode;
2765 {
2766   return register_operand (op, mode)
2767     || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
2768     || GET_CODE (op) == CONST_INT;
2769 }
2770
2771 /* True if this is a register with a condition-code mode.  */
2772
2773 int
2774 mmix_reg_cc_operand (op, mode)
2775      rtx op;
2776      enum machine_mode mode;
2777 {
2778   if (mode == VOIDmode)
2779     mode = GET_MODE (op);
2780
2781   return register_operand (op, mode)
2782     && (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
2783         || mode == CC_FPEQmode || mode == CC_FUNmode);
2784 }
2785
2786 /* True if this is a foldable comparison operator
2787    - one where a the result of (compare:CC (reg) (const_int 0)) can be
2788    replaced by (reg).  */
2789
2790 int
2791 mmix_foldable_comparison_operator (op, mode)
2792      rtx op;
2793      enum machine_mode mode;
2794 {
2795   RTX_CODE code = GET_CODE (op);
2796
2797   if (mode == VOIDmode)
2798     mode = GET_MODE (op);
2799
2800   if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2801     mode = GET_MODE (XEXP (op, 0));
2802
2803   return ((mode == CCmode || mode == DImode)
2804           && (code == NE || code == EQ || code == GE || code == GT
2805               || code == LE))
2806     /* FIXME: This may be a stupid trick.  What happens when GCC wants to
2807        reverse the condition?  Can it do that by itself?  Maybe it can
2808        even reverse the condition to fit a foldable one in the first
2809        place?  */
2810     || (mode == CC_UNSmode && (code == GTU || code == LEU));
2811 }
2812
2813 /* Like comparison_operator, but only true if this comparison operator is
2814    applied to a valid mode.  Needed to avoid jump.c generating invalid
2815    code with -ffast-math (gcc.dg/20001228-1.c).  */
2816
2817 int
2818 mmix_comparison_operator (op, mode)
2819      rtx op;
2820      enum machine_mode mode;
2821 {
2822   RTX_CODE code = GET_CODE (op);
2823
2824   /* Comparison operators usually don't have a mode, but let's try and get
2825      one anyway for the day that changes.  */
2826   if (mode == VOIDmode)
2827     mode = GET_MODE (op);
2828
2829   /* Get the mode from the first operand if we don't have one.  */
2830   if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2831     mode = GET_MODE (XEXP (op, 0));
2832
2833   /* FIXME: This needs to be kept in sync with the tables in
2834      mmix_output_condition.  */
2835   return
2836     (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2837     || (mode == CC_FUNmode
2838         && (code == ORDERED || code == UNORDERED))
2839     || (mode == CC_FPmode
2840         && (code == GT || code == LT))
2841     || (mode == CC_FPEQmode
2842         && (code == NE || code == EQ))
2843     || (mode == CC_UNSmode
2844         && (code == GEU || code == GTU || code == LEU || code == LTU))
2845     || (mode == CCmode
2846         && (code == NE || code == EQ || code == GE || code == GT
2847             || code == LE || code == LT))
2848     || (mode == DImode
2849         && (code == NE || code == EQ || code == GE || code == GT
2850             || code == LE || code == LT || code == LEU || code == GTU));
2851 }
2852
2853 /* True if this is a register or 0 (int or float).  */
2854
2855 int
2856 mmix_reg_or_0_operand (op, mode)
2857      rtx op;
2858      enum machine_mode mode;
2859 {
2860   /* FIXME: Is mode calculation necessary and correct?  */
2861   return
2862     op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
2863     || register_operand (op, mode);
2864 }
2865
2866 /* True if this is a register or an int 0..255.  */
2867
2868 int
2869 mmix_reg_or_8bit_operand (op, mode)
2870      rtx op;
2871      enum machine_mode mode;
2872 {
2873   return register_operand (op, mode)
2874     || (GET_CODE (op) == CONST_INT
2875         && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
2876 }
2877
2878 /* True if this is a register or an int 0..256.  We include 256,
2879    because it can be canonicalized into 255 for comparisons, which is
2880    currently the only use of this predicate.
2881    FIXME:  Check that this happens and does TRT.  */
2882
2883 int
2884 mmix_reg_or_8bit_or_256_operand (op, mode)
2885      rtx op;
2886      enum machine_mode mode;
2887 {
2888   return mmix_reg_or_8bit_operand (op, mode)
2889     || (GET_CODE (op) == CONST_INT && INTVAL (op) == 256);
2890 }
2891
2892 /* Returns zero if code and mode is not a valid condition from a
2893    compare-type insn.  Nonzero if it is.  The parameter op, if non-NULL,
2894    is the comparison of mode is CC-somethingmode.  */
2895
2896 int
2897 mmix_valid_comparison (code, mode, op)
2898      RTX_CODE code;
2899      enum machine_mode mode;
2900      rtx op;
2901 {
2902   if (mode == VOIDmode && op != NULL_RTX)
2903     mode = GET_MODE (op);
2904
2905   /* We don't care to look at these, they should always be valid.  */
2906   if (mode == CCmode || mode == CC_UNSmode || mode == DImode)
2907     return 1;
2908
2909   if ((mode == CC_FPmode || mode == DFmode)
2910       && (code == GT || code == LT))
2911     return 1;
2912
2913   if ((mode == CC_FPEQmode || mode == DFmode)
2914       && (code == EQ || code == NE))
2915     return 1;
2916
2917   if ((mode == CC_FUNmode || mode == DFmode)
2918       && (code == ORDERED || code == UNORDERED))
2919     return 1;
2920
2921   return 0;
2922 }
2923
2924 /* X and Y are two things to compare using CODE.  Emit a compare insn if
2925    possible and return the rtx for the cc-reg in the proper mode, or
2926    NULL_RTX if this is not a valid comparison.  */
2927
2928 rtx
2929 mmix_gen_compare_reg (code, x, y)
2930      RTX_CODE code;
2931      rtx x, y;
2932 {
2933   enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
2934   rtx cc_reg;
2935
2936   /* FIXME: Do we get constants here?  Of double mode?  */
2937   enum machine_mode mode
2938     = GET_MODE (x) == VOIDmode
2939     ? GET_MODE (y)
2940     : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode;
2941
2942   if (! mmix_valid_comparison (code, mode, x))
2943     return NULL_RTX;
2944
2945   cc_reg = gen_reg_rtx (ccmode);
2946
2947   /* FIXME:  Can we avoid emitting a compare insn here?  */
2948   if (! REG_P (x) && ! REG_P (y))
2949     x = force_reg (mode, x);
2950
2951   CANONICALIZE_COMPARISON (code, x, y);
2952
2953   /* If it's not quite right yet, put y in a register.  */
2954   if (! REG_P (y)
2955       && (GET_CODE (y) != CONST_INT
2956           || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I')))
2957     y = force_reg (mode, y);
2958
2959   emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
2960                           gen_rtx_COMPARE (ccmode, x, y)));
2961
2962   return cc_reg;
2963 }
2964
2965 /* Local (static) helper functions.  */
2966
2967 /* Print operator suitable for doing something with a shiftable
2968    wyde.  The type of operator is passed as an asm output modifier.  */
2969
2970 static void
2971 mmix_output_shiftvalue_op_from_str (stream, mainop, value)
2972      FILE *stream;
2973      const char *mainop;
2974      HOST_WIDEST_INT value;
2975 {
2976   static const char *const op_part[] = {"L", "ML", "MH", "H"};
2977   int i;
2978
2979   if (! mmix_shiftable_wyde_value (value))
2980     {
2981       char s[sizeof ("0xffffffffffffffff")];
2982       sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
2983       internal_error ("MMIX Internal: %s is not a shiftable int", s);
2984     }
2985
2986   for (i = 0; i < 4; i++)
2987     {
2988       /* We know we're through when we find one-bits in the low
2989          16 bits.  */
2990       if (value & 0xffff)
2991         {
2992           fprintf (stream, "%s%s", mainop, op_part[i]);
2993           return;
2994         }
2995       value >>= 16;
2996     }
2997
2998   /* No bits set?  Then it must have been zero.  */
2999   fprintf (stream, "%sL", mainop);
3000 }
3001
3002 /* Print a 64-bit value, optionally prefixed by assembly pseudo.  */
3003
3004 static void
3005 mmix_output_octa (stream, value, do_begin_end)
3006      FILE *stream;
3007      HOST_WIDEST_INT value;
3008      int do_begin_end;
3009 {
3010   /* Snipped from final.c:output_addr_const.  We need to avoid the
3011      presumed universal "0x" prefix.  We can do it by replacing "0x" with
3012      "#0" here; we must avoid a space in the operands and no, the zero
3013      won't cause the number to be assumed in octal format.  */
3014   char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)];
3015
3016   if (do_begin_end)
3017     fprintf (stream, "\tOCTA ");
3018
3019   strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX);
3020   hex_format[0] = '#';
3021   hex_format[1] = '0';
3022
3023   /* Provide a few alternative output formats depending on the number, to
3024      improve legibility of assembler output.  */
3025   if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
3026       || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
3027     fprintf (stream, "%d", (int) value);
3028   else if (value > (HOST_WIDEST_INT) 0
3029            && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
3030     fprintf (stream, "#%x", (unsigned int) value);
3031   else
3032     fprintf (stream, hex_format, value);
3033
3034   if (do_begin_end)
3035     fprintf (stream, "\n");
3036 }
3037
3038 /* Print the presumed shiftable wyde argument shifted into place (to
3039    be output with an operand).  */
3040
3041 static void
3042 mmix_output_shifted_value (stream, value)
3043      FILE * stream;
3044      HOST_WIDEST_INT value;
3045 {
3046   int i;
3047
3048   if (! mmix_shiftable_wyde_value (value))
3049     {
3050       char s[16+2+1];
3051       sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
3052       internal_error ("MMIX Internal: %s is not a shiftable int", s);
3053     }
3054
3055   for (i = 0; i < 4; i++)
3056   {
3057     /* We know we're through when we find one-bits in the low 16 bits.  */
3058     if (value & 0xffff)
3059     {
3060       fprintf (stream, "#%x", (int) (value & 0xffff));
3061       return;
3062     }
3063
3064     value >>= 16;
3065   }
3066
3067   /* No bits set?  Then it must have been zero.  */
3068   fprintf (stream, "0");
3069 }
3070
3071 /* Output an MMIX condition name corresponding to an operator
3072    and operands:
3073    (comparison_operator [(comparison_operator ...) (const_int 0)])
3074    which means we have to look at *two* operators.
3075
3076    The argument "reversed" refers to reversal of the condition (not the
3077    same as swapping the arguments).  */
3078
3079 static void
3080 mmix_output_condition (stream, x, reversed)
3081      FILE *stream;
3082      rtx x;
3083      int reversed;
3084 {
3085   struct cc_conv
3086   {
3087     RTX_CODE cc;
3088
3089     /* The normal output cc-code.  */
3090     const char *const normal;
3091
3092     /* The reversed cc-code, or NULL if invalid.  */
3093     const char *const reversed;
3094   };
3095
3096   struct cc_type_conv
3097   {
3098     enum machine_mode cc_mode;
3099
3100     /* Terminated with {NIL, NULL, NULL} */
3101     const struct cc_conv *const convs;
3102   };
3103
3104 #undef CCEND
3105 #define CCEND {NIL, NULL, NULL}
3106
3107   static const struct cc_conv cc_fun_convs[]
3108     = {{ORDERED, "Z", "P"},
3109        {UNORDERED, "P", "Z"},
3110        CCEND};
3111   static const struct cc_conv cc_fp_convs[]
3112     = {{GT, "P", NULL},
3113        {LT, "N", NULL},
3114        CCEND};
3115   static const struct cc_conv cc_fpeq_convs[]
3116     = {{NE, "Z", "P"},
3117        {EQ, "P", "Z"},
3118        CCEND};
3119   static const struct cc_conv cc_uns_convs[]
3120     = {{GEU, "NN", "N"},
3121        {GTU, "P", "NP"},
3122        {LEU, "NP", "P"},
3123        {LTU, "N", "NN"},
3124        CCEND};
3125   static const struct cc_conv cc_signed_convs[]
3126     = {{NE, "NZ", "Z"},
3127        {EQ, "Z", "NZ"},
3128        {GE, "NN", "N"},
3129        {GT, "P", "NP"},
3130        {LE, "NP", "P"},
3131        {LT, "N", "NN"},
3132        CCEND};
3133   static const struct cc_conv cc_di_convs[]
3134     = {{NE, "NZ", "Z"},
3135        {EQ, "Z", "NZ"},
3136        {GE, "NN", "N"},
3137        {GT, "P", "NP"},
3138        {LE, "NP", "P"},
3139        {LT, "N", "NN"},
3140        {GTU, "NZ", "Z"},
3141        {LEU, "Z", "NZ"},
3142        CCEND};
3143 #undef CCEND
3144
3145   static const struct cc_type_conv cc_convs[]
3146     = {{CC_FUNmode, cc_fun_convs},
3147        {CC_FPmode, cc_fp_convs},
3148        {CC_FPEQmode, cc_fpeq_convs},
3149        {CC_UNSmode, cc_uns_convs},
3150        {CCmode, cc_signed_convs},
3151        {DImode, cc_di_convs}};
3152
3153   size_t i;
3154   int j;
3155
3156   enum machine_mode mode = GET_MODE (XEXP (x, 0));
3157   RTX_CODE cc = GET_CODE (x);
3158
3159   for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
3160     {
3161       if (mode == cc_convs[i].cc_mode)
3162         {
3163           for (j = 0; cc_convs[i].convs[j].cc != NIL; j++)
3164             if (cc == cc_convs[i].convs[j].cc)
3165               {
3166                 const char *mmix_cc
3167                   = (reversed ? cc_convs[i].convs[j].reversed
3168                      : cc_convs[i].convs[j].normal);
3169
3170                 if (mmix_cc == NULL)
3171                   fatal_insn ("MMIX Internal: Trying to output invalidly\
3172  reversed condition:", x);
3173
3174                 fprintf (stream, "%s", mmix_cc);
3175                 return;
3176               }
3177
3178           fatal_insn ("MMIX Internal: What's the CC of this?", x);
3179         }
3180     }
3181
3182   fatal_insn ("MMIX Internal: What is the CC of this?", x);
3183 }
3184
3185 /* Return the bit-value for a const_int or const_double.  */
3186
3187 static HOST_WIDEST_INT
3188 mmix_intval (x)
3189      rtx x;
3190 {
3191   unsigned HOST_WIDEST_INT retval;
3192
3193   if (GET_CODE (x) == CONST_INT)
3194     return INTVAL (x);
3195
3196   /* We make a little song and dance because converting to long long in
3197      gcc-2.7.2 is broken.  I still want people to be able to use it for
3198      cross-compilation to MMIX.  */
3199   if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
3200     {
3201       if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
3202         {
3203           retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
3204           retval *= 2;
3205           retval |= CONST_DOUBLE_LOW (x) & 1;
3206
3207           retval |=
3208             (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
3209               << (HOST_BITS_PER_LONG);
3210         }
3211       else
3212         retval = CONST_DOUBLE_HIGH (x);
3213
3214       return retval;
3215     }
3216
3217   if (GET_CODE (x) == CONST_DOUBLE)
3218     {
3219       REAL_VALUE_TYPE value;
3220
3221       /* FIXME:  This macro is not in the manual but should be.  */
3222       REAL_VALUE_FROM_CONST_DOUBLE (value, x);
3223
3224       if (GET_MODE (x) == DFmode)
3225         {
3226           long bits[2];
3227
3228           REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
3229
3230           if (sizeof (long) < sizeof (HOST_WIDEST_INT))
3231             {
3232               retval = (unsigned long) bits[1] / 2;
3233               retval *= 2;
3234               retval |= (unsigned long) bits[1] & 1;
3235               retval
3236                 |= (unsigned HOST_WIDEST_INT) bits[0]
3237                   << (sizeof (bits[0]) * 8);
3238             }
3239           else
3240             retval = (unsigned long) bits[1];
3241
3242           return retval;
3243         }
3244       else if (GET_MODE (x) == SFmode)
3245         {
3246           long bits;
3247           REAL_VALUE_TO_TARGET_SINGLE (value, bits);
3248
3249           return (unsigned long) bits;
3250         }
3251     }
3252
3253   fatal_insn ("MMIX Internal: This is not a constant:", x);
3254 }
3255
3256 /*
3257  * Local variables:
3258  * eval: (c-set-style "gnu")
3259  * indent-tabs-mode: t
3260  * End:
3261  */