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