mmix.c revision 1.11
1/* Definitions of target machine for GNU compiler, for MMIX.
2   Copyright (C) 2000-2020 Free Software Foundation, Inc.
3   Contributed by Hans-Peter Nilsson (hp@bitrange.com)
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3.  If not see
19<http://www.gnu.org/licenses/>.  */
20
21#define IN_TARGET_CODE 1
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "backend.h"
27#include "target.h"
28#include "rtl.h"
29#include "tree.h"
30#include "stringpool.h"
31#include "attribs.h"
32#include "df.h"
33#include "memmodel.h"
34#include "tm_p.h"
35#include "insn-config.h"
36#include "optabs.h"
37#include "regs.h"
38#include "emit-rtl.h"
39#include "recog.h"
40#include "diagnostic-core.h"
41#include "output.h"
42#include "varasm.h"
43#include "stor-layout.h"
44#include "calls.h"
45#include "explow.h"
46#include "expr.h"
47#include "dwarf2.h"
48#include "tm-constrs.h"
49#include "builtins.h"
50
51/* This file should be included last.  */
52#include "target-def.h"
53
54/* First some local helper definitions.  */
55#define MMIX_FIRST_GLOBAL_REGNUM 32
56
57/* We'd need a current_function_has_landing_pad.  It's marked as such when
58   a nonlocal_goto_receiver is expanded.  Not just a C++ thing, but
59   mostly.  */
60#define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)
61
62/* We have no means to tell DWARF 2 about the register stack, so we need
63   to store the return address on the stack if an exception can get into
64   this function.  We'll have an "initial value" recorded for the
65   return-register if we've seen a call instruction emitted.  This note
66   will be inaccurate before instructions are emitted, but the only caller
67   at that time is looking for modulo from stack-boundary, to which the
68   return-address does not contribute, and which is always 0 for MMIX
69   anyway.  Beware of calling leaf_function_p here, as it'll abort if
70   called within a sequence.  */
71#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS			\
72 (flag_exceptions						\
73  && has_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
74
75#define IS_MMIX_EH_RETURN_DATA_REG(REGNO)	\
76 (crtl->calls_eh_return		\
77  && (EH_RETURN_DATA_REGNO (0) == REGNO		\
78      || EH_RETURN_DATA_REGNO (1) == REGNO	\
79      || EH_RETURN_DATA_REGNO (2) == REGNO	\
80      || EH_RETURN_DATA_REGNO (3) == REGNO))
81
82/* For the default ABI, we rename registers at output-time to fill the gap
83   between the (statically partitioned) saved registers and call-clobbered
84   registers.  In effect this makes unused call-saved registers to be used
85   as call-clobbered registers.  The benefit comes from keeping the number
86   of local registers (value of rL) low, since there's a cost of
87   increasing rL and clearing unused (unset) registers with lower numbers.
88   Don't translate while outputting the prologue.  */
89#define MMIX_OUTPUT_REGNO(N)					\
90 (TARGET_ABI_GNU 						\
91  || (int) (N) < MMIX_RETURN_VALUE_REGNUM			\
92  || (int) (N) > MMIX_LAST_STACK_REGISTER_REGNUM		\
93  || cfun == NULL 						\
94  || cfun->machine == NULL 					\
95  || cfun->machine->in_prologue					\
96  ? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM			\
97	   + cfun->machine->highest_saved_stack_register + 1))
98
99/* The %d in "POP %d,0".  */
100#define MMIX_POP_ARGUMENT()						\
101 ((! TARGET_ABI_GNU							\
102   && crtl->return_rtx != NULL				\
103   && ! cfun->returns_struct)				\
104  ? (GET_CODE (crtl->return_rtx) == PARALLEL			\
105     ? GET_NUM_ELEM (XVEC (crtl->return_rtx, 0)) : 1)	\
106  : 0)
107
108/* The canonical saved comparison operands for non-cc0 machines, set in
109   the compare expander.  */
110rtx mmix_compare_op0;
111rtx mmix_compare_op1;
112
113/* Declarations of locals.  */
114
115/* Intermediate for insn output.  */
116static int mmix_output_destination_register;
117
118static void mmix_option_override (void);
119static void mmix_asm_output_source_filename (FILE *, const char *);
120static void mmix_output_shiftvalue_op_from_str
121  (FILE *, const char *, int64_t);
122static void mmix_output_shifted_value (FILE *, int64_t);
123static void mmix_output_condition (FILE *, const_rtx, int);
124static void mmix_output_octa (FILE *, int64_t, int);
125static bool mmix_assemble_integer (rtx, unsigned int, int);
126static struct machine_function *mmix_init_machine_status (void);
127static void mmix_encode_section_info (tree, rtx, int);
128static const char *mmix_strip_name_encoding (const char *);
129static void mmix_emit_sp_add (HOST_WIDE_INT offset);
130static void mmix_target_asm_function_prologue (FILE *);
131static void mmix_target_asm_function_end_prologue (FILE *);
132static void mmix_target_asm_function_epilogue (FILE *);
133static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
134static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
135static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
136static bool mmix_legitimate_constant_p (machine_mode, rtx);
137static void mmix_reorg (void);
138static void mmix_asm_output_mi_thunk
139  (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
140static void mmix_setup_incoming_varargs
141  (cumulative_args_t, const function_arg_info &, int *, int);
142static void mmix_file_start (void);
143static void mmix_file_end (void);
144static void mmix_init_libfuncs (void);
145static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
146static int mmix_register_move_cost (machine_mode,
147				    reg_class_t, reg_class_t);
148static rtx mmix_struct_value_rtx (tree, int);
149static machine_mode mmix_promote_function_mode (const_tree,
150						     machine_mode,
151	                                             int *, const_tree, int);
152static void mmix_function_arg_advance (cumulative_args_t,
153				       const function_arg_info &);
154static rtx mmix_function_incoming_arg (cumulative_args_t,
155				       const function_arg_info &);
156static rtx mmix_function_arg (cumulative_args_t, const function_arg_info &);
157static rtx mmix_function_value (const_tree, const_tree, bool);
158static rtx mmix_libcall_value (machine_mode, const_rtx);
159static bool mmix_function_value_regno_p (const unsigned int);
160static bool mmix_pass_by_reference (cumulative_args_t,
161				    const function_arg_info &);
162static bool mmix_frame_pointer_required (void);
163static void mmix_asm_trampoline_template (FILE *);
164static void mmix_trampoline_init (rtx, tree, rtx);
165static void mmix_print_operand (FILE *, rtx, int);
166static void mmix_print_operand_address (FILE *, machine_mode, rtx);
167static bool mmix_print_operand_punct_valid_p (unsigned char);
168static void mmix_conditional_register_usage (void);
169static HOST_WIDE_INT mmix_static_rtx_alignment (machine_mode);
170static HOST_WIDE_INT mmix_constant_alignment (const_tree, HOST_WIDE_INT);
171static HOST_WIDE_INT mmix_starting_frame_offset (void);
172
173/* Target structure macros.  Listed by node.  See `Using and Porting GCC'
174   for a general description.  */
175
176/* Node: Function Entry */
177
178#undef TARGET_ASM_BYTE_OP
179#define TARGET_ASM_BYTE_OP NULL
180#undef TARGET_ASM_ALIGNED_HI_OP
181#define TARGET_ASM_ALIGNED_HI_OP NULL
182#undef TARGET_ASM_ALIGNED_SI_OP
183#define TARGET_ASM_ALIGNED_SI_OP NULL
184#undef TARGET_ASM_ALIGNED_DI_OP
185#define TARGET_ASM_ALIGNED_DI_OP NULL
186#undef TARGET_ASM_INTEGER
187#define TARGET_ASM_INTEGER mmix_assemble_integer
188
189#undef TARGET_ASM_FUNCTION_PROLOGUE
190#define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
191
192#undef TARGET_ASM_FUNCTION_END_PROLOGUE
193#define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue
194
195#undef TARGET_ASM_FUNCTION_EPILOGUE
196#define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
197
198#undef TARGET_PRINT_OPERAND
199#define TARGET_PRINT_OPERAND mmix_print_operand
200#undef TARGET_PRINT_OPERAND_ADDRESS
201#define TARGET_PRINT_OPERAND_ADDRESS mmix_print_operand_address
202#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
203#define TARGET_PRINT_OPERAND_PUNCT_VALID_P mmix_print_operand_punct_valid_p
204
205#undef TARGET_ENCODE_SECTION_INFO
206#define TARGET_ENCODE_SECTION_INFO  mmix_encode_section_info
207#undef TARGET_STRIP_NAME_ENCODING
208#define TARGET_STRIP_NAME_ENCODING  mmix_strip_name_encoding
209
210#undef TARGET_ASM_OUTPUT_MI_THUNK
211#define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
212#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
213#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
214#undef TARGET_ASM_FILE_START
215#define TARGET_ASM_FILE_START mmix_file_start
216#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
217#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
218#undef TARGET_ASM_FILE_END
219#define TARGET_ASM_FILE_END mmix_file_end
220#undef TARGET_ASM_OUTPUT_SOURCE_FILENAME
221#define TARGET_ASM_OUTPUT_SOURCE_FILENAME mmix_asm_output_source_filename
222
223#undef TARGET_INIT_LIBFUNCS
224#define TARGET_INIT_LIBFUNCS mmix_init_libfuncs
225
226#undef TARGET_CONDITIONAL_REGISTER_USAGE
227#define TARGET_CONDITIONAL_REGISTER_USAGE mmix_conditional_register_usage
228
229#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
230#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
231
232#undef TARGET_RTX_COSTS
233#define TARGET_RTX_COSTS mmix_rtx_costs
234#undef TARGET_ADDRESS_COST
235#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
236
237#undef TARGET_REGISTER_MOVE_COST
238#define TARGET_REGISTER_MOVE_COST mmix_register_move_cost
239
240#undef TARGET_MACHINE_DEPENDENT_REORG
241#define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg
242
243#undef TARGET_PROMOTE_FUNCTION_MODE
244#define TARGET_PROMOTE_FUNCTION_MODE mmix_promote_function_mode
245
246#undef TARGET_FUNCTION_VALUE
247#define TARGET_FUNCTION_VALUE mmix_function_value
248#undef TARGET_LIBCALL_VALUE
249#define TARGET_LIBCALL_VALUE mmix_libcall_value
250#undef TARGET_FUNCTION_VALUE_REGNO_P
251#define TARGET_FUNCTION_VALUE_REGNO_P mmix_function_value_regno_p
252
253#undef TARGET_FUNCTION_ARG
254#define TARGET_FUNCTION_ARG mmix_function_arg
255#undef TARGET_FUNCTION_INCOMING_ARG
256#define TARGET_FUNCTION_INCOMING_ARG mmix_function_incoming_arg
257#undef TARGET_FUNCTION_ARG_ADVANCE
258#define TARGET_FUNCTION_ARG_ADVANCE mmix_function_arg_advance
259#undef TARGET_STRUCT_VALUE_RTX
260#define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx
261#undef TARGET_SETUP_INCOMING_VARARGS
262#define TARGET_SETUP_INCOMING_VARARGS mmix_setup_incoming_varargs
263#undef TARGET_PASS_BY_REFERENCE
264#define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference
265#undef TARGET_CALLEE_COPIES
266#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
267
268#undef TARGET_PREFERRED_RELOAD_CLASS
269#define TARGET_PREFERRED_RELOAD_CLASS mmix_preferred_reload_class
270#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
271#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mmix_preferred_output_reload_class
272
273#undef TARGET_LRA_P
274#define TARGET_LRA_P hook_bool_void_false
275
276#undef TARGET_LEGITIMATE_ADDRESS_P
277#define TARGET_LEGITIMATE_ADDRESS_P	mmix_legitimate_address_p
278#undef TARGET_LEGITIMATE_CONSTANT_P
279#define TARGET_LEGITIMATE_CONSTANT_P	mmix_legitimate_constant_p
280
281#undef TARGET_FRAME_POINTER_REQUIRED
282#define TARGET_FRAME_POINTER_REQUIRED mmix_frame_pointer_required
283
284#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
285#define TARGET_ASM_TRAMPOLINE_TEMPLATE mmix_asm_trampoline_template
286#undef TARGET_TRAMPOLINE_INIT
287#define TARGET_TRAMPOLINE_INIT mmix_trampoline_init
288
289#undef TARGET_OPTION_OVERRIDE
290#define TARGET_OPTION_OVERRIDE mmix_option_override
291
292#undef TARGET_STATIC_RTX_ALIGNMENT
293#define TARGET_STATIC_RTX_ALIGNMENT mmix_static_rtx_alignment
294#undef TARGET_CONSTANT_ALIGNMENT
295#define TARGET_CONSTANT_ALIGNMENT mmix_constant_alignment
296
297#undef TARGET_STARTING_FRAME_OFFSET
298#define TARGET_STARTING_FRAME_OFFSET mmix_starting_frame_offset
299
300struct gcc_target targetm = TARGET_INITIALIZER;
301
302/* Functions that are expansions for target macros.
303   See Target Macros in `Using and Porting GCC'.  */
304
305/* TARGET_OPTION_OVERRIDE.  */
306
307static void
308mmix_option_override (void)
309{
310  /* Should we err or should we warn?  Hmm.  At least we must neutralize
311     it.  For example the wrong kind of case-tables will be generated with
312     PIC; we use absolute address items for mmixal compatibility.  FIXME:
313     They could be relative if we just elide them to after all pertinent
314     labels.  */
315  if (flag_pic)
316    {
317      warning (0, "%<-f%s%> not supported: ignored",
318	       (flag_pic > 1) ? "PIC" : "pic");
319      flag_pic = 0;
320    }
321}
322
323/* INIT_EXPANDERS.  */
324
325void
326mmix_init_expanders (void)
327{
328  init_machine_status = mmix_init_machine_status;
329}
330
331/* Set the per-function data.  */
332
333static struct machine_function *
334mmix_init_machine_status (void)
335{
336  return ggc_cleared_alloc<machine_function> ();
337}
338
339/* DATA_ABI_ALIGNMENT.
340   We have trouble getting the address of stuff that is located at other
341   than 32-bit alignments (GETA requirements), so try to give everything
342   at least 32-bit alignment.  */
343
344int
345mmix_data_alignment (tree type ATTRIBUTE_UNUSED, int basic_align)
346{
347  if (basic_align < 32)
348    return 32;
349
350  return basic_align;
351}
352
353/* Implement TARGET_STATIC_RTX_ALIGNMENT.  */
354
355static HOST_WIDE_INT
356mmix_static_rtx_alignment (machine_mode mode)
357{
358  return MAX (GET_MODE_ALIGNMENT (mode), 32);
359}
360
361/* Implement tARGET_CONSTANT_ALIGNMENT.  */
362
363static HOST_WIDE_INT
364mmix_constant_alignment (const_tree, HOST_WIDE_INT basic_align)
365{
366  if (basic_align < 32)
367    return 32;
368
369  return basic_align;
370}
371
372/* LOCAL_ALIGNMENT.  */
373
374unsigned
375mmix_local_alignment (tree type ATTRIBUTE_UNUSED, unsigned basic_align)
376{
377  if (basic_align < 32)
378    return 32;
379
380  return basic_align;
381}
382
383/* TARGET_CONDITIONAL_REGISTER_USAGE.  */
384
385static void
386mmix_conditional_register_usage (void)
387{
388  int i;
389
390  if (TARGET_ABI_GNU)
391    {
392      static const int gnu_abi_reg_alloc_order[]
393	= MMIX_GNU_ABI_REG_ALLOC_ORDER;
394
395      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
396	reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];
397
398      /* Change the default from the mmixware ABI.  For the GNU ABI,
399	 $15..$30 are call-saved just as $0..$14.  There must be one
400	 call-clobbered local register for the "hole" that holds the
401	 number of saved local registers saved by PUSHJ/PUSHGO during the
402	 function call, receiving the return value at return.  So best is
403	 to use the highest, $31.  It's already marked call-clobbered for
404	 the mmixware ABI.  */
405      for (i = 15; i <= 30; i++)
406	call_used_regs[i] = 0;
407
408      /* "Unfix" the parameter registers.  */
409      for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
410	   i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
411	   i++)
412	fixed_regs[i] = 0;
413    }
414
415  /* Step over the ":" in special register names.  */
416  if (! TARGET_TOPLEVEL_SYMBOLS)
417    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
418      if (reg_names[i][0] == ':')
419	reg_names[i]++;
420}
421
422/* INCOMING_REGNO and OUTGOING_REGNO worker function.
423   Those two macros must only be applied to function argument
424   registers and the function return value register for the opposite
425   use.  FIXME: for their current use in gcc, it'd be better with an
426   explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P a'la
427   TARGET_FUNCTION_ARG / TARGET_FUNCTION_INCOMING_ARG instead of
428   forcing the target to commit to a fixed mapping and for any
429   unspecified register use.  Particularly when thinking about the
430   return-value, it is better to imagine INCOMING_REGNO and
431   OUTGOING_REGNO as named CALLEE_TO_CALLER_REGNO and INNER_REGNO as
432   named CALLER_TO_CALLEE_REGNO because the direction.  The "incoming"
433   and "outgoing" is from the perspective of the parameter-registers,
434   but the same macro is (must be, lacking an alternative like
435   suggested above) used to map the return-value-register from the
436   same perspective.  To make directions even more confusing, the macro
437   MMIX_OUTGOING_RETURN_VALUE_REGNUM holds the number of the register
438   in which to return a value, i.e. INCOMING_REGNO for the return-value-
439   register as received from a called function; the return-value on the
440   way out.  */
441
442int
443mmix_opposite_regno (int regno, int incoming)
444{
445  if (incoming && regno == MMIX_OUTGOING_RETURN_VALUE_REGNUM)
446    return MMIX_RETURN_VALUE_REGNUM;
447
448  if (!incoming && regno == MMIX_RETURN_VALUE_REGNUM)
449    return MMIX_OUTGOING_RETURN_VALUE_REGNUM;
450
451  if (!mmix_function_arg_regno_p (regno, incoming))
452    return regno;
453
454  return
455    regno - (incoming
456	     ? MMIX_FIRST_INCOMING_ARG_REGNUM - MMIX_FIRST_ARG_REGNUM
457	     : MMIX_FIRST_ARG_REGNUM - MMIX_FIRST_INCOMING_ARG_REGNUM);
458}
459
460/* LOCAL_REGNO.
461   All registers that are part of the register stack and that will be
462   saved are local.  */
463
464int
465mmix_local_regno (int regno)
466{
467  return (regno <= MMIX_LAST_STACK_REGISTER_REGNUM
468	  && !call_used_or_fixed_reg_p (regno));
469}
470
471/* TARGET_PREFERRED_RELOAD_CLASS.
472   We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */
473
474static reg_class_t
475mmix_preferred_reload_class (rtx x, reg_class_t rclass)
476{
477  /* FIXME: Revisit.  */
478  return GET_CODE (x) == MOD && GET_MODE (x) == DImode
479    ? REMAINDER_REG : rclass;
480}
481
482/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS.
483   We need to extend the reload class of REMAINDER_REG and HIMULT_REG.  */
484
485static reg_class_t
486mmix_preferred_output_reload_class (rtx x, reg_class_t rclass)
487{
488  /* FIXME: Revisit.  */
489  return GET_CODE (x) == MOD && GET_MODE (x) == DImode
490    ? REMAINDER_REG : rclass;
491}
492
493/* SECONDARY_RELOAD_CLASS.
494   We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere.  */
495
496enum reg_class
497mmix_secondary_reload_class (enum reg_class rclass,
498			     machine_mode mode ATTRIBUTE_UNUSED,
499			     rtx x ATTRIBUTE_UNUSED,
500			     int in_p ATTRIBUTE_UNUSED)
501{
502  if (rclass == REMAINDER_REG
503      || rclass == HIMULT_REG
504      || rclass == SYSTEM_REGS)
505    return GENERAL_REGS;
506
507  return NO_REGS;
508}
509
510/* DYNAMIC_CHAIN_ADDRESS.  */
511
512rtx
513mmix_dynamic_chain_address (rtx frame)
514{
515  /* FIXME: the frame-pointer is stored at offset -8 from the current
516     frame-pointer.  Unfortunately, the caller assumes that a
517     frame-pointer is present for *all* previous frames.  There should be
518     a way to say that that cannot be done, like for RETURN_ADDR_RTX.  */
519  return plus_constant (Pmode, frame, -8);
520}
521
522/* Implement TARGET_STARTING_FRAME_OFFSET.  */
523
524static HOST_WIDE_INT
525mmix_starting_frame_offset (void)
526{
527  /* The old frame pointer is in the slot below the new one, so
528     FIRST_PARM_OFFSET does not need to depend on whether the
529     frame-pointer is needed or not.  We have to adjust for the register
530     stack pointer being located below the saved frame pointer.
531     Similarly, we store the return address on the stack too, for
532     exception handling, and always if we save the register stack pointer.  */
533  return
534    (-8
535     + (MMIX_CFUN_HAS_LANDING_PAD
536	? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0)));
537}
538
539/* RETURN_ADDR_RTX.  */
540
541rtx
542mmix_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
543{
544  return count == 0
545    ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS
546       /* FIXME: Set frame_alias_set on the following.  (Why?)
547	  See mmix_initial_elimination_offset for the reason we can't use
548	  get_hard_reg_initial_val for both.  Always using a stack slot
549	  and not a register would be suboptimal.  */
550       ? validize_mem (gen_rtx_MEM (Pmode,
551				    plus_constant (Pmode,
552						   frame_pointer_rtx, -16)))
553       : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
554    : NULL_RTX;
555}
556
557/* SETUP_FRAME_ADDRESSES.  */
558
559void
560mmix_setup_frame_addresses (void)
561{
562  /* Nothing needed at the moment.  */
563}
564
565/* The difference between the (imaginary) frame pointer and the stack
566   pointer.  Used to eliminate the frame pointer.  */
567
568int
569mmix_initial_elimination_offset (int fromreg, int toreg)
570{
571  int regno;
572  int fp_sp_offset
573    = (get_frame_size () + crtl->outgoing_args_size + 7) & ~7;
574
575  /* There is no actual offset between these two virtual values, but for
576     the frame-pointer, we have the old one in the stack position below
577     it, so the offset for the frame-pointer to the stack-pointer is one
578     octabyte larger.  */
579  if (fromreg == MMIX_ARG_POINTER_REGNUM
580      && toreg == MMIX_FRAME_POINTER_REGNUM)
581    return 0;
582
583  /* The difference is the size of local variables plus the size of
584     outgoing function arguments that would normally be passed as
585     registers but must be passed on stack because we're out of
586     function-argument registers.  Only global saved registers are
587     counted; the others go on the register stack.
588
589     The frame-pointer is counted too if it is what is eliminated, as we
590     need to balance the offset for it from TARGET_STARTING_FRAME_OFFSET.
591
592     Also add in the slot for the register stack pointer we save if we
593     have a landing pad.
594
595     Unfortunately, we can't access $0..$14, from unwinder code easily, so
596     store the return address in a frame slot too.  FIXME: Only for
597     non-leaf functions.  FIXME: Always with a landing pad, because it's
598     hard to know whether we need the other at the time we know we need
599     the offset for one (and have to state it).  It's a kludge until we
600     can express the register stack in the EH frame info.
601
602     We have to do alignment here; get_frame_size will not return a
603     multiple of STACK_BOUNDARY.  FIXME: Add note in manual.  */
604
605  for (regno = MMIX_FIRST_GLOBAL_REGNUM;
606       regno <= 255;
607       regno++)
608    if ((df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
609	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
610      fp_sp_offset += 8;
611
612  return fp_sp_offset
613    + (MMIX_CFUN_HAS_LANDING_PAD
614       ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0))
615    + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8);
616}
617
618static void
619mmix_function_arg_advance (cumulative_args_t argsp_v,
620			   const function_arg_info &arg)
621{
622  CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
623  int arg_size = MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type);
624
625  argsp->regs = ((targetm.calls.must_pass_in_stack (arg)
626		  || (arg_size > 8
627		      && !TARGET_LIBFUNC
628		      && !argsp->lib))
629		 ? (MMIX_MAX_ARGS_IN_REGS) + 1
630		 : argsp->regs + (7 + arg_size) / 8);
631}
632
633/* Helper function for mmix_function_arg and mmix_function_incoming_arg.  */
634
635static rtx
636mmix_function_arg_1 (const cumulative_args_t argsp_v,
637		     const function_arg_info &arg, bool incoming)
638{
639  CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
640
641  /* Last-argument marker.  */
642  if (arg.end_marker_p ())
643    return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
644      ? gen_rtx_REG (arg.mode,
645		     (incoming
646		      ? MMIX_FIRST_INCOMING_ARG_REGNUM
647		      : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
648      : NULL_RTX;
649
650  return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
651	  && !targetm.calls.must_pass_in_stack (arg)
652	  && (GET_MODE_BITSIZE (arg.mode) <= 64
653	      || argsp->lib
654	      || TARGET_LIBFUNC))
655    ? gen_rtx_REG (arg.mode,
656		   (incoming
657		    ? MMIX_FIRST_INCOMING_ARG_REGNUM
658		    : MMIX_FIRST_ARG_REGNUM)
659		   + argsp->regs)
660    : NULL_RTX;
661}
662
663/* Return an rtx for a function argument to go in a register, and 0 for
664   one that must go on stack.  */
665
666static rtx
667mmix_function_arg (cumulative_args_t argsp, const function_arg_info &arg)
668{
669  return mmix_function_arg_1 (argsp, arg, false);
670}
671
672static rtx
673mmix_function_incoming_arg (cumulative_args_t argsp,
674			    const function_arg_info &arg)
675{
676  return mmix_function_arg_1 (argsp, arg, true);
677}
678
679/* Returns nonzero for everything that goes by reference, 0 for
680   everything that goes by value.  */
681
682static bool
683mmix_pass_by_reference (cumulative_args_t argsp_v,
684			const function_arg_info &arg)
685{
686  CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
687
688  /* FIXME: Check: I'm not sure the must_pass_in_stack check is
689     necessary.  */
690  if (targetm.calls.must_pass_in_stack (arg))
691    return true;
692
693  if (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8
694      && !TARGET_LIBFUNC
695      && (!argsp || !argsp->lib))
696    return true;
697
698  return false;
699}
700
701/* Return nonzero if regno is a register number where a parameter is
702   passed, and 0 otherwise.  */
703
704int
705mmix_function_arg_regno_p (int regno, int incoming)
706{
707  int first_arg_regnum
708    = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM;
709
710  return regno >= first_arg_regnum
711    && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS;
712}
713
714/* Implements TARGET_FUNCTION_VALUE.  */
715
716static rtx
717mmix_function_value (const_tree valtype,
718		     const_tree func ATTRIBUTE_UNUSED,
719		     bool outgoing)
720{
721  machine_mode mode = TYPE_MODE (valtype);
722  machine_mode cmode;
723  int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
724  rtx vec[MMIX_MAX_REGS_FOR_VALUE];
725  int i;
726  int nregs;
727
728  if (!outgoing)
729    return gen_rtx_REG (mode, MMIX_RETURN_VALUE_REGNUM);
730
731  /* Return values that fit in a register need no special handling.
732     There's no register hole when parameters are passed in global
733     registers.  */
734  if (TARGET_ABI_GNU
735      || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
736    return
737      gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
738
739  if (COMPLEX_MODE_P (mode))
740    /* A complex type, made up of components.  */
741    cmode = TYPE_MODE (TREE_TYPE (valtype));
742  else
743    {
744      /* Of the other larger-than-register modes, we only support
745	 scalar mode TImode.  (At least, that's the only one that's
746	 been rudimentally tested.)  Make sure we're alerted for
747	 unexpected cases.  */
748      if (mode != TImode)
749	sorry ("support for mode %qs", GET_MODE_NAME (mode));
750
751      /* In any case, we will fill registers to the natural size.  */
752      cmode = DImode;
753    }
754
755  nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
756
757  /* We need to take care of the effect of the register hole on return
758     values of large sizes; the last register will appear as the first
759     register, with the rest shifted.  (For complex modes, this is just
760     swapped registers.)  */
761
762  if (nregs > MMIX_MAX_REGS_FOR_VALUE)
763    internal_error ("too large function value type, needs %d registers,\
764 have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE);
765
766  /* FIXME: Maybe we should handle structure values like this too
767     (adjusted for BLKmode), perhaps for both ABI:s.  */
768  for (i = 0; i < nregs - 1; i++)
769    vec[i]
770      = gen_rtx_EXPR_LIST (VOIDmode,
771			   gen_rtx_REG (cmode, first_val_regnum + i),
772			   GEN_INT ((i + 1) * BITS_PER_UNIT));
773
774  vec[nregs - 1]
775    = gen_rtx_EXPR_LIST (VOIDmode,
776			 gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
777			 const0_rtx);
778
779  return gen_rtx_PARALLEL (mode, gen_rtvec_v (nregs, vec));
780}
781
782/* Implements TARGET_LIBCALL_VALUE.  */
783
784static rtx
785mmix_libcall_value (machine_mode mode,
786		    const_rtx fun ATTRIBUTE_UNUSED)
787{
788  return gen_rtx_REG (mode, MMIX_RETURN_VALUE_REGNUM);
789}
790
791/* Implements TARGET_FUNCTION_VALUE_REGNO_P.  */
792
793static bool
794mmix_function_value_regno_p (const unsigned int regno)
795{
796  return regno == MMIX_RETURN_VALUE_REGNUM;
797}
798
799/* EH_RETURN_DATA_REGNO. */
800
801int
802mmix_eh_return_data_regno (int n)
803{
804  if (n >= 0 && n < 4)
805    return MMIX_EH_RETURN_DATA_REGNO_START + n;
806
807  return INVALID_REGNUM;
808}
809
810/* EH_RETURN_STACKADJ_RTX. */
811
812rtx
813mmix_eh_return_stackadj_rtx (void)
814{
815  return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM);
816}
817
818/* EH_RETURN_HANDLER_RTX.  */
819
820rtx
821mmix_eh_return_handler_rtx (void)
822{
823  return gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
824}
825
826/* ASM_PREFERRED_EH_DATA_FORMAT. */
827
828int
829mmix_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED,
830				   int global ATTRIBUTE_UNUSED)
831{
832  /* This is the default (was at 2001-07-20).  Revisit when needed.  */
833  return DW_EH_PE_absptr;
834}
835
836/* Make a note that we've seen the beginning of the prologue.  This
837   matters to whether we'll translate register numbers as calculated by
838   mmix_reorg.  */
839
840static void
841mmix_target_asm_function_prologue (FILE *)
842{
843  cfun->machine->in_prologue = 1;
844}
845
846/* Make a note that we've seen the end of the prologue.  */
847
848static void
849mmix_target_asm_function_end_prologue (FILE *stream ATTRIBUTE_UNUSED)
850{
851  cfun->machine->in_prologue = 0;
852}
853
854/* Implement TARGET_MACHINE_DEPENDENT_REORG.  No actual rearrangements
855   done here; just virtually by calculating the highest saved stack
856   register number used to modify the register numbers at output time.  */
857
858static void
859mmix_reorg (void)
860{
861  int regno;
862
863  /* We put the number of the highest saved register-file register in a
864     location convenient for the call-patterns to output.  Note that we
865     don't tell dwarf2 about these registers, since it can't restore them
866     anyway.  */
867  for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
868       regno >= 0;
869       regno--)
870    if ((df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
871	|| (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
872      break;
873
874  /* Regardless of whether they're saved (they might be just read), we
875     mustn't include registers that carry parameters.  We could scan the
876     insns to see whether they're actually used (and indeed do other less
877     trivial register usage analysis and transformations), but it seems
878     wasteful to optimize for unused parameter registers.  As of
879     2002-04-30, df_regs_ever_live_p (n) seems to be set for only-reads too, but
880     that might change.  */
881  if (!TARGET_ABI_GNU && regno < crtl->args.info.regs - 1)
882    {
883      regno = crtl->args.info.regs - 1;
884
885      /* We don't want to let this cause us to go over the limit and make
886	 incoming parameter registers be misnumbered and treating the last
887	 parameter register and incoming return value register call-saved.
888	 Stop things at the unmodified scheme.  */
889      if (regno > MMIX_RETURN_VALUE_REGNUM - 1)
890	regno = MMIX_RETURN_VALUE_REGNUM - 1;
891    }
892
893  cfun->machine->highest_saved_stack_register = regno;
894}
895
896/* TARGET_ASM_FUNCTION_EPILOGUE.  */
897
898static void
899mmix_target_asm_function_epilogue (FILE *stream)
900{
901  /* Emit an \n for readability of the generated assembly.  */
902  fputc ('\n', stream);
903}
904
905/* TARGET_ASM_OUTPUT_MI_THUNK.  */
906
907static void
908mmix_asm_output_mi_thunk (FILE *stream,
909			  tree thunk_fndecl ATTRIBUTE_UNUSED,
910			  HOST_WIDE_INT delta,
911			  HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
912			  tree func)
913{
914  /* If you define TARGET_STRUCT_VALUE_RTX that returns 0 (i.e. pass
915     location of structure to return as invisible first argument), you
916     need to tweak this code too.  */
917  const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
918  const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
919
920  assemble_start_function (thunk_fndecl, fnname);
921
922  if (delta >= 0 && delta < 65536)
923    fprintf (stream, "\tINCL %s,%d\n", regname, (int)delta);
924  else if (delta < 0 && delta >= -255)
925    fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, (int)-delta);
926  else
927    {
928      mmix_output_register_setting (stream, 255, delta, 1);
929      fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname);
930    }
931
932  fprintf (stream, "\tJMP ");
933  assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
934  fprintf (stream, "\n");
935  assemble_end_function (thunk_fndecl, fnname);
936}
937
938/* FUNCTION_PROFILER.  */
939
940void
941mmix_function_profiler (FILE *stream ATTRIBUTE_UNUSED,
942			int labelno ATTRIBUTE_UNUSED)
943{
944  sorry ("function_profiler support for MMIX");
945}
946
947/* Worker function for TARGET_SETUP_INCOMING_VARARGS.  For the moment,
948   let's stick to pushing argument registers on the stack.  Later, we
949   can parse all arguments in registers, to improve performance.  */
950
951static void
952mmix_setup_incoming_varargs (cumulative_args_t args_so_farp_v,
953			     const function_arg_info &arg,
954			     int *pretend_sizep,
955			     int second_time ATTRIBUTE_UNUSED)
956{
957  CUMULATIVE_ARGS *args_so_farp = get_cumulative_args (args_so_farp_v);
958
959  /* The last named variable has been handled, but
960     args_so_farp has not been advanced for it.  */
961  if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS)
962    *pretend_sizep = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8;
963
964  /* We assume that one argument takes up one register here.  That should
965     be true until we start messing with multi-reg parameters.  */
966  if ((7 + (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type))) / 8 != 1)
967    internal_error ("MMIX Internal: Last named vararg would not fit in a register");
968}
969
970/* TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
971
972static void
973mmix_asm_trampoline_template (FILE *stream)
974{
975  /* Read a value into the static-chain register and jump somewhere.  The
976     static chain is stored at offset 16, and the function address is
977     stored at offset 24.  */
978
979  fprintf (stream, "\tGETA $255,1F\n\t");
980  fprintf (stream, "LDOU %s,$255,0\n\t", reg_names[MMIX_STATIC_CHAIN_REGNUM]);
981  fprintf (stream, "LDOU $255,$255,8\n\t");
982  fprintf (stream, "GO $255,$255,0\n");
983  fprintf (stream, "1H\tOCTA 0\n\t");
984  fprintf (stream, "OCTA 0\n");
985}
986
987/* TARGET_TRAMPOLINE_INIT.  */
988/* Set the static chain and function pointer field in the trampoline.
989   We also SYNCID here to be sure (doesn't matter in the simulator, but
990   some day it will).  */
991
992static void
993mmix_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
994{
995  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
996  rtx mem;
997
998  emit_block_move (m_tramp, assemble_trampoline_template (),
999		   GEN_INT (2*UNITS_PER_WORD), BLOCK_OP_NORMAL);
1000
1001  mem = adjust_address (m_tramp, DImode, 2*UNITS_PER_WORD);
1002  emit_move_insn (mem, static_chain);
1003  mem = adjust_address (m_tramp, DImode, 3*UNITS_PER_WORD);
1004  emit_move_insn (mem, fnaddr);
1005
1006  mem = adjust_address (m_tramp, DImode, 0);
1007  emit_insn (gen_sync_icache (mem, GEN_INT (TRAMPOLINE_SIZE - 1)));
1008}
1009
1010/* We must exclude constant addresses that have an increment that is not a
1011   multiple of four bytes because of restrictions of the GETA
1012   instruction, unless TARGET_BASE_ADDRESSES.  */
1013
1014int
1015mmix_constant_address_p (rtx x)
1016{
1017  RTX_CODE code = GET_CODE (x);
1018  int addend = 0;
1019  /* When using "base addresses", anything constant goes.  */
1020  int constant_ok = TARGET_BASE_ADDRESSES != 0;
1021
1022  switch (code)
1023    {
1024    case LABEL_REF:
1025    case SYMBOL_REF:
1026      return 1;
1027
1028    case HIGH:
1029      /* FIXME: Don't know how to dissect these.  Avoid them for now,
1030	 except we know they're constants.  */
1031      return constant_ok;
1032
1033    case CONST_INT:
1034      addend = INTVAL (x);
1035      break;
1036
1037    case CONST_DOUBLE:
1038      if (GET_MODE (x) != VOIDmode)
1039	/* Strange that we got here.  FIXME: Check if we do.  */
1040	return constant_ok;
1041      addend = CONST_DOUBLE_LOW (x);
1042      break;
1043
1044    case CONST:
1045      /* Note that expressions with arithmetic on forward references don't
1046	 work in mmixal.  People using gcc assembly code with mmixal might
1047	 need to move arrays and such to before the point of use.  */
1048      if (GET_CODE (XEXP (x, 0)) == PLUS)
1049	{
1050	  rtx x0 = XEXP (XEXP (x, 0), 0);
1051	  rtx x1 = XEXP (XEXP (x, 0), 1);
1052
1053	  if ((GET_CODE (x0) == SYMBOL_REF
1054	       || GET_CODE (x0) == LABEL_REF)
1055	      && (GET_CODE (x1) == CONST_INT
1056		  || (GET_CODE (x1) == CONST_DOUBLE
1057		      && GET_MODE (x1) == VOIDmode)))
1058	    addend = mmix_intval (x1);
1059	  else
1060	    return constant_ok;
1061	}
1062      else
1063	return constant_ok;
1064      break;
1065
1066    default:
1067      return 0;
1068    }
1069
1070  return constant_ok || (addend & 3) == 0;
1071}
1072
1073/* Return 1 if the address is OK, otherwise 0.  */
1074
1075bool
1076mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1077			   rtx x,
1078			   bool strict_checking)
1079{
1080#define MMIX_REG_OK(X)							\
1081  ((strict_checking							\
1082    && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER				\
1083	|| (reg_renumber[REGNO (X)] > 0					\
1084	    && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER)))	\
1085   || (!strict_checking							\
1086       && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER			\
1087	   || REGNO (X) >= FIRST_PSEUDO_REGISTER			\
1088	   || REGNO (X) == ARG_POINTER_REGNUM)))
1089
1090  /* We only accept:
1091     (mem reg)
1092     (mem (plus reg reg))
1093     (mem (plus reg 0..255)).
1094     unless TARGET_BASE_ADDRESSES, in which case we accept all
1095     (mem constant_address) too.  */
1096
1097
1098    /* (mem reg) */
1099  if (REG_P (x) && MMIX_REG_OK (x))
1100    return 1;
1101
1102  if (GET_CODE(x) == PLUS)
1103    {
1104      rtx x1 = XEXP (x, 0);
1105      rtx x2 = XEXP (x, 1);
1106
1107      /* Try swapping the order.  FIXME: Do we need this?  */
1108      if (! REG_P (x1))
1109	{
1110	  rtx tem = x1;
1111	  x1 = x2;
1112	  x2 = tem;
1113	}
1114
1115      /* (mem (plus (reg?) (?))) */
1116      if (!REG_P (x1) || !MMIX_REG_OK (x1))
1117	return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1118
1119      /* (mem (plus (reg) (reg?))) */
1120      if (REG_P (x2) && MMIX_REG_OK (x2))
1121	return 1;
1122
1123      /* (mem (plus (reg) (0..255?))) */
1124      if (satisfies_constraint_I (x2))
1125	return 1;
1126
1127      return 0;
1128    }
1129
1130  return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1131}
1132
1133/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
1134
1135static bool
1136mmix_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1137{
1138  RTX_CODE code = GET_CODE (x);
1139
1140  /* We must allow any number due to the way the cse passes works; if we
1141     do not allow any number here, general_operand will fail, and insns
1142     will fatally fail recognition instead of "softly".  */
1143  if (code == CONST_INT || code == CONST_DOUBLE)
1144    return 1;
1145
1146  return CONSTANT_ADDRESS_P (x);
1147}
1148
1149/* SELECT_CC_MODE.  */
1150
1151machine_mode
1152mmix_select_cc_mode (RTX_CODE op, rtx x, rtx y ATTRIBUTE_UNUSED)
1153{
1154  /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to
1155     output different compare insns.  Note that we do not check the
1156     validity of the comparison here.  */
1157
1158  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
1159    {
1160      if (op == ORDERED || op == UNORDERED || op == UNGE
1161	  || op == UNGT || op == UNLE || op == UNLT)
1162	return CC_FUNmode;
1163
1164      if (op == EQ || op == NE)
1165	return CC_FPEQmode;
1166
1167      return CC_FPmode;
1168    }
1169
1170  if (op == GTU || op == LTU || op == GEU || op == LEU)
1171    return CC_UNSmode;
1172
1173  return CCmode;
1174}
1175
1176/* REVERSIBLE_CC_MODE.  */
1177
1178int
1179mmix_reversible_cc_mode (machine_mode mode)
1180{
1181  /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float
1182     compares.  */
1183  return mode != CC_FPmode;
1184}
1185
1186/* TARGET_RTX_COSTS.  */
1187
1188static bool
1189mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1190		machine_mode mode ATTRIBUTE_UNUSED,
1191		int outer_code ATTRIBUTE_UNUSED,
1192		int opno ATTRIBUTE_UNUSED,
1193		int *total ATTRIBUTE_UNUSED,
1194		bool speed ATTRIBUTE_UNUSED)
1195{
1196  /* For the time being, this is just a stub and we'll accept the
1197     generic calculations, until we can do measurements, at least.
1198     Say we did not modify any calculated costs.  */
1199  return false;
1200}
1201
1202/* TARGET_REGISTER_MOVE_COST.
1203
1204   The special registers can only move to and from general regs, and we
1205   need to check that their constraints match, so say 3 for them.  */
1206
1207static int
1208mmix_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
1209			 reg_class_t from,
1210			 reg_class_t to)
1211{
1212  return (from == GENERAL_REGS && from == to) ? 2 : 3;
1213}
1214
1215/* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a
1216   compile-time constant; it's used in an asm in crtstuff.c, compiled for
1217   the target.  */
1218
1219/* DATA_SECTION_ASM_OP.  */
1220
1221const char *
1222mmix_data_section_asm_op (void)
1223{
1224  return "\t.data ! mmixal:= 8H LOC 9B";
1225}
1226
1227static void
1228mmix_encode_section_info (tree decl, rtx rtl, int first)
1229{
1230  /* Test for an external declaration, and do nothing if it is one.  */
1231  if ((TREE_CODE (decl) == VAR_DECL
1232       && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))
1233      || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))
1234    ;
1235  else if (first && DECL_P (decl))
1236    {
1237      /* For non-visible declarations, add a "@" prefix, which we skip
1238	 when the label is output.  If the label does not have this
1239	 prefix, a ":" is output if -mtoplevel-symbols.
1240
1241	 Note that this does not work for data that is declared extern and
1242	 later defined as static.  If there's code in between, that code
1243	 will refer to the extern declaration, and vice versa.  This just
1244	 means that when -mtoplevel-symbols is in use, we can just handle
1245	 well-behaved ISO-compliant code.  */
1246
1247      const char *str = XSTR (XEXP (rtl, 0), 0);
1248      int len = strlen (str);
1249      char *newstr = XALLOCAVEC (char, len + 2);
1250      newstr[0] = '@';
1251      strcpy (newstr + 1, str);
1252      XSTR (XEXP (rtl, 0), 0) = ggc_alloc_string (newstr, len + 1);
1253    }
1254
1255  /* Set SYMBOL_REF_FLAG for things that we want to access with GETA.  We
1256     may need different options to reach for different things with GETA.
1257     For now, functions and things we know or have been told are constant.  */
1258  if (TREE_CODE (decl) == FUNCTION_DECL
1259      || TREE_CONSTANT (decl)
1260      || (TREE_CODE (decl) == VAR_DECL
1261	  && TREE_READONLY (decl)
1262	  && !TREE_SIDE_EFFECTS (decl)
1263	  && (!DECL_INITIAL (decl)
1264	      || TREE_CONSTANT (DECL_INITIAL (decl)))))
1265    SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
1266}
1267
1268static const char *
1269mmix_strip_name_encoding (const char *name)
1270{
1271  for (; (*name == '@' || *name == '*'); name++)
1272    ;
1273
1274  return name;
1275}
1276
1277/* TARGET_ASM_FILE_START.
1278   We just emit a little comment for the time being.  */
1279
1280static void
1281mmix_file_start (void)
1282{
1283  default_file_start ();
1284
1285  fputs ("! mmixal:= 8H LOC Data_Section\n", asm_out_file);
1286
1287  /* Make sure each file starts with the text section.  */
1288  switch_to_section (text_section);
1289}
1290
1291/* TARGET_ASM_FILE_END.  */
1292
1293static void
1294mmix_file_end (void)
1295{
1296  /* Make sure each file ends with the data section.  */
1297  switch_to_section (data_section);
1298}
1299
1300/* TARGET_ASM_OUTPUT_SOURCE_FILENAME.  */
1301
1302static void
1303mmix_asm_output_source_filename (FILE *stream, const char *name)
1304{
1305  fprintf (stream, "# 1 ");
1306  OUTPUT_QUOTED_STRING (stream, name);
1307  fprintf (stream, "\n");
1308}
1309
1310/* Unfortunately, by default __builtin_ffs is expanded to ffs for
1311   targets where INT_TYPE_SIZE < BITS_PER_WORD.  That together with
1312   newlib since 2017-07-04 implementing ffs as __builtin_ffs leads to
1313   (newlib) ffs recursively calling itself.  But, because of argument
1314   promotion, and with ffs we're counting from the least bit, the
1315   libgcc equivalent for ffsl works equally well for int arguments, so
1316   just use that.  */
1317
1318static void
1319mmix_init_libfuncs (void)
1320{
1321  set_optab_libfunc (ffs_optab, SImode, "__ffsdi2");
1322}
1323
1324/* OUTPUT_QUOTED_STRING.  */
1325
1326void
1327mmix_output_quoted_string (FILE *stream, const char *string, int length)
1328{
1329  const char * string_end = string + length;
1330  static const char *const unwanted_chars = "\"[]\\";
1331
1332  /* Output "any character except newline and double quote character".  We
1333     play it safe and avoid all control characters too.  We also do not
1334     want [] as characters, should input be passed through m4 with [] as
1335     quotes.  Further, we avoid "\", because the GAS port handles it as a
1336     quoting character.  */
1337  while (string < string_end)
1338    {
1339      if (*string
1340	  && (unsigned char) *string < 128
1341	  && !ISCNTRL (*string)
1342	  && strchr (unwanted_chars, *string) == NULL)
1343	{
1344	  fputc ('"', stream);
1345	  while (*string
1346		 && (unsigned char) *string < 128
1347		 && !ISCNTRL (*string)
1348		 && strchr (unwanted_chars, *string) == NULL
1349		 && string < string_end)
1350	    {
1351	      fputc (*string, stream);
1352	      string++;
1353	    }
1354	  fputc ('"', stream);
1355	  if (string < string_end)
1356	    fprintf (stream, ",");
1357	}
1358      if (string < string_end)
1359	{
1360	  fprintf (stream, "#%x", *string & 255);
1361	  string++;
1362	  if (string < string_end)
1363	    fprintf (stream, ",");
1364	}
1365    }
1366}
1367
1368/* Target hook for assembling integer objects.  Use mmix_print_operand
1369   for WYDE and TETRA.  Use mmix_output_octa to output 8-byte
1370   CONST_DOUBLEs.  */
1371
1372static bool
1373mmix_assemble_integer (rtx x, unsigned int size, int aligned_p)
1374{
1375  if (aligned_p)
1376    switch (size)
1377      {
1378	/* We handle a limited number of types of operands in here.  But
1379	   that's ok, because we can punt to generic functions.  We then
1380	   pretend that aligned data isn't needed, so the usual .<pseudo>
1381	   syntax is used (which works for aligned data too).  We actually
1382	   *must* do that, since we say we don't have simple aligned
1383	   pseudos, causing this function to be called.  We just try and
1384	   keep as much compatibility as possible with mmixal syntax for
1385	   normal cases (i.e. without GNU extensions and C only).  */
1386      case 1:
1387	if (GET_CODE (x) != CONST_INT)
1388	  {
1389	    /* There is no "unaligned byte" op or generic function to
1390	       which we can punt, so we have to handle this here.  As
1391	       the expression isn't a plain literal, the generated
1392	       assembly-code can't be mmixal-equivalent (i.e. "BYTE"
1393	       won't work) and thus it's ok to emit the default op
1394	       ".byte". */
1395	    assemble_integer_with_op ("\t.byte\t", x);
1396	    return true;
1397	  }
1398	fputs ("\tBYTE\t", asm_out_file);
1399	mmix_print_operand (asm_out_file, x, 'B');
1400	fputc ('\n', asm_out_file);
1401	return true;
1402
1403      case 2:
1404	if (GET_CODE (x) != CONST_INT)
1405	  {
1406	    aligned_p = 0;
1407	    break;
1408	  }
1409	fputs ("\tWYDE\t", asm_out_file);
1410	mmix_print_operand (asm_out_file, x, 'W');
1411	fputc ('\n', asm_out_file);
1412	return true;
1413
1414      case 4:
1415	if (GET_CODE (x) != CONST_INT)
1416	  {
1417	    aligned_p = 0;
1418	    break;
1419	  }
1420	fputs ("\tTETRA\t", asm_out_file);
1421	mmix_print_operand (asm_out_file, x, 'L');
1422	fputc ('\n', asm_out_file);
1423	return true;
1424
1425      case 8:
1426	/* We don't get here anymore for CONST_DOUBLE, because DImode
1427	   isn't expressed as CONST_DOUBLE, and DFmode is handled
1428	   elsewhere.  */
1429	gcc_assert (GET_CODE (x) != CONST_DOUBLE);
1430	assemble_integer_with_op ("\tOCTA\t", x);
1431	return true;
1432      }
1433  return default_assemble_integer (x, size, aligned_p);
1434}
1435
1436/* ASM_OUTPUT_ASCII.  */
1437
1438void
1439mmix_asm_output_ascii (FILE *stream, const char *string, int length)
1440{
1441  while (length > 0)
1442    {
1443      int chunk_size = length > 60 ? 60 : length;
1444      fprintf (stream, "\tBYTE ");
1445      mmix_output_quoted_string (stream, string, chunk_size);
1446      string += chunk_size;
1447      length -= chunk_size;
1448      fprintf (stream, "\n");
1449    }
1450}
1451
1452/* ASM_OUTPUT_ALIGNED_COMMON.  */
1453
1454void
1455mmix_asm_output_aligned_common (FILE *stream,
1456				const char *name,
1457				int size,
1458				int align)
1459{
1460  /* This is mostly the elfos.h one.  There doesn't seem to be a way to
1461     express this in a mmixal-compatible way.  */
1462  fprintf (stream, "\t.comm\t");
1463  assemble_name (stream, name);
1464  fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",
1465	   size, align / BITS_PER_UNIT);
1466}
1467
1468/* ASM_OUTPUT_ALIGNED_LOCAL.  */
1469
1470void
1471mmix_asm_output_aligned_local (FILE *stream,
1472			       const char *name,
1473			       int size,
1474			       int align)
1475{
1476  switch_to_section (data_section);
1477
1478  ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
1479  assemble_name (stream, name);
1480  fprintf (stream, "\tLOC @+%d\n", size);
1481}
1482
1483/* ASM_OUTPUT_LABEL.  */
1484
1485void
1486mmix_asm_output_label (FILE *stream, const char *name)
1487{
1488  assemble_name (stream, name);
1489  fprintf (stream, "\tIS @\n");
1490}
1491
1492/* ASM_OUTPUT_INTERNAL_LABEL.  */
1493
1494void
1495mmix_asm_output_internal_label (FILE *stream, const char *name)
1496{
1497  assemble_name_raw (stream, name);
1498  fprintf (stream, "\tIS @\n");
1499}
1500
1501/* ASM_DECLARE_REGISTER_GLOBAL.  */
1502
1503void
1504mmix_asm_declare_register_global (FILE *stream ATTRIBUTE_UNUSED,
1505				  tree decl ATTRIBUTE_UNUSED,
1506				  int regno ATTRIBUTE_UNUSED,
1507				  const char *name ATTRIBUTE_UNUSED)
1508{
1509  /* Nothing to do here, but there *will* be, therefore the framework is
1510     here.  */
1511}
1512
1513/* ASM_WEAKEN_LABEL.  */
1514
1515void
1516mmix_asm_weaken_label (FILE *stream ATTRIBUTE_UNUSED,
1517		       const char *name ATTRIBUTE_UNUSED)
1518{
1519  fprintf (stream, "\t.weak ");
1520  assemble_name (stream, name);
1521  fprintf (stream, " ! mmixal-incompatible\n");
1522}
1523
1524/* MAKE_DECL_ONE_ONLY.  */
1525
1526void
1527mmix_make_decl_one_only (tree decl)
1528{
1529  DECL_WEAK (decl) = 1;
1530}
1531
1532/* ASM_OUTPUT_LABELREF.
1533   Strip GCC's '*' and our own '@'.  No order is assumed.  */
1534
1535void
1536mmix_asm_output_labelref (FILE *stream, const char *name)
1537{
1538  int is_extern = 1;
1539
1540  for (; (*name == '@' || *name == '*'); name++)
1541    if (*name == '@')
1542      is_extern = 0;
1543
1544  asm_fprintf (stream, "%s%U%s",
1545	       is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
1546	       name);
1547}
1548
1549/* ASM_OUTPUT_DEF.  */
1550
1551void
1552mmix_asm_output_def (FILE *stream, const char *name, const char *value)
1553{
1554  assemble_name (stream, name);
1555  fprintf (stream, "\tIS ");
1556  assemble_name (stream, value);
1557  fputc ('\n', stream);
1558}
1559
1560/* TARGET_PRINT_OPERAND.  */
1561
1562static void
1563mmix_print_operand (FILE *stream, rtx x, int code)
1564{
1565  /* When we add support for different codes later, we can, when needed,
1566     drop through to the main handler with a modified operand.  */
1567  rtx modified_x = x;
1568  int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
1569
1570  switch (code)
1571    {
1572      /* Unrelated codes are in alphabetic order.  */
1573
1574    case '+':
1575      /* For conditional branches, output "P" for a probable branch.  */
1576      if (TARGET_BRANCH_PREDICT)
1577	{
1578	  x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
1579	  if (x && profile_probability::from_reg_br_prob_note (XINT (x, 0))
1580	      > profile_probability::even ())
1581	    putc ('P', stream);
1582	}
1583      return;
1584
1585    case '.':
1586      /* For the %d in POP %d,0.  */
1587      fprintf (stream, "%d", MMIX_POP_ARGUMENT ());
1588      return;
1589
1590    case 'B':
1591      if (GET_CODE (x) != CONST_INT)
1592	fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1593      fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
1594      return;
1595
1596    case 'H':
1597      /* Highpart.  Must be general register, and not the last one, as
1598	 that one cannot be part of a consecutive register pair.  */
1599      if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1600	internal_error ("MMIX Internal: Bad register: %d", regno);
1601
1602      /* This is big-endian, so the high-part is the first one.  */
1603      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1604      return;
1605
1606    case 'L':
1607      /* Lowpart.  Must be CONST_INT or general register, and not the last
1608	 one, as that one cannot be part of a consecutive register pair.  */
1609      if (GET_CODE (x) == CONST_INT)
1610	{
1611	  fprintf (stream, "#%lx",
1612		   (unsigned long) (INTVAL (x)
1613				    & ((unsigned int) 0x7fffffff * 2 + 1)));
1614	  return;
1615	}
1616
1617      if (GET_CODE (x) == SYMBOL_REF)
1618	{
1619	  output_addr_const (stream, x);
1620	  return;
1621	}
1622
1623      if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1624	internal_error ("MMIX Internal: Bad register: %d", regno);
1625
1626      /* This is big-endian, so the low-part is + 1.  */
1627      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
1628      return;
1629
1630      /* Can't use 'a' because that's a generic modifier for address
1631	 output.  */
1632    case 'A':
1633      mmix_output_shiftvalue_op_from_str (stream, "ANDN",
1634					  ~(uint64_t)
1635					  mmix_intval (x));
1636      return;
1637
1638    case 'i':
1639      mmix_output_shiftvalue_op_from_str (stream, "INC",
1640					  (uint64_t)
1641					  mmix_intval (x));
1642      return;
1643
1644    case 'o':
1645      mmix_output_shiftvalue_op_from_str (stream, "OR",
1646					  (uint64_t)
1647					  mmix_intval (x));
1648      return;
1649
1650    case 's':
1651      mmix_output_shiftvalue_op_from_str (stream, "SET",
1652					  (uint64_t)
1653					  mmix_intval (x));
1654      return;
1655
1656    case 'd':
1657    case 'D':
1658      mmix_output_condition (stream, x, (code == 'D'));
1659      return;
1660
1661    case 'e':
1662      /* Output an extra "e" to make fcmpe, fune.  */
1663      if (TARGET_FCMP_EPSILON)
1664	fprintf (stream, "e");
1665      return;
1666
1667    case 'm':
1668      /* Output the number minus 1.  */
1669      if (GET_CODE (x) != CONST_INT)
1670	{
1671	  fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
1672		      x);
1673	}
1674      fprintf (stream, "%" PRId64,
1675	       (int64_t) (mmix_intval (x) - 1));
1676      return;
1677
1678    case 'p':
1679      /* Store the number of registers we want to save.  This was setup
1680	 by the prologue.  The actual operand contains the number of
1681	 registers to pass, but we don't use it currently.  Anyway, we
1682	 need to output the number of saved registers here.  */
1683      fprintf (stream, "%d",
1684	       cfun->machine->highest_saved_stack_register + 1);
1685      return;
1686
1687    case 'r':
1688      /* Store the register to output a constant to.  */
1689      if (! REG_P (x))
1690	fatal_insn ("MMIX Internal: Expected a register, not this", x);
1691      mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
1692      return;
1693
1694    case 'I':
1695      /* Output the constant.  Note that we use this for floats as well.  */
1696      if (GET_CODE (x) != CONST_INT
1697	  && (GET_CODE (x) != CONST_DOUBLE
1698	      || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
1699		  && GET_MODE (x) != SFmode)))
1700	fatal_insn ("MMIX Internal: Expected a constant, not this", x);
1701      mmix_output_register_setting (stream,
1702				    mmix_output_destination_register,
1703				    mmix_intval (x), 0);
1704      return;
1705
1706    case 'U':
1707      /* An U for unsigned, if TARGET_ZERO_EXTEND.  Ignore the operand.  */
1708      if (TARGET_ZERO_EXTEND)
1709	putc ('U', stream);
1710      return;
1711
1712    case 'v':
1713      mmix_output_shifted_value (stream, (int64_t) mmix_intval (x));
1714      return;
1715
1716    case 'V':
1717      mmix_output_shifted_value (stream, (int64_t) ~mmix_intval (x));
1718      return;
1719
1720    case 'W':
1721      if (GET_CODE (x) != CONST_INT)
1722	fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1723      fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
1724      return;
1725
1726    case 0:
1727      /* Nothing to do.  */
1728      break;
1729
1730    default:
1731      /* Presumably there's a missing case above if we get here.  */
1732      internal_error ("MMIX Internal: Missing %qc case in mmix_print_operand", code);
1733    }
1734
1735  switch (GET_CODE (modified_x))
1736    {
1737    case REG:
1738      regno = REGNO (modified_x);
1739      if (regno >= FIRST_PSEUDO_REGISTER)
1740	internal_error ("MMIX Internal: Bad register: %d", regno);
1741      fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1742      return;
1743
1744    case MEM:
1745      output_address (GET_MODE (modified_x), XEXP (modified_x, 0));
1746      return;
1747
1748    case CONST_INT:
1749      /* For -2147483648, mmixal complains that the constant does not fit
1750	 in 4 bytes, so let's output it as hex.  Take care to handle hosts
1751	 where HOST_WIDE_INT is longer than an int.
1752
1753	 Print small constants +-255 using decimal.  */
1754
1755      if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
1756	fprintf (stream, "%d", (int) (INTVAL (modified_x)));
1757      else
1758	fprintf (stream, "#%x",
1759		 (int) (INTVAL (modified_x)) & (unsigned int) ~0);
1760      return;
1761
1762    case CONST_DOUBLE:
1763      /* Do somewhat as CONST_INT.  */
1764      mmix_output_octa (stream, mmix_intval (modified_x), 0);
1765      return;
1766
1767    case CONST:
1768      output_addr_const (stream, modified_x);
1769      return;
1770
1771    default:
1772      /* No need to test for all strange things.  Let output_addr_const do
1773	 it for us.  */
1774      if (CONSTANT_P (modified_x)
1775	  /* Strangely enough, this is not included in CONSTANT_P.
1776	     FIXME: Ask/check about sanity here.  */
1777	  || LABEL_P (modified_x))
1778	{
1779	  output_addr_const (stream, modified_x);
1780	  return;
1781	}
1782
1783      /* We need the original here.  */
1784      fatal_insn ("MMIX Internal: Cannot decode this operand", x);
1785    }
1786}
1787
1788/* TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
1789
1790static bool
1791mmix_print_operand_punct_valid_p (unsigned char code)
1792{
1793  /* A '+' is used for branch prediction, similar to other ports.  */
1794  return code == '+'
1795    /* A '.' is used for the %d in the POP %d,0 return insn.  */
1796    || code == '.';
1797}
1798
1799/* TARGET_PRINT_OPERAND_ADDRESS.  */
1800
1801static void
1802mmix_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
1803{
1804  if (REG_P (x))
1805    {
1806      /* I find the generated assembly code harder to read without
1807	 the ",0".  */
1808      fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
1809      return;
1810    }
1811  else if (GET_CODE (x) == PLUS)
1812    {
1813      rtx x1 = XEXP (x, 0);
1814      rtx x2 = XEXP (x, 1);
1815
1816      if (REG_P (x1))
1817	{
1818	  fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
1819
1820	  if (REG_P (x2))
1821	    {
1822	      fprintf (stream, "%s",
1823		       reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
1824	      return;
1825	    }
1826	  else if (satisfies_constraint_I (x2))
1827	    {
1828	      output_addr_const (stream, x2);
1829	      return;
1830	    }
1831	}
1832    }
1833
1834  if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (Pmode, x))
1835    {
1836      output_addr_const (stream, x);
1837      return;
1838    }
1839
1840  fatal_insn ("MMIX Internal: This is not a recognized address", x);
1841}
1842
1843/* ASM_OUTPUT_REG_PUSH.  */
1844
1845void
1846mmix_asm_output_reg_push (FILE *stream, int regno)
1847{
1848  fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
1849	   reg_names[MMIX_STACK_POINTER_REGNUM],
1850	   reg_names[MMIX_STACK_POINTER_REGNUM],
1851	   reg_names[MMIX_OUTPUT_REGNO (regno)],
1852	   reg_names[MMIX_STACK_POINTER_REGNUM]);
1853}
1854
1855/* ASM_OUTPUT_REG_POP.  */
1856
1857void
1858mmix_asm_output_reg_pop (FILE *stream, int regno)
1859{
1860  fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
1861	   reg_names[MMIX_OUTPUT_REGNO (regno)],
1862	   reg_names[MMIX_STACK_POINTER_REGNUM],
1863	   reg_names[MMIX_STACK_POINTER_REGNUM]);
1864}
1865
1866/* ASM_OUTPUT_ADDR_DIFF_ELT.  */
1867
1868void
1869mmix_asm_output_addr_diff_elt (FILE *stream,
1870			       rtx body ATTRIBUTE_UNUSED,
1871			       int value,
1872			       int rel)
1873{
1874  fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
1875}
1876
1877/* ASM_OUTPUT_ADDR_VEC_ELT.  */
1878
1879void
1880mmix_asm_output_addr_vec_elt (FILE *stream, int value)
1881{
1882  fprintf (stream, "\tOCTA L:%d\n", value);
1883}
1884
1885/* ASM_OUTPUT_SKIP.  */
1886
1887void
1888mmix_asm_output_skip (FILE *stream, int nbytes)
1889{
1890  fprintf (stream, "\tLOC @+%d\n", nbytes);
1891}
1892
1893/* ASM_OUTPUT_ALIGN.  */
1894
1895void
1896mmix_asm_output_align (FILE *stream, int power)
1897{
1898  /* We need to record the needed alignment of this section in the object,
1899     so we have to output an alignment directive.  Use a .p2align (not
1900     .align) so people will never have to wonder about whether the
1901     argument is in number of bytes or the log2 thereof.  We do it in
1902     addition to the LOC directive, so nothing needs tweaking when
1903     copy-pasting assembly into mmixal.  */
1904 fprintf (stream, "\t.p2align %d\n", power);
1905 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
1906}
1907
1908/* DBX_REGISTER_NUMBER.  */
1909
1910unsigned
1911mmix_dbx_register_number (unsigned regno)
1912{
1913  /* Adjust the register number to the one it will be output as, dammit.
1914     It'd be nice if we could check the assumption that we're filling a
1915     gap, but every register between the last saved register and parameter
1916     registers might be a valid parameter register.  */
1917  regno = MMIX_OUTPUT_REGNO (regno);
1918
1919  /* We need to renumber registers to get the number of the return address
1920     register in the range 0..255.  It is also space-saving if registers
1921     mentioned in the call-frame information (which uses this function by
1922     defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered
1923     0 .. 63.  So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48.  */
1924  return regno >= 224 ? (regno - 224) : (regno + 48);
1925}
1926
1927/* End of target macro support functions.
1928
1929   Now the MMIX port's own functions.  First the exported ones.  */
1930
1931/* Wrapper for get_hard_reg_initial_val since integrate.h isn't included
1932   from insn-emit.c.  */
1933
1934rtx
1935mmix_get_hard_reg_initial_val (machine_mode mode, int regno)
1936{
1937  return get_hard_reg_initial_val (mode, regno);
1938}
1939
1940/* Nonzero when the function epilogue is simple enough that a single
1941   "POP %d,0" should be used even within the function.  */
1942
1943int
1944mmix_use_simple_return (void)
1945{
1946  int regno;
1947
1948  int stack_space_to_allocate
1949    = (crtl->outgoing_args_size
1950       + crtl->args.pretend_args_size
1951       + get_frame_size () + 7) & ~7;
1952
1953  if (!TARGET_USE_RETURN_INSN || !reload_completed)
1954    return 0;
1955
1956  for (regno = 255;
1957       regno >= MMIX_FIRST_GLOBAL_REGNUM;
1958       regno--)
1959    /* Note that we assume that the frame-pointer-register is one of these
1960       registers, in which case we don't count it here.  */
1961    if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1962	  && df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno)))
1963	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
1964      return 0;
1965
1966  if (frame_pointer_needed)
1967    stack_space_to_allocate += 8;
1968
1969  if (MMIX_CFUN_HAS_LANDING_PAD)
1970    stack_space_to_allocate += 16;
1971  else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
1972    stack_space_to_allocate += 8;
1973
1974  return stack_space_to_allocate == 0;
1975}
1976
1977
1978/* Expands the function prologue into RTX.  */
1979
1980void
1981mmix_expand_prologue (void)
1982{
1983  HOST_WIDE_INT locals_size = get_frame_size ();
1984  int regno;
1985  HOST_WIDE_INT stack_space_to_allocate
1986    = (crtl->outgoing_args_size
1987       + crtl->args.pretend_args_size
1988       + locals_size + 7) & ~7;
1989  HOST_WIDE_INT offset = -8;
1990
1991  /* Add room needed to save global non-register-stack registers.  */
1992  for (regno = 255;
1993       regno >= MMIX_FIRST_GLOBAL_REGNUM;
1994       regno--)
1995    /* Note that we assume that the frame-pointer-register is one of these
1996       registers, in which case we don't count it here.  */
1997    if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1998	  && df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno)))
1999	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
2000      stack_space_to_allocate += 8;
2001
2002  /* If we do have a frame-pointer, add room for it.  */
2003  if (frame_pointer_needed)
2004    stack_space_to_allocate += 8;
2005
2006  /* If we have a non-local label, we need to be able to unwind to it, so
2007     store the current register stack pointer.  Also store the return
2008     address if we do that.  */
2009  if (MMIX_CFUN_HAS_LANDING_PAD)
2010    stack_space_to_allocate += 16;
2011  else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2012    /* If we do have a saved return-address slot, add room for it.  */
2013    stack_space_to_allocate += 8;
2014
2015  /* Make sure we don't get an unaligned stack.  */
2016  if ((stack_space_to_allocate % 8) != 0)
2017    internal_error ("stack frame not a multiple of 8 bytes: %wd",
2018		    stack_space_to_allocate);
2019
2020  if (crtl->args.pretend_args_size)
2021    {
2022      int mmix_first_vararg_reg
2023	= (MMIX_FIRST_INCOMING_ARG_REGNUM
2024	   + (MMIX_MAX_ARGS_IN_REGS
2025	      - crtl->args.pretend_args_size / 8));
2026
2027      for (regno
2028	     = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
2029	   regno >= mmix_first_vararg_reg;
2030	   regno--)
2031	{
2032	  if (offset < 0)
2033	    {
2034	      HOST_WIDE_INT stack_chunk
2035		= stack_space_to_allocate > (256 - 8)
2036		? (256 - 8) : stack_space_to_allocate;
2037
2038	      mmix_emit_sp_add (-stack_chunk);
2039	      offset += stack_chunk;
2040	      stack_space_to_allocate -= stack_chunk;
2041	    }
2042
2043	  /* These registers aren't actually saved (as in "will be
2044	     restored"), so don't tell DWARF2 they're saved.  */
2045	  emit_move_insn (gen_rtx_MEM (DImode,
2046				       plus_constant (Pmode, stack_pointer_rtx,
2047						      offset)),
2048			  gen_rtx_REG (DImode, regno));
2049	  offset -= 8;
2050	}
2051    }
2052
2053  /* Store the frame-pointer.  */
2054
2055  if (frame_pointer_needed)
2056    {
2057      rtx insn;
2058
2059      if (offset < 0)
2060	{
2061	  /* Get 8 less than otherwise, since we need to reach offset + 8.  */
2062	  HOST_WIDE_INT stack_chunk
2063	    = stack_space_to_allocate > (256 - 8 - 8)
2064	    ? (256 - 8 - 8) : stack_space_to_allocate;
2065
2066	  mmix_emit_sp_add (-stack_chunk);
2067
2068	  offset += stack_chunk;
2069	  stack_space_to_allocate -= stack_chunk;
2070	}
2071
2072      insn = emit_move_insn (gen_rtx_MEM (DImode,
2073					  plus_constant (Pmode,
2074							 stack_pointer_rtx,
2075							 offset)),
2076			     hard_frame_pointer_rtx);
2077      RTX_FRAME_RELATED_P (insn) = 1;
2078      insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
2079				    stack_pointer_rtx,
2080				    GEN_INT (offset + 8)));
2081      RTX_FRAME_RELATED_P (insn) = 1;
2082      offset -= 8;
2083    }
2084
2085  if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2086    {
2087      rtx tmpreg, retreg;
2088      rtx insn;
2089
2090      /* Store the return-address, if one is needed on the stack.  We
2091	 usually store it in a register when needed, but that doesn't work
2092	 with -fexceptions.  */
2093
2094      if (offset < 0)
2095	{
2096	  /* Get 8 less than otherwise, since we need to reach offset + 8.  */
2097	  HOST_WIDE_INT stack_chunk
2098	    = stack_space_to_allocate > (256 - 8 - 8)
2099	    ? (256 - 8 - 8) : stack_space_to_allocate;
2100
2101	  mmix_emit_sp_add (-stack_chunk);
2102
2103	  offset += stack_chunk;
2104	  stack_space_to_allocate -= stack_chunk;
2105	}
2106
2107      tmpreg = gen_rtx_REG (DImode, 255);
2108      retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM);
2109
2110      /* Dwarf2 code is confused by the use of a temporary register for
2111	 storing the return address, so we have to express it as a note,
2112	 which we attach to the actual store insn.  */
2113      emit_move_insn (tmpreg, retreg);
2114
2115      insn = emit_move_insn (gen_rtx_MEM (DImode,
2116					  plus_constant (Pmode,
2117							 stack_pointer_rtx,
2118							 offset)),
2119			     tmpreg);
2120      RTX_FRAME_RELATED_P (insn) = 1;
2121      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2122		    gen_rtx_SET (gen_rtx_MEM (DImode,
2123					      plus_constant (Pmode,
2124							     stack_pointer_rtx,
2125							     offset)),
2126				 retreg));
2127
2128      offset -= 8;
2129    }
2130  else if (MMIX_CFUN_HAS_LANDING_PAD)
2131    offset -= 8;
2132
2133  if (MMIX_CFUN_HAS_LANDING_PAD)
2134    {
2135      /* Store the register defining the numbering of local registers, so
2136	 we know how long to unwind the register stack.  */
2137
2138      if (offset < 0)
2139	{
2140	  /* Get 8 less than otherwise, since we need to reach offset + 8.  */
2141	  HOST_WIDE_INT stack_chunk
2142	    = stack_space_to_allocate > (256 - 8 - 8)
2143	    ? (256 - 8 - 8) : stack_space_to_allocate;
2144
2145	  mmix_emit_sp_add (-stack_chunk);
2146
2147	  offset += stack_chunk;
2148	  stack_space_to_allocate -= stack_chunk;
2149	}
2150
2151      /* We don't tell dwarf2 about this one; we just have it to unwind
2152	 the register stack at landing pads.  FIXME: It's a kludge because
2153	 we can't describe the effect of the PUSHJ and PUSHGO insns on the
2154	 register stack at the moment.  Best thing would be to handle it
2155	 like stack-pointer offsets.  Better: some hook into dwarf2out.c
2156	 to produce DW_CFA_expression:s that specify the increment of rO,
2157	 and unwind it at eh_return (preferred) or at the landing pad.
2158	 Then saves to $0..$G-1 could be specified through that register.  */
2159
2160      emit_move_insn (gen_rtx_REG (DImode, 255),
2161		      gen_rtx_REG (DImode,
2162				   MMIX_rO_REGNUM));
2163      emit_move_insn (gen_rtx_MEM (DImode,
2164				   plus_constant (Pmode, stack_pointer_rtx,
2165						  offset)),
2166		      gen_rtx_REG (DImode, 255));
2167      offset -= 8;
2168    }
2169
2170  /* After the return-address and the frame-pointer, we have the local
2171     variables.  They're the ones that may have an "unaligned" size.  */
2172  offset -= (locals_size + 7) & ~7;
2173
2174  /* Now store all registers that are global, i.e. not saved by the
2175     register file machinery.
2176
2177     It is assumed that the frame-pointer is one of these registers, so it
2178     is explicitly excluded in the count.  */
2179
2180  for (regno = 255;
2181       regno >= MMIX_FIRST_GLOBAL_REGNUM;
2182       regno--)
2183    if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2184	 && df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
2185	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
2186      {
2187	rtx insn;
2188
2189	if (offset < 0)
2190	  {
2191	    HOST_WIDE_INT stack_chunk
2192	      = (stack_space_to_allocate > (256 - offset - 8)
2193		 ? (256 - offset - 8) : stack_space_to_allocate);
2194
2195	    mmix_emit_sp_add (-stack_chunk);
2196	    offset += stack_chunk;
2197	    stack_space_to_allocate -= stack_chunk;
2198	  }
2199
2200	insn = emit_move_insn (gen_rtx_MEM (DImode,
2201					    plus_constant (Pmode,
2202							   stack_pointer_rtx,
2203							   offset)),
2204			       gen_rtx_REG (DImode, regno));
2205	RTX_FRAME_RELATED_P (insn) = 1;
2206	offset -= 8;
2207      }
2208
2209  /* Finally, allocate room for outgoing args and local vars if room
2210     wasn't allocated above.  */
2211  if (stack_space_to_allocate)
2212    mmix_emit_sp_add (-stack_space_to_allocate);
2213}
2214
2215/* Expands the function epilogue into RTX.  */
2216
2217void
2218mmix_expand_epilogue (void)
2219{
2220  HOST_WIDE_INT locals_size = get_frame_size ();
2221  int regno;
2222  HOST_WIDE_INT stack_space_to_deallocate
2223    = (crtl->outgoing_args_size
2224       + crtl->args.pretend_args_size
2225       + locals_size + 7) & ~7;
2226
2227  /* The first address to access is beyond the outgoing_args area.  */
2228  HOST_WIDE_INT offset = crtl->outgoing_args_size;
2229
2230  /* Add the space for global non-register-stack registers.
2231     It is assumed that the frame-pointer register can be one of these
2232     registers, in which case it is excluded from the count when needed.  */
2233  for (regno = 255;
2234       regno >= MMIX_FIRST_GLOBAL_REGNUM;
2235       regno--)
2236    if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2237	 && df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
2238	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
2239      stack_space_to_deallocate += 8;
2240
2241  /* Add in the space for register stack-pointer.  If so, always add room
2242     for the saved PC.  */
2243  if (MMIX_CFUN_HAS_LANDING_PAD)
2244    stack_space_to_deallocate += 16;
2245  else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2246    /* If we have a saved return-address slot, add it in.  */
2247    stack_space_to_deallocate += 8;
2248
2249  /* Add in the frame-pointer.  */
2250  if (frame_pointer_needed)
2251    stack_space_to_deallocate += 8;
2252
2253  /* Make sure we don't get an unaligned stack.  */
2254  if ((stack_space_to_deallocate % 8) != 0)
2255    internal_error ("stack frame not a multiple of octabyte: %wd",
2256		    stack_space_to_deallocate);
2257
2258  /* We will add back small offsets to the stack pointer as we go.
2259     First, we restore all registers that are global, i.e. not saved by
2260     the register file machinery.  */
2261
2262  for (regno = MMIX_FIRST_GLOBAL_REGNUM;
2263       regno <= 255;
2264       regno++)
2265    if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2266	 && df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
2267	|| IS_MMIX_EH_RETURN_DATA_REG (regno))
2268      {
2269	if (offset > 255)
2270	  {
2271	    mmix_emit_sp_add (offset);
2272	    stack_space_to_deallocate -= offset;
2273	    offset = 0;
2274	  }
2275
2276	emit_move_insn (gen_rtx_REG (DImode, regno),
2277			gen_rtx_MEM (DImode,
2278				     plus_constant (Pmode, stack_pointer_rtx,
2279						    offset)));
2280	offset += 8;
2281      }
2282
2283  /* Here is where the local variables were.  As in the prologue, they
2284     might be of an unaligned size.  */
2285  offset += (locals_size + 7) & ~7;
2286
2287  /* The saved register stack pointer is just below the frame-pointer
2288     register.  We don't need to restore it "manually"; the POP
2289     instruction does that.  */
2290  if (MMIX_CFUN_HAS_LANDING_PAD)
2291    offset += 16;
2292  else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2293    /* The return-address slot is just below the frame-pointer register.
2294       We don't need to restore it because we don't really use it.  */
2295    offset += 8;
2296
2297  /* Get back the old frame-pointer-value.  */
2298  if (frame_pointer_needed)
2299    {
2300      if (offset > 255)
2301	{
2302	  mmix_emit_sp_add (offset);
2303
2304	  stack_space_to_deallocate -= offset;
2305	  offset = 0;
2306	}
2307
2308      emit_move_insn (hard_frame_pointer_rtx,
2309		      gen_rtx_MEM (DImode,
2310				   plus_constant (Pmode, stack_pointer_rtx,
2311						  offset)));
2312      offset += 8;
2313    }
2314
2315  /* We do not need to restore pretended incoming args, just add back
2316     offset to sp.  */
2317  if (stack_space_to_deallocate != 0)
2318    mmix_emit_sp_add (stack_space_to_deallocate);
2319
2320  if (crtl->calls_eh_return)
2321    /* Adjust the (normal) stack-pointer to that of the receiver.
2322       FIXME: It would be nice if we could also adjust the register stack
2323       here, but we need to express it through DWARF 2 too.  */
2324    emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
2325			   gen_rtx_REG (DImode,
2326					MMIX_EH_RETURN_STACKADJ_REGNUM)));
2327}
2328
2329/* Output an optimal sequence for setting a register to a specific
2330   constant.  Used in an alternative for const_ints in movdi, and when
2331   using large stack-frame offsets.
2332
2333   Use do_begin_end to say if a line-starting TAB and newline before the
2334   first insn and after the last insn is wanted.  */
2335
2336void
2337mmix_output_register_setting (FILE *stream,
2338			      int regno,
2339			      int64_t value,
2340			      int do_begin_end)
2341{
2342  if (do_begin_end)
2343    fprintf (stream, "\t");
2344
2345  if (insn_const_int_ok_for_constraint (value, CONSTRAINT_K))
2346    fprintf (stream, "NEGU %s,0,%" PRId64, reg_names[regno], -value);
2347  else if (mmix_shiftable_wyde_value ((uint64_t) value))
2348    {
2349      /* First, the one-insn cases.  */
2350      mmix_output_shiftvalue_op_from_str (stream, "SET",
2351					  (uint64_t)
2352					  value);
2353      fprintf (stream, " %s,", reg_names[regno]);
2354      mmix_output_shifted_value (stream, (uint64_t) value);
2355    }
2356  else if (mmix_shiftable_wyde_value (-(uint64_t) value))
2357    {
2358      /* We do this to get a bit more legible assembly code.  The next
2359	 alternative is mostly redundant with this.  */
2360
2361      mmix_output_shiftvalue_op_from_str (stream, "SET",
2362					  -(uint64_t)
2363					  value);
2364      fprintf (stream, " %s,", reg_names[regno]);
2365      mmix_output_shifted_value (stream, -(uint64_t) value);
2366      fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
2367	       reg_names[regno]);
2368    }
2369  else if (mmix_shiftable_wyde_value (~(uint64_t) value))
2370    {
2371      /* Slightly more expensive, the two-insn cases.  */
2372
2373      /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255)
2374	 is shiftable, or any other one-insn transformation of the value.
2375	 FIXME: Check first if the value is "shiftable" by two loading
2376	 with two insns, since it makes more readable assembly code (if
2377	 anyone else cares).  */
2378
2379      mmix_output_shiftvalue_op_from_str (stream, "SET",
2380					  ~(uint64_t)
2381					  value);
2382      fprintf (stream, " %s,", reg_names[regno]);
2383      mmix_output_shifted_value (stream, ~(uint64_t) value);
2384      fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
2385	       reg_names[regno]);
2386    }
2387  else
2388    {
2389      /* The generic case.  2..4 insns.  */
2390      static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
2391      const char *op = "SET";
2392      const char *line_begin = "";
2393      int insns = 0;
2394      int i;
2395      int64_t tmpvalue = value;
2396
2397      /* Compute the number of insns needed to output this constant.  */
2398      for (i = 0; i < 4 && tmpvalue != 0; i++)
2399	{
2400	  if (tmpvalue & 65535)
2401	    insns++;
2402	  tmpvalue >>= 16;
2403	}
2404      if (TARGET_BASE_ADDRESSES && insns == 3)
2405	{
2406	  /* The number three is based on a static observation on
2407	     ghostscript-6.52.  Two and four are excluded because there
2408	     are too many such constants, and each unique constant (maybe
2409	     offset by 1..255) were used few times compared to other uses,
2410	     e.g. addresses.
2411
2412	     We use base-plus-offset addressing to force it into a global
2413	     register; we just use a "LDA reg,VALUE", which will cause the
2414	     assembler and linker to DTRT (for constants as well as
2415	     addresses).  */
2416	  fprintf (stream, "LDA %s,", reg_names[regno]);
2417	  mmix_output_octa (stream, value, 0);
2418	}
2419      else
2420	{
2421	  /* Output pertinent parts of the 4-wyde sequence.
2422	     Still more to do if we want this to be optimal, but hey...
2423	     Note that the zero case has been handled above.  */
2424	  for (i = 0; i < 4 && value != 0; i++)
2425	    {
2426	      if (value & 65535)
2427		{
2428		  fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
2429			   higher_parts[i], reg_names[regno],
2430			   (int) (value & 65535));
2431		  /* The first one sets the rest of the bits to 0, the next
2432		     ones add set bits.  */
2433		  op = "INC";
2434		  line_begin = "\n\t";
2435		}
2436
2437	      value >>= 16;
2438	    }
2439	}
2440    }
2441
2442  if (do_begin_end)
2443    fprintf (stream, "\n");
2444}
2445
2446/* Return 1 if value is 0..65535*2**(16*N) for N=0..3.
2447   else return 0.  */
2448
2449int
2450mmix_shiftable_wyde_value (uint64_t value)
2451{
2452  /* Shift by 16 bits per group, stop when we've found two groups with
2453     nonzero bits.  */
2454  int i;
2455  int has_candidate = 0;
2456
2457  for (i = 0; i < 4; i++)
2458    {
2459      if (value & 65535)
2460	{
2461	  if (has_candidate)
2462	    return 0;
2463	  else
2464	    has_candidate = 1;
2465	}
2466
2467      value >>= 16;
2468    }
2469
2470  return 1;
2471}
2472
2473/* X and Y are two things to compare using CODE.  Return the rtx for
2474   the cc-reg in the proper mode.  */
2475
2476rtx
2477mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y)
2478{
2479  machine_mode ccmode = SELECT_CC_MODE (code, x, y);
2480  return gen_reg_rtx (ccmode);
2481}
2482
2483/* Local (static) helper functions.  */
2484
2485static void
2486mmix_emit_sp_add (HOST_WIDE_INT offset)
2487{
2488  rtx insn;
2489
2490  if (offset < 0)
2491    {
2492      /* Negative stack-pointer adjustments are allocations and appear in
2493	 the prologue only.  We mark them as frame-related so unwind and
2494	 debug info is properly emitted for them.  */
2495      if (offset > -255)
2496	insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2497				      stack_pointer_rtx,
2498				      GEN_INT (offset)));
2499      else
2500	{
2501	  rtx tmpr = gen_rtx_REG (DImode, 255);
2502	  RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1;
2503	  insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2504					stack_pointer_rtx, tmpr));
2505	}
2506      RTX_FRAME_RELATED_P (insn) = 1;
2507    }
2508  else
2509    {
2510      /* Positive adjustments are in the epilogue only.  Don't mark them
2511	 as "frame-related" for unwind info.  */
2512      if (insn_const_int_ok_for_constraint (offset, CONSTRAINT_L))
2513	emit_insn (gen_adddi3 (stack_pointer_rtx,
2514			       stack_pointer_rtx,
2515			       GEN_INT (offset)));
2516      else
2517	{
2518	  rtx tmpr = gen_rtx_REG (DImode, 255);
2519	  emit_move_insn (tmpr, GEN_INT (offset));
2520	  insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2521					stack_pointer_rtx, tmpr));
2522	}
2523    }
2524}
2525
2526/* Print operator suitable for doing something with a shiftable
2527   wyde.  The type of operator is passed as an asm output modifier.  */
2528
2529static void
2530mmix_output_shiftvalue_op_from_str (FILE *stream,
2531				    const char *mainop,
2532				    int64_t value)
2533{
2534  static const char *const op_part[] = {"L", "ML", "MH", "H"};
2535  int i;
2536
2537  if (! mmix_shiftable_wyde_value (value))
2538    {
2539      char s[sizeof ("0xffffffffffffffff")];
2540      sprintf (s, "%#" PRIx64, value);
2541      internal_error ("MMIX Internal: %s is not a shiftable int", s);
2542    }
2543
2544  for (i = 0; i < 4; i++)
2545    {
2546      /* We know we're through when we find one-bits in the low
2547	 16 bits.  */
2548      if (value & 0xffff)
2549	{
2550	  fprintf (stream, "%s%s", mainop, op_part[i]);
2551	  return;
2552	}
2553      value >>= 16;
2554    }
2555
2556  /* No bits set?  Then it must have been zero.  */
2557  fprintf (stream, "%sL", mainop);
2558}
2559
2560/* Print a 64-bit value, optionally prefixed by assembly pseudo.  */
2561
2562static void
2563mmix_output_octa (FILE *stream, int64_t value, int do_begin_end)
2564{
2565  if (do_begin_end)
2566    fprintf (stream, "\tOCTA ");
2567
2568  /* Provide a few alternative output formats depending on the number, to
2569     improve legibility of assembler output.  */
2570  if ((value < (int64_t) 0 && value > (int64_t) -10000)
2571      || (value >= (int64_t) 0 && value <= (int64_t) 16384))
2572    fprintf (stream, "%d", (int) value);
2573  else if (value > (int64_t) 0
2574	   && value < ((int64_t) 1 << 31) * 2)
2575    fprintf (stream, "#%x", (unsigned int) value);
2576  else if (sizeof (HOST_WIDE_INT) == sizeof (int64_t))
2577    /* We need to avoid the not-so-universal "0x" prefix; we need the
2578       pure hex-digits together with the mmixal "#" hex prefix.  */
2579    fprintf (stream, "#" HOST_WIDE_INT_PRINT_HEX_PURE,
2580	     (HOST_WIDE_INT) value);
2581  else /* Need to avoid the hex output; there's no ...WIDEST...HEX_PURE.  */
2582    fprintf (stream, "%" PRIu64, value);
2583
2584  if (do_begin_end)
2585    fprintf (stream, "\n");
2586}
2587
2588/* Print the presumed shiftable wyde argument shifted into place (to
2589   be output with an operand).  */
2590
2591static void
2592mmix_output_shifted_value (FILE *stream, int64_t value)
2593{
2594  int i;
2595
2596  if (! mmix_shiftable_wyde_value (value))
2597    {
2598      char s[16+2+1];
2599      sprintf (s, "%#" PRIx64, value);
2600      internal_error ("MMIX Internal: %s is not a shiftable int", s);
2601    }
2602
2603  for (i = 0; i < 4; i++)
2604    {
2605      /* We know we're through when we find one-bits in the low 16 bits.  */
2606      if (value & 0xffff)
2607	{
2608	  fprintf (stream, "#%x", (int) (value & 0xffff));
2609	  return;
2610	}
2611
2612    value >>= 16;
2613  }
2614
2615  /* No bits set?  Then it must have been zero.  */
2616  fprintf (stream, "0");
2617}
2618
2619/* Output an MMIX condition name corresponding to an operator
2620   and operands:
2621   (comparison_operator [(comparison_operator ...) (const_int 0)])
2622   which means we have to look at *two* operators.
2623
2624   The argument "reversed" refers to reversal of the condition (not the
2625   same as swapping the arguments).  */
2626
2627static void
2628mmix_output_condition (FILE *stream, const_rtx x, int reversed)
2629{
2630  struct cc_conv
2631  {
2632    RTX_CODE cc;
2633
2634    /* The normal output cc-code.  */
2635    const char *const normal;
2636
2637    /* The reversed cc-code, or NULL if invalid.  */
2638    const char *const reversed;
2639  };
2640
2641  struct cc_type_conv
2642  {
2643    machine_mode cc_mode;
2644
2645    /* Terminated with {UNKNOWN, NULL, NULL} */
2646    const struct cc_conv *const convs;
2647  };
2648
2649#undef CCEND
2650#define CCEND {UNKNOWN, NULL, NULL}
2651
2652  static const struct cc_conv cc_fun_convs[]
2653    = {{ORDERED, "Z", "P"},
2654       {UNORDERED, "P", "Z"},
2655       CCEND};
2656  static const struct cc_conv cc_fp_convs[]
2657    = {{GT, "P", NULL},
2658       {LT, "N", NULL},
2659       CCEND};
2660  static const struct cc_conv cc_fpeq_convs[]
2661    = {{NE, "Z", "P"},
2662       {EQ, "P", "Z"},
2663       CCEND};
2664  static const struct cc_conv cc_uns_convs[]
2665    = {{GEU, "NN", "N"},
2666       {GTU, "P", "NP"},
2667       {LEU, "NP", "P"},
2668       {LTU, "N", "NN"},
2669       CCEND};
2670  static const struct cc_conv cc_signed_convs[]
2671    = {{NE, "NZ", "Z"},
2672       {EQ, "Z", "NZ"},
2673       {GE, "NN", "N"},
2674       {GT, "P", "NP"},
2675       {LE, "NP", "P"},
2676       {LT, "N", "NN"},
2677       CCEND};
2678  static const struct cc_conv cc_di_convs[]
2679    = {{NE, "NZ", "Z"},
2680       {EQ, "Z", "NZ"},
2681       {GE, "NN", "N"},
2682       {GT, "P", "NP"},
2683       {LE, "NP", "P"},
2684       {LT, "N", "NN"},
2685       {GTU, "NZ", "Z"},
2686       {LEU, "Z", "NZ"},
2687       CCEND};
2688#undef CCEND
2689
2690  static const struct cc_type_conv cc_convs[]
2691    = {{E_CC_FUNmode, cc_fun_convs},
2692       {E_CC_FPmode, cc_fp_convs},
2693       {E_CC_FPEQmode, cc_fpeq_convs},
2694       {E_CC_UNSmode, cc_uns_convs},
2695       {E_CCmode, cc_signed_convs},
2696       {E_DImode, cc_di_convs}};
2697
2698  size_t i;
2699  int j;
2700
2701  machine_mode mode = GET_MODE (XEXP (x, 0));
2702  RTX_CODE cc = GET_CODE (x);
2703
2704  for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
2705    {
2706      if (mode == cc_convs[i].cc_mode)
2707	{
2708	  for (j = 0; cc_convs[i].convs[j].cc != UNKNOWN; j++)
2709	    if (cc == cc_convs[i].convs[j].cc)
2710	      {
2711		const char *mmix_cc
2712		  = (reversed ? cc_convs[i].convs[j].reversed
2713		     : cc_convs[i].convs[j].normal);
2714
2715		if (mmix_cc == NULL)
2716		  fatal_insn ("MMIX Internal: Trying to output invalidly\
2717 reversed condition:", x);
2718
2719		fprintf (stream, "%s", mmix_cc);
2720		return;
2721	      }
2722
2723	  fatal_insn ("MMIX Internal: What's the CC of this?", x);
2724	}
2725    }
2726
2727  fatal_insn ("MMIX Internal: What is the CC of this?", x);
2728}
2729
2730/* Return the bit-value for a const_int or const_double.  */
2731
2732int64_t
2733mmix_intval (const_rtx x)
2734{
2735  if (GET_CODE (x) == CONST_INT)
2736    return INTVAL (x);
2737
2738  /* We make a little song and dance because converting to long long in
2739     gcc-2.7.2 is broken.  I still want people to be able to use it for
2740     cross-compilation to MMIX.  */
2741  if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
2742    return CONST_DOUBLE_HIGH (x);
2743
2744  if (GET_CODE (x) == CONST_DOUBLE)
2745    {
2746      if (GET_MODE (x) == DFmode)
2747	{
2748	  long bits[2];
2749
2750	  REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
2751
2752	  /* The double cast is necessary to avoid getting the long
2753	     sign-extended to unsigned long long(!) when they're of
2754	     different size (usually 32-bit hosts).  */
2755	  return
2756	    ((uint64_t) (unsigned long) bits[0]
2757	     << (uint64_t) 32U)
2758	    | (uint64_t) (unsigned long) bits[1];
2759	}
2760      else if (GET_MODE (x) == SFmode)
2761	{
2762	  long bits;
2763	  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
2764
2765	  return (unsigned long) bits;
2766	}
2767    }
2768
2769  fatal_insn ("MMIX Internal: This is not a constant:", x);
2770}
2771
2772/* Worker function for TARGET_PROMOTE_FUNCTION_MODE.  */
2773
2774machine_mode
2775mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
2776                            machine_mode mode,
2777                            int *punsignedp ATTRIBUTE_UNUSED,
2778                            const_tree fntype ATTRIBUTE_UNUSED,
2779                            int for_return)
2780{
2781  /* Apparently not doing TRT if int < register-size.  FIXME: Perhaps
2782     FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say.  */
2783  if (for_return == 1)
2784    return mode;
2785
2786  /* Promotion of modes currently generates slow code, extending before
2787     operation, so we do it only for arguments.  */
2788  if (GET_MODE_CLASS (mode) == MODE_INT
2789      && GET_MODE_SIZE (mode) < 8)
2790    return DImode;
2791  else
2792    return mode;
2793}
2794/* Worker function for TARGET_STRUCT_VALUE_RTX.  */
2795
2796static rtx
2797mmix_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
2798		       int incoming ATTRIBUTE_UNUSED)
2799{
2800  return gen_rtx_REG (Pmode, MMIX_STRUCT_VALUE_REGNUM);
2801}
2802
2803/* Worker function for TARGET_FRAME_POINTER_REQUIRED.
2804
2805   FIXME: Is this requirement built-in?  Anyway, we should try to get rid
2806   of it; we can deduce the value.  */
2807
2808bool
2809mmix_frame_pointer_required (void)
2810{
2811  return (cfun->has_nonlocal_label);
2812}
2813
2814/*
2815 * Local variables:
2816 * eval: (c-set-style "gnu")
2817 * indent-tabs-mode: t
2818 * End:
2819 */
2820