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