* config/i386/i386.c (ix86_expand_prologue): Tighten assert
[official-gcc.git] / gcc / config / mmix / mmix.c
blob4a73162c18c09d20329b109b679ea49fe2a34554
1 /* Definitions of target machine for GNU compiler, for MMIX.
2 Copyright (C) 2000-2017 Free Software Foundation, Inc.
3 Contributed by Hans-Peter Nilsson (hp@bitrange.com)
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "target.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "stringpool.h"
29 #include "attribs.h"
30 #include "df.h"
31 #include "memmodel.h"
32 #include "tm_p.h"
33 #include "insn-config.h"
34 #include "regs.h"
35 #include "emit-rtl.h"
36 #include "recog.h"
37 #include "diagnostic-core.h"
38 #include "output.h"
39 #include "varasm.h"
40 #include "stor-layout.h"
41 #include "calls.h"
42 #include "explow.h"
43 #include "expr.h"
44 #include "dwarf2.h"
45 #include "tm-constrs.h"
46 #include "builtins.h"
48 /* This file should be included last. */
49 #include "target-def.h"
51 /* First some local helper definitions. */
52 #define MMIX_FIRST_GLOBAL_REGNUM 32
54 /* We'd need a current_function_has_landing_pad. It's marked as such when
55 a nonlocal_goto_receiver is expanded. Not just a C++ thing, but
56 mostly. */
57 #define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)
59 /* We have no means to tell DWARF 2 about the register stack, so we need
60 to store the return address on the stack if an exception can get into
61 this function. FIXME: Narrow condition. Before any whole-function
62 analysis, df_regs_ever_live_p () isn't initialized. We know it's up-to-date
63 after reload_completed; it may contain incorrect information some time
64 before that. Within a RTL sequence (after a call to start_sequence,
65 such as in RTL expanders), leaf_function_p doesn't see all insns
66 (perhaps any insn). But regs_ever_live is up-to-date when
67 leaf_function_p () isn't, so we "or" them together to get accurate
68 information. FIXME: Some tweak to leaf_function_p might be
69 preferable. */
70 #define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
71 (flag_exceptions \
72 && ((reload_completed && df_regs_ever_live_p (MMIX_rJ_REGNUM)) \
73 || !leaf_function_p ()))
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))
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))
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)
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;
113 /* Declarations of locals. */
115 /* Intermediate for insn output. */
116 static int mmix_output_destination_register;
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, machine_mode, tree, int *, int);
142 static void mmix_file_start (void);
143 static void mmix_file_end (void);
144 static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
145 static int mmix_register_move_cost (machine_mode,
146 reg_class_t, reg_class_t);
147 static rtx mmix_struct_value_rtx (tree, int);
148 static machine_mode mmix_promote_function_mode (const_tree,
149 machine_mode,
150 int *, const_tree, int);
151 static void mmix_function_arg_advance (cumulative_args_t, machine_mode,
152 const_tree, bool);
153 static rtx mmix_function_arg_1 (const cumulative_args_t, machine_mode,
154 const_tree, bool, bool);
155 static rtx mmix_function_incoming_arg (cumulative_args_t, machine_mode,
156 const_tree, bool);
157 static rtx mmix_function_arg (cumulative_args_t, machine_mode,
158 const_tree, bool);
159 static rtx mmix_function_value (const_tree, const_tree, bool);
160 static rtx mmix_libcall_value (machine_mode, const_rtx);
161 static bool mmix_function_value_regno_p (const unsigned int);
162 static bool mmix_pass_by_reference (cumulative_args_t,
163 machine_mode, const_tree, bool);
164 static bool mmix_frame_pointer_required (void);
165 static void mmix_asm_trampoline_template (FILE *);
166 static void mmix_trampoline_init (rtx, tree, rtx);
167 static void mmix_print_operand (FILE *, rtx, int);
168 static void mmix_print_operand_address (FILE *, machine_mode, rtx);
169 static bool mmix_print_operand_punct_valid_p (unsigned char);
170 static void mmix_conditional_register_usage (void);
171 static HOST_WIDE_INT mmix_static_rtx_alignment (machine_mode);
172 static HOST_WIDE_INT mmix_constant_alignment (const_tree, HOST_WIDE_INT);
173 static HOST_WIDE_INT mmix_starting_frame_offset (void);
175 /* Target structure macros. Listed by node. See `Using and Porting GCC'
176 for a general description. */
178 /* Node: Function Entry */
180 #undef TARGET_ASM_BYTE_OP
181 #define TARGET_ASM_BYTE_OP NULL
182 #undef TARGET_ASM_ALIGNED_HI_OP
183 #define TARGET_ASM_ALIGNED_HI_OP NULL
184 #undef TARGET_ASM_ALIGNED_SI_OP
185 #define TARGET_ASM_ALIGNED_SI_OP NULL
186 #undef TARGET_ASM_ALIGNED_DI_OP
187 #define TARGET_ASM_ALIGNED_DI_OP NULL
188 #undef TARGET_ASM_INTEGER
189 #define TARGET_ASM_INTEGER mmix_assemble_integer
191 #undef TARGET_ASM_FUNCTION_PROLOGUE
192 #define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
194 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
195 #define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue
197 #undef TARGET_ASM_FUNCTION_EPILOGUE
198 #define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
200 #undef TARGET_PRINT_OPERAND
201 #define TARGET_PRINT_OPERAND mmix_print_operand
202 #undef TARGET_PRINT_OPERAND_ADDRESS
203 #define TARGET_PRINT_OPERAND_ADDRESS mmix_print_operand_address
204 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
205 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P mmix_print_operand_punct_valid_p
207 #undef TARGET_ENCODE_SECTION_INFO
208 #define TARGET_ENCODE_SECTION_INFO mmix_encode_section_info
209 #undef TARGET_STRIP_NAME_ENCODING
210 #define TARGET_STRIP_NAME_ENCODING mmix_strip_name_encoding
212 #undef TARGET_ASM_OUTPUT_MI_THUNK
213 #define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
214 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
215 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
216 #undef TARGET_ASM_FILE_START
217 #define TARGET_ASM_FILE_START mmix_file_start
218 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
219 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
220 #undef TARGET_ASM_FILE_END
221 #define TARGET_ASM_FILE_END mmix_file_end
222 #undef TARGET_ASM_OUTPUT_SOURCE_FILENAME
223 #define TARGET_ASM_OUTPUT_SOURCE_FILENAME mmix_asm_output_source_filename
225 #undef TARGET_CONDITIONAL_REGISTER_USAGE
226 #define TARGET_CONDITIONAL_REGISTER_USAGE mmix_conditional_register_usage
228 #undef TARGET_RTX_COSTS
229 #define TARGET_RTX_COSTS mmix_rtx_costs
230 #undef TARGET_ADDRESS_COST
231 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
233 #undef TARGET_REGISTER_MOVE_COST
234 #define TARGET_REGISTER_MOVE_COST mmix_register_move_cost
236 #undef TARGET_MACHINE_DEPENDENT_REORG
237 #define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg
239 #undef TARGET_PROMOTE_FUNCTION_MODE
240 #define TARGET_PROMOTE_FUNCTION_MODE mmix_promote_function_mode
242 #undef TARGET_FUNCTION_VALUE
243 #define TARGET_FUNCTION_VALUE mmix_function_value
244 #undef TARGET_LIBCALL_VALUE
245 #define TARGET_LIBCALL_VALUE mmix_libcall_value
246 #undef TARGET_FUNCTION_VALUE_REGNO_P
247 #define TARGET_FUNCTION_VALUE_REGNO_P mmix_function_value_regno_p
249 #undef TARGET_FUNCTION_ARG
250 #define TARGET_FUNCTION_ARG mmix_function_arg
251 #undef TARGET_FUNCTION_INCOMING_ARG
252 #define TARGET_FUNCTION_INCOMING_ARG mmix_function_incoming_arg
253 #undef TARGET_FUNCTION_ARG_ADVANCE
254 #define TARGET_FUNCTION_ARG_ADVANCE mmix_function_arg_advance
255 #undef TARGET_STRUCT_VALUE_RTX
256 #define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx
257 #undef TARGET_SETUP_INCOMING_VARARGS
258 #define TARGET_SETUP_INCOMING_VARARGS mmix_setup_incoming_varargs
259 #undef TARGET_PASS_BY_REFERENCE
260 #define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference
261 #undef TARGET_CALLEE_COPIES
262 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
264 #undef TARGET_PREFERRED_RELOAD_CLASS
265 #define TARGET_PREFERRED_RELOAD_CLASS mmix_preferred_reload_class
266 #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
267 #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mmix_preferred_output_reload_class
269 #undef TARGET_LRA_P
270 #define TARGET_LRA_P hook_bool_void_false
272 #undef TARGET_LEGITIMATE_ADDRESS_P
273 #define TARGET_LEGITIMATE_ADDRESS_P mmix_legitimate_address_p
274 #undef TARGET_LEGITIMATE_CONSTANT_P
275 #define TARGET_LEGITIMATE_CONSTANT_P mmix_legitimate_constant_p
277 #undef TARGET_FRAME_POINTER_REQUIRED
278 #define TARGET_FRAME_POINTER_REQUIRED mmix_frame_pointer_required
280 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
281 #define TARGET_ASM_TRAMPOLINE_TEMPLATE mmix_asm_trampoline_template
282 #undef TARGET_TRAMPOLINE_INIT
283 #define TARGET_TRAMPOLINE_INIT mmix_trampoline_init
285 #undef TARGET_OPTION_OVERRIDE
286 #define TARGET_OPTION_OVERRIDE mmix_option_override
288 #undef TARGET_STATIC_RTX_ALIGNMENT
289 #define TARGET_STATIC_RTX_ALIGNMENT mmix_static_rtx_alignment
290 #undef TARGET_CONSTANT_ALIGNMENT
291 #define TARGET_CONSTANT_ALIGNMENT mmix_constant_alignment
293 #undef TARGET_STARTING_FRAME_OFFSET
294 #define TARGET_STARTING_FRAME_OFFSET mmix_starting_frame_offset
296 struct gcc_target targetm = TARGET_INITIALIZER;
298 /* Functions that are expansions for target macros.
299 See Target Macros in `Using and Porting GCC'. */
301 /* TARGET_OPTION_OVERRIDE. */
303 static void
304 mmix_option_override (void)
306 /* Should we err or should we warn? Hmm. At least we must neutralize
307 it. For example the wrong kind of case-tables will be generated with
308 PIC; we use absolute address items for mmixal compatibility. FIXME:
309 They could be relative if we just elide them to after all pertinent
310 labels. */
311 if (flag_pic)
313 warning (0, "-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
314 flag_pic = 0;
318 /* INIT_EXPANDERS. */
320 void
321 mmix_init_expanders (void)
323 init_machine_status = mmix_init_machine_status;
326 /* Set the per-function data. */
328 static struct machine_function *
329 mmix_init_machine_status (void)
331 return ggc_cleared_alloc<machine_function> ();
334 /* DATA_ABI_ALIGNMENT.
335 We have trouble getting the address of stuff that is located at other
336 than 32-bit alignments (GETA requirements), so try to give everything
337 at least 32-bit alignment. */
340 mmix_data_alignment (tree type ATTRIBUTE_UNUSED, int basic_align)
342 if (basic_align < 32)
343 return 32;
345 return basic_align;
348 /* Implement TARGET_STATIC_RTX_ALIGNMENT. */
350 static HOST_WIDE_INT
351 mmix_static_rtx_alignment (machine_mode mode)
353 return MAX (GET_MODE_ALIGNMENT (mode), 32);
356 /* Implement tARGET_CONSTANT_ALIGNMENT. */
358 static HOST_WIDE_INT
359 mmix_constant_alignment (const_tree, HOST_WIDE_INT basic_align)
361 if (basic_align < 32)
362 return 32;
364 return basic_align;
367 /* LOCAL_ALIGNMENT. */
369 unsigned
370 mmix_local_alignment (tree type ATTRIBUTE_UNUSED, unsigned basic_align)
372 if (basic_align < 32)
373 return 32;
375 return basic_align;
378 /* TARGET_CONDITIONAL_REGISTER_USAGE. */
380 static void
381 mmix_conditional_register_usage (void)
383 int i;
385 if (TARGET_ABI_GNU)
387 static const int gnu_abi_reg_alloc_order[]
388 = MMIX_GNU_ABI_REG_ALLOC_ORDER;
390 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
391 reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];
393 /* Change the default from the mmixware ABI. For the GNU ABI,
394 $15..$30 are call-saved just as $0..$14. There must be one
395 call-clobbered local register for the "hole" that holds the
396 number of saved local registers saved by PUSHJ/PUSHGO during the
397 function call, receiving the return value at return. So best is
398 to use the highest, $31. It's already marked call-clobbered for
399 the mmixware ABI. */
400 for (i = 15; i <= 30; i++)
401 call_used_regs[i] = 0;
403 /* "Unfix" the parameter registers. */
404 for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
405 i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
406 i++)
407 fixed_regs[i] = 0;
410 /* Step over the ":" in special register names. */
411 if (! TARGET_TOPLEVEL_SYMBOLS)
412 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
413 if (reg_names[i][0] == ':')
414 reg_names[i]++;
417 /* INCOMING_REGNO and OUTGOING_REGNO worker function.
418 Those two macros must only be applied to function argument
419 registers and the function return value register for the opposite
420 use. FIXME: for their current use in gcc, it'd be better with an
421 explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P a'la
422 TARGET_FUNCTION_ARG / TARGET_FUNCTION_INCOMING_ARG instead of
423 forcing the target to commit to a fixed mapping and for any
424 unspecified register use. Particularly when thinking about the
425 return-value, it is better to imagine INCOMING_REGNO and
426 OUTGOING_REGNO as named CALLEE_TO_CALLER_REGNO and INNER_REGNO as
427 named CALLER_TO_CALLEE_REGNO because the direction. The "incoming"
428 and "outgoing" is from the perspective of the parameter-registers,
429 but the same macro is (must be, lacking an alternative like
430 suggested above) used to map the return-value-register from the
431 same perspective. To make directions even more confusing, the macro
432 MMIX_OUTGOING_RETURN_VALUE_REGNUM holds the number of the register
433 in which to return a value, i.e. INCOMING_REGNO for the return-value-
434 register as received from a called function; the return-value on the
435 way out. */
438 mmix_opposite_regno (int regno, int incoming)
440 if (incoming && regno == MMIX_OUTGOING_RETURN_VALUE_REGNUM)
441 return MMIX_RETURN_VALUE_REGNUM;
443 if (!incoming && regno == MMIX_RETURN_VALUE_REGNUM)
444 return MMIX_OUTGOING_RETURN_VALUE_REGNUM;
446 if (!mmix_function_arg_regno_p (regno, incoming))
447 return regno;
449 return
450 regno - (incoming
451 ? MMIX_FIRST_INCOMING_ARG_REGNUM - MMIX_FIRST_ARG_REGNUM
452 : MMIX_FIRST_ARG_REGNUM - MMIX_FIRST_INCOMING_ARG_REGNUM);
455 /* LOCAL_REGNO.
456 All registers that are part of the register stack and that will be
457 saved are local. */
460 mmix_local_regno (int regno)
462 return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && !call_used_regs[regno];
465 /* TARGET_PREFERRED_RELOAD_CLASS.
466 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */
468 static reg_class_t
469 mmix_preferred_reload_class (rtx x, reg_class_t rclass)
471 /* FIXME: Revisit. */
472 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
473 ? REMAINDER_REG : rclass;
476 /* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS.
477 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */
479 static reg_class_t
480 mmix_preferred_output_reload_class (rtx x, reg_class_t rclass)
482 /* FIXME: Revisit. */
483 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
484 ? REMAINDER_REG : rclass;
487 /* SECONDARY_RELOAD_CLASS.
488 We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere. */
490 enum reg_class
491 mmix_secondary_reload_class (enum reg_class rclass,
492 machine_mode mode ATTRIBUTE_UNUSED,
493 rtx x ATTRIBUTE_UNUSED,
494 int in_p ATTRIBUTE_UNUSED)
496 if (rclass == REMAINDER_REG
497 || rclass == HIMULT_REG
498 || rclass == SYSTEM_REGS)
499 return GENERAL_REGS;
501 return NO_REGS;
504 /* DYNAMIC_CHAIN_ADDRESS. */
507 mmix_dynamic_chain_address (rtx frame)
509 /* FIXME: the frame-pointer is stored at offset -8 from the current
510 frame-pointer. Unfortunately, the caller assumes that a
511 frame-pointer is present for *all* previous frames. There should be
512 a way to say that that cannot be done, like for RETURN_ADDR_RTX. */
513 return plus_constant (Pmode, frame, -8);
516 /* Implement TARGET_STARTING_FRAME_OFFSET. */
518 static HOST_WIDE_INT
519 mmix_starting_frame_offset (void)
521 /* The old frame pointer is in the slot below the new one, so
522 FIRST_PARM_OFFSET does not need to depend on whether the
523 frame-pointer is needed or not. We have to adjust for the register
524 stack pointer being located below the saved frame pointer.
525 Similarly, we store the return address on the stack too, for
526 exception handling, and always if we save the register stack pointer. */
527 return
529 + (MMIX_CFUN_HAS_LANDING_PAD
530 ? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0)));
533 /* RETURN_ADDR_RTX. */
536 mmix_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
538 return count == 0
539 ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS
540 /* FIXME: Set frame_alias_set on the following. (Why?)
541 See mmix_initial_elimination_offset for the reason we can't use
542 get_hard_reg_initial_val for both. Always using a stack slot
543 and not a register would be suboptimal. */
544 ? validize_mem (gen_rtx_MEM (Pmode,
545 plus_constant (Pmode,
546 frame_pointer_rtx, -16)))
547 : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
548 : NULL_RTX;
551 /* SETUP_FRAME_ADDRESSES. */
553 void
554 mmix_setup_frame_addresses (void)
556 /* Nothing needed at the moment. */
559 /* The difference between the (imaginary) frame pointer and the stack
560 pointer. Used to eliminate the frame pointer. */
563 mmix_initial_elimination_offset (int fromreg, int toreg)
565 int regno;
566 int fp_sp_offset
567 = (get_frame_size () + crtl->outgoing_args_size + 7) & ~7;
569 /* There is no actual offset between these two virtual values, but for
570 the frame-pointer, we have the old one in the stack position below
571 it, so the offset for the frame-pointer to the stack-pointer is one
572 octabyte larger. */
573 if (fromreg == MMIX_ARG_POINTER_REGNUM
574 && toreg == MMIX_FRAME_POINTER_REGNUM)
575 return 0;
577 /* The difference is the size of local variables plus the size of
578 outgoing function arguments that would normally be passed as
579 registers but must be passed on stack because we're out of
580 function-argument registers. Only global saved registers are
581 counted; the others go on the register stack.
583 The frame-pointer is counted too if it is what is eliminated, as we
584 need to balance the offset for it from TARGET_STARTING_FRAME_OFFSET.
586 Also add in the slot for the register stack pointer we save if we
587 have a landing pad.
589 Unfortunately, we can't access $0..$14, from unwinder code easily, so
590 store the return address in a frame slot too. FIXME: Only for
591 non-leaf functions. FIXME: Always with a landing pad, because it's
592 hard to know whether we need the other at the time we know we need
593 the offset for one (and have to state it). It's a kludge until we
594 can express the register stack in the EH frame info.
596 We have to do alignment here; get_frame_size will not return a
597 multiple of STACK_BOUNDARY. FIXME: Add note in manual. */
599 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
600 regno <= 255;
601 regno++)
602 if ((df_regs_ever_live_p (regno) && ! call_used_regs[regno])
603 || IS_MMIX_EH_RETURN_DATA_REG (regno))
604 fp_sp_offset += 8;
606 return fp_sp_offset
607 + (MMIX_CFUN_HAS_LANDING_PAD
608 ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0))
609 + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8);
612 static void
613 mmix_function_arg_advance (cumulative_args_t argsp_v, machine_mode mode,
614 const_tree type, bool named ATTRIBUTE_UNUSED)
616 CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
617 int arg_size = MMIX_FUNCTION_ARG_SIZE (mode, type);
619 argsp->regs = ((targetm.calls.must_pass_in_stack (mode, type)
620 || (arg_size > 8
621 && !TARGET_LIBFUNC
622 && !argsp->lib))
623 ? (MMIX_MAX_ARGS_IN_REGS) + 1
624 : argsp->regs + (7 + arg_size) / 8);
627 /* Helper function for mmix_function_arg and mmix_function_incoming_arg. */
629 static rtx
630 mmix_function_arg_1 (const cumulative_args_t argsp_v,
631 machine_mode mode,
632 const_tree type,
633 bool named ATTRIBUTE_UNUSED,
634 bool incoming)
636 CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
638 /* Last-argument marker. */
639 if (type == void_type_node)
640 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
641 ? gen_rtx_REG (mode,
642 (incoming
643 ? MMIX_FIRST_INCOMING_ARG_REGNUM
644 : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
645 : NULL_RTX;
647 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
648 && !targetm.calls.must_pass_in_stack (mode, type)
649 && (GET_MODE_BITSIZE (mode) <= 64
650 || argsp->lib
651 || TARGET_LIBFUNC))
652 ? gen_rtx_REG (mode,
653 (incoming
654 ? MMIX_FIRST_INCOMING_ARG_REGNUM
655 : MMIX_FIRST_ARG_REGNUM)
656 + argsp->regs)
657 : NULL_RTX;
660 /* Return an rtx for a function argument to go in a register, and 0 for
661 one that must go on stack. */
663 static rtx
664 mmix_function_arg (cumulative_args_t argsp,
665 machine_mode mode,
666 const_tree type,
667 bool named)
669 return mmix_function_arg_1 (argsp, mode, type, named, false);
672 static rtx
673 mmix_function_incoming_arg (cumulative_args_t argsp,
674 machine_mode mode,
675 const_tree type,
676 bool named)
678 return mmix_function_arg_1 (argsp, mode, type, named, true);
681 /* Returns nonzero for everything that goes by reference, 0 for
682 everything that goes by value. */
684 static bool
685 mmix_pass_by_reference (cumulative_args_t argsp_v, machine_mode mode,
686 const_tree type, bool named ATTRIBUTE_UNUSED)
688 CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
690 /* FIXME: Check: I'm not sure the must_pass_in_stack check is
691 necessary. */
692 if (targetm.calls.must_pass_in_stack (mode, type))
693 return true;
695 if (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
696 && !TARGET_LIBFUNC
697 && (!argsp || !argsp->lib))
698 return true;
700 return false;
703 /* Return nonzero if regno is a register number where a parameter is
704 passed, and 0 otherwise. */
707 mmix_function_arg_regno_p (int regno, int incoming)
709 int first_arg_regnum
710 = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM;
712 return regno >= first_arg_regnum
713 && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS;
716 /* Implements TARGET_FUNCTION_VALUE. */
718 static rtx
719 mmix_function_value (const_tree valtype,
720 const_tree func ATTRIBUTE_UNUSED,
721 bool outgoing)
723 machine_mode mode = TYPE_MODE (valtype);
724 machine_mode cmode;
725 int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
726 rtx vec[MMIX_MAX_REGS_FOR_VALUE];
727 int i;
728 int nregs;
730 if (!outgoing)
731 return gen_rtx_REG (mode, MMIX_RETURN_VALUE_REGNUM);
733 /* Return values that fit in a register need no special handling.
734 There's no register hole when parameters are passed in global
735 registers. */
736 if (TARGET_ABI_GNU
737 || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
738 return
739 gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
741 if (COMPLEX_MODE_P (mode))
742 /* A complex type, made up of components. */
743 cmode = TYPE_MODE (TREE_TYPE (valtype));
744 else
746 /* Of the other larger-than-register modes, we only support
747 scalar mode TImode. (At least, that's the only one that's
748 been rudimentally tested.) Make sure we're alerted for
749 unexpected cases. */
750 if (mode != TImode)
751 sorry ("support for mode %qs", GET_MODE_NAME (mode));
753 /* In any case, we will fill registers to the natural size. */
754 cmode = DImode;
757 nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
759 /* We need to take care of the effect of the register hole on return
760 values of large sizes; the last register will appear as the first
761 register, with the rest shifted. (For complex modes, this is just
762 swapped registers.) */
764 if (nregs > MMIX_MAX_REGS_FOR_VALUE)
765 internal_error ("too large function value type, needs %d registers,\
766 have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE);
768 /* FIXME: Maybe we should handle structure values like this too
769 (adjusted for BLKmode), perhaps for both ABI:s. */
770 for (i = 0; i < nregs - 1; i++)
771 vec[i]
772 = gen_rtx_EXPR_LIST (VOIDmode,
773 gen_rtx_REG (cmode, first_val_regnum + i),
774 GEN_INT ((i + 1) * BITS_PER_UNIT));
776 vec[nregs - 1]
777 = gen_rtx_EXPR_LIST (VOIDmode,
778 gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
779 const0_rtx);
781 return gen_rtx_PARALLEL (mode, gen_rtvec_v (nregs, vec));
784 /* Implements TARGET_LIBCALL_VALUE. */
786 static rtx
787 mmix_libcall_value (machine_mode mode,
788 const_rtx fun ATTRIBUTE_UNUSED)
790 return gen_rtx_REG (mode, MMIX_RETURN_VALUE_REGNUM);
793 /* Implements TARGET_FUNCTION_VALUE_REGNO_P. */
795 static bool
796 mmix_function_value_regno_p (const unsigned int regno)
798 return regno == MMIX_RETURN_VALUE_REGNUM;
801 /* EH_RETURN_DATA_REGNO. */
804 mmix_eh_return_data_regno (int n)
806 if (n >= 0 && n < 4)
807 return MMIX_EH_RETURN_DATA_REGNO_START + n;
809 return INVALID_REGNUM;
812 /* EH_RETURN_STACKADJ_RTX. */
815 mmix_eh_return_stackadj_rtx (void)
817 return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM);
820 /* EH_RETURN_HANDLER_RTX. */
823 mmix_eh_return_handler_rtx (void)
825 return gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
828 /* ASM_PREFERRED_EH_DATA_FORMAT. */
831 mmix_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED,
832 int global ATTRIBUTE_UNUSED)
834 /* This is the default (was at 2001-07-20). Revisit when needed. */
835 return DW_EH_PE_absptr;
838 /* Make a note that we've seen the beginning of the prologue. This
839 matters to whether we'll translate register numbers as calculated by
840 mmix_reorg. */
842 static void
843 mmix_target_asm_function_prologue (FILE *)
845 cfun->machine->in_prologue = 1;
848 /* Make a note that we've seen the end of the prologue. */
850 static void
851 mmix_target_asm_function_end_prologue (FILE *stream ATTRIBUTE_UNUSED)
853 cfun->machine->in_prologue = 0;
856 /* Implement TARGET_MACHINE_DEPENDENT_REORG. No actual rearrangements
857 done here; just virtually by calculating the highest saved stack
858 register number used to modify the register numbers at output time. */
860 static void
861 mmix_reorg (void)
863 int regno;
865 /* We put the number of the highest saved register-file register in a
866 location convenient for the call-patterns to output. Note that we
867 don't tell dwarf2 about these registers, since it can't restore them
868 anyway. */
869 for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
870 regno >= 0;
871 regno--)
872 if ((df_regs_ever_live_p (regno) && !call_used_regs[regno])
873 || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
874 break;
876 /* Regardless of whether they're saved (they might be just read), we
877 mustn't include registers that carry parameters. We could scan the
878 insns to see whether they're actually used (and indeed do other less
879 trivial register usage analysis and transformations), but it seems
880 wasteful to optimize for unused parameter registers. As of
881 2002-04-30, df_regs_ever_live_p (n) seems to be set for only-reads too, but
882 that might change. */
883 if (!TARGET_ABI_GNU && regno < crtl->args.info.regs - 1)
885 regno = crtl->args.info.regs - 1;
887 /* We don't want to let this cause us to go over the limit and make
888 incoming parameter registers be misnumbered and treating the last
889 parameter register and incoming return value register call-saved.
890 Stop things at the unmodified scheme. */
891 if (regno > MMIX_RETURN_VALUE_REGNUM - 1)
892 regno = MMIX_RETURN_VALUE_REGNUM - 1;
895 cfun->machine->highest_saved_stack_register = regno;
898 /* TARGET_ASM_FUNCTION_EPILOGUE. */
900 static void
901 mmix_target_asm_function_epilogue (FILE *stream)
903 /* Emit an \n for readability of the generated assembly. */
904 fputc ('\n', stream);
907 /* TARGET_ASM_OUTPUT_MI_THUNK. */
909 static void
910 mmix_asm_output_mi_thunk (FILE *stream,
911 tree fndecl ATTRIBUTE_UNUSED,
912 HOST_WIDE_INT delta,
913 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
914 tree func)
916 /* If you define TARGET_STRUCT_VALUE_RTX that returns 0 (i.e. pass
917 location of structure to return as invisible first argument), you
918 need to tweak this code too. */
919 const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
921 if (delta >= 0 && delta < 65536)
922 fprintf (stream, "\tINCL %s,%d\n", regname, (int)delta);
923 else if (delta < 0 && delta >= -255)
924 fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, (int)-delta);
925 else
927 mmix_output_register_setting (stream, 255, delta, 1);
928 fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname);
931 fprintf (stream, "\tJMP ");
932 assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
933 fprintf (stream, "\n");
936 /* FUNCTION_PROFILER. */
938 void
939 mmix_function_profiler (FILE *stream ATTRIBUTE_UNUSED,
940 int labelno ATTRIBUTE_UNUSED)
942 sorry ("function_profiler support for MMIX");
945 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. For the moment,
946 let's stick to pushing argument registers on the stack. Later, we
947 can parse all arguments in registers, to improve performance. */
949 static void
950 mmix_setup_incoming_varargs (cumulative_args_t args_so_farp_v,
951 machine_mode mode,
952 tree vartype,
953 int *pretend_sizep,
954 int second_time ATTRIBUTE_UNUSED)
956 CUMULATIVE_ARGS *args_so_farp = get_cumulative_args (args_so_farp_v);
958 /* The last named variable has been handled, but
959 args_so_farp has not been advanced for it. */
960 if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS)
961 *pretend_sizep = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8;
963 /* We assume that one argument takes up one register here. That should
964 be true until we start messing with multi-reg parameters. */
965 if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1)
966 internal_error ("MMIX Internal: Last named vararg would not fit in a register");
969 /* TARGET_ASM_TRAMPOLINE_TEMPLATE. */
971 static void
972 mmix_asm_trampoline_template (FILE *stream)
974 /* Read a value into the static-chain register and jump somewhere. The
975 static chain is stored at offset 16, and the function address is
976 stored at offset 24. */
978 fprintf (stream, "\tGETA $255,1F\n\t");
979 fprintf (stream, "LDOU %s,$255,0\n\t", reg_names[MMIX_STATIC_CHAIN_REGNUM]);
980 fprintf (stream, "LDOU $255,$255,8\n\t");
981 fprintf (stream, "GO $255,$255,0\n");
982 fprintf (stream, "1H\tOCTA 0\n\t");
983 fprintf (stream, "OCTA 0\n");
986 /* TARGET_TRAMPOLINE_INIT. */
987 /* Set the static chain and function pointer field in the trampoline.
988 We also SYNCID here to be sure (doesn't matter in the simulator, but
989 some day it will). */
991 static void
992 mmix_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
994 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
995 rtx mem;
997 emit_block_move (m_tramp, assemble_trampoline_template (),
998 GEN_INT (2*UNITS_PER_WORD), BLOCK_OP_NORMAL);
1000 mem = adjust_address (m_tramp, DImode, 2*UNITS_PER_WORD);
1001 emit_move_insn (mem, static_chain);
1002 mem = adjust_address (m_tramp, DImode, 3*UNITS_PER_WORD);
1003 emit_move_insn (mem, fnaddr);
1005 mem = adjust_address (m_tramp, DImode, 0);
1006 emit_insn (gen_sync_icache (mem, GEN_INT (TRAMPOLINE_SIZE - 1)));
1009 /* We must exclude constant addresses that have an increment that is not a
1010 multiple of four bytes because of restrictions of the GETA
1011 instruction, unless TARGET_BASE_ADDRESSES. */
1014 mmix_constant_address_p (rtx x)
1016 RTX_CODE code = GET_CODE (x);
1017 int addend = 0;
1018 /* When using "base addresses", anything constant goes. */
1019 int constant_ok = TARGET_BASE_ADDRESSES != 0;
1021 switch (code)
1023 case LABEL_REF:
1024 case SYMBOL_REF:
1025 return 1;
1027 case HIGH:
1028 /* FIXME: Don't know how to dissect these. Avoid them for now,
1029 except we know they're constants. */
1030 return constant_ok;
1032 case CONST_INT:
1033 addend = INTVAL (x);
1034 break;
1036 case CONST_DOUBLE:
1037 if (GET_MODE (x) != VOIDmode)
1038 /* Strange that we got here. FIXME: Check if we do. */
1039 return constant_ok;
1040 addend = CONST_DOUBLE_LOW (x);
1041 break;
1043 case CONST:
1044 /* Note that expressions with arithmetic on forward references don't
1045 work in mmixal. People using gcc assembly code with mmixal might
1046 need to move arrays and such to before the point of use. */
1047 if (GET_CODE (XEXP (x, 0)) == PLUS)
1049 rtx x0 = XEXP (XEXP (x, 0), 0);
1050 rtx x1 = XEXP (XEXP (x, 0), 1);
1052 if ((GET_CODE (x0) == SYMBOL_REF
1053 || GET_CODE (x0) == LABEL_REF)
1054 && (GET_CODE (x1) == CONST_INT
1055 || (GET_CODE (x1) == CONST_DOUBLE
1056 && GET_MODE (x1) == VOIDmode)))
1057 addend = mmix_intval (x1);
1058 else
1059 return constant_ok;
1061 else
1062 return constant_ok;
1063 break;
1065 default:
1066 return 0;
1069 return constant_ok || (addend & 3) == 0;
1072 /* Return 1 if the address is OK, otherwise 0. */
1074 bool
1075 mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1076 rtx x,
1077 bool strict_checking)
1079 #define MMIX_REG_OK(X) \
1080 ((strict_checking \
1081 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
1082 || (reg_renumber[REGNO (X)] > 0 \
1083 && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER))) \
1084 || (!strict_checking \
1085 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
1086 || REGNO (X) >= FIRST_PSEUDO_REGISTER \
1087 || REGNO (X) == ARG_POINTER_REGNUM)))
1089 /* We only accept:
1090 (mem reg)
1091 (mem (plus reg reg))
1092 (mem (plus reg 0..255)).
1093 unless TARGET_BASE_ADDRESSES, in which case we accept all
1094 (mem constant_address) too. */
1097 /* (mem reg) */
1098 if (REG_P (x) && MMIX_REG_OK (x))
1099 return 1;
1101 if (GET_CODE(x) == PLUS)
1103 rtx x1 = XEXP (x, 0);
1104 rtx x2 = XEXP (x, 1);
1106 /* Try swapping the order. FIXME: Do we need this? */
1107 if (! REG_P (x1))
1109 rtx tem = x1;
1110 x1 = x2;
1111 x2 = tem;
1114 /* (mem (plus (reg?) (?))) */
1115 if (!REG_P (x1) || !MMIX_REG_OK (x1))
1116 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1118 /* (mem (plus (reg) (reg?))) */
1119 if (REG_P (x2) && MMIX_REG_OK (x2))
1120 return 1;
1122 /* (mem (plus (reg) (0..255?))) */
1123 if (satisfies_constraint_I (x2))
1124 return 1;
1126 return 0;
1129 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1132 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1134 static bool
1135 mmix_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1137 RTX_CODE code = GET_CODE (x);
1139 /* We must allow any number due to the way the cse passes works; if we
1140 do not allow any number here, general_operand will fail, and insns
1141 will fatally fail recognition instead of "softly". */
1142 if (code == CONST_INT || code == CONST_DOUBLE)
1143 return 1;
1145 return CONSTANT_ADDRESS_P (x);
1148 /* SELECT_CC_MODE. */
1150 machine_mode
1151 mmix_select_cc_mode (RTX_CODE op, rtx x, rtx y ATTRIBUTE_UNUSED)
1153 /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to
1154 output different compare insns. Note that we do not check the
1155 validity of the comparison here. */
1157 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
1159 if (op == ORDERED || op == UNORDERED || op == UNGE
1160 || op == UNGT || op == UNLE || op == UNLT)
1161 return CC_FUNmode;
1163 if (op == EQ || op == NE)
1164 return CC_FPEQmode;
1166 return CC_FPmode;
1169 if (op == GTU || op == LTU || op == GEU || op == LEU)
1170 return CC_UNSmode;
1172 return CCmode;
1175 /* REVERSIBLE_CC_MODE. */
1178 mmix_reversible_cc_mode (machine_mode mode)
1180 /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float
1181 compares. */
1182 return mode != CC_FPmode;
1185 /* TARGET_RTX_COSTS. */
1187 static bool
1188 mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1189 machine_mode mode ATTRIBUTE_UNUSED,
1190 int outer_code ATTRIBUTE_UNUSED,
1191 int opno ATTRIBUTE_UNUSED,
1192 int *total ATTRIBUTE_UNUSED,
1193 bool speed ATTRIBUTE_UNUSED)
1195 /* For the time being, this is just a stub and we'll accept the
1196 generic calculations, until we can do measurements, at least.
1197 Say we did not modify any calculated costs. */
1198 return false;
1201 /* TARGET_REGISTER_MOVE_COST.
1203 The special registers can only move to and from general regs, and we
1204 need to check that their constraints match, so say 3 for them. */
1206 static int
1207 mmix_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
1208 reg_class_t from,
1209 reg_class_t to)
1211 return (from == GENERAL_REGS && from == to) ? 2 : 3;
1214 /* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a
1215 compile-time constant; it's used in an asm in crtstuff.c, compiled for
1216 the target. */
1218 /* DATA_SECTION_ASM_OP. */
1220 const char *
1221 mmix_data_section_asm_op (void)
1223 return "\t.data ! mmixal:= 8H LOC 9B";
1226 static void
1227 mmix_encode_section_info (tree decl, rtx rtl, int first)
1229 /* Test for an external declaration, and do nothing if it is one. */
1230 if ((TREE_CODE (decl) == VAR_DECL
1231 && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))
1232 || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))
1234 else if (first && DECL_P (decl))
1236 /* For non-visible declarations, add a "@" prefix, which we skip
1237 when the label is output. If the label does not have this
1238 prefix, a ":" is output if -mtoplevel-symbols.
1240 Note that this does not work for data that is declared extern and
1241 later defined as static. If there's code in between, that code
1242 will refer to the extern declaration, and vice versa. This just
1243 means that when -mtoplevel-symbols is in use, we can just handle
1244 well-behaved ISO-compliant code. */
1246 const char *str = XSTR (XEXP (rtl, 0), 0);
1247 int len = strlen (str);
1248 char *newstr = XALLOCAVEC (char, len + 2);
1249 newstr[0] = '@';
1250 strcpy (newstr + 1, str);
1251 XSTR (XEXP (rtl, 0), 0) = ggc_alloc_string (newstr, len + 1);
1254 /* Set SYMBOL_REF_FLAG for things that we want to access with GETA. We
1255 may need different options to reach for different things with GETA.
1256 For now, functions and things we know or have been told are constant. */
1257 if (TREE_CODE (decl) == FUNCTION_DECL
1258 || TREE_CONSTANT (decl)
1259 || (TREE_CODE (decl) == VAR_DECL
1260 && TREE_READONLY (decl)
1261 && !TREE_SIDE_EFFECTS (decl)
1262 && (!DECL_INITIAL (decl)
1263 || TREE_CONSTANT (DECL_INITIAL (decl)))))
1264 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
1267 static const char *
1268 mmix_strip_name_encoding (const char *name)
1270 for (; (*name == '@' || *name == '*'); name++)
1273 return name;
1276 /* TARGET_ASM_FILE_START.
1277 We just emit a little comment for the time being. */
1279 static void
1280 mmix_file_start (void)
1282 default_file_start ();
1284 fputs ("! mmixal:= 8H LOC Data_Section\n", asm_out_file);
1286 /* Make sure each file starts with the text section. */
1287 switch_to_section (text_section);
1290 /* TARGET_ASM_FILE_END. */
1292 static void
1293 mmix_file_end (void)
1295 /* Make sure each file ends with the data section. */
1296 switch_to_section (data_section);
1299 /* TARGET_ASM_OUTPUT_SOURCE_FILENAME. */
1301 static void
1302 mmix_asm_output_source_filename (FILE *stream, const char *name)
1304 fprintf (stream, "# 1 ");
1305 OUTPUT_QUOTED_STRING (stream, name);
1306 fprintf (stream, "\n");
1309 /* OUTPUT_QUOTED_STRING. */
1311 void
1312 mmix_output_quoted_string (FILE *stream, const char *string, int length)
1314 const char * string_end = string + length;
1315 static const char *const unwanted_chars = "\"[]\\";
1317 /* Output "any character except newline and double quote character". We
1318 play it safe and avoid all control characters too. We also do not
1319 want [] as characters, should input be passed through m4 with [] as
1320 quotes. Further, we avoid "\", because the GAS port handles it as a
1321 quoting character. */
1322 while (string < string_end)
1324 if (*string
1325 && (unsigned char) *string < 128
1326 && !ISCNTRL (*string)
1327 && strchr (unwanted_chars, *string) == NULL)
1329 fputc ('"', stream);
1330 while (*string
1331 && (unsigned char) *string < 128
1332 && !ISCNTRL (*string)
1333 && strchr (unwanted_chars, *string) == NULL
1334 && string < string_end)
1336 fputc (*string, stream);
1337 string++;
1339 fputc ('"', stream);
1340 if (string < string_end)
1341 fprintf (stream, ",");
1343 if (string < string_end)
1345 fprintf (stream, "#%x", *string & 255);
1346 string++;
1347 if (string < string_end)
1348 fprintf (stream, ",");
1353 /* Target hook for assembling integer objects. Use mmix_print_operand
1354 for WYDE and TETRA. Use mmix_output_octa to output 8-byte
1355 CONST_DOUBLEs. */
1357 static bool
1358 mmix_assemble_integer (rtx x, unsigned int size, int aligned_p)
1360 if (aligned_p)
1361 switch (size)
1363 /* We handle a limited number of types of operands in here. But
1364 that's ok, because we can punt to generic functions. We then
1365 pretend that aligned data isn't needed, so the usual .<pseudo>
1366 syntax is used (which works for aligned data too). We actually
1367 *must* do that, since we say we don't have simple aligned
1368 pseudos, causing this function to be called. We just try and
1369 keep as much compatibility as possible with mmixal syntax for
1370 normal cases (i.e. without GNU extensions and C only). */
1371 case 1:
1372 if (GET_CODE (x) != CONST_INT)
1374 aligned_p = 0;
1375 break;
1377 fputs ("\tBYTE\t", asm_out_file);
1378 mmix_print_operand (asm_out_file, x, 'B');
1379 fputc ('\n', asm_out_file);
1380 return true;
1382 case 2:
1383 if (GET_CODE (x) != CONST_INT)
1385 aligned_p = 0;
1386 break;
1388 fputs ("\tWYDE\t", asm_out_file);
1389 mmix_print_operand (asm_out_file, x, 'W');
1390 fputc ('\n', asm_out_file);
1391 return true;
1393 case 4:
1394 if (GET_CODE (x) != CONST_INT)
1396 aligned_p = 0;
1397 break;
1399 fputs ("\tTETRA\t", asm_out_file);
1400 mmix_print_operand (asm_out_file, x, 'L');
1401 fputc ('\n', asm_out_file);
1402 return true;
1404 case 8:
1405 /* We don't get here anymore for CONST_DOUBLE, because DImode
1406 isn't expressed as CONST_DOUBLE, and DFmode is handled
1407 elsewhere. */
1408 gcc_assert (GET_CODE (x) != CONST_DOUBLE);
1409 assemble_integer_with_op ("\tOCTA\t", x);
1410 return true;
1412 return default_assemble_integer (x, size, aligned_p);
1415 /* ASM_OUTPUT_ASCII. */
1417 void
1418 mmix_asm_output_ascii (FILE *stream, const char *string, int length)
1420 while (length > 0)
1422 int chunk_size = length > 60 ? 60 : length;
1423 fprintf (stream, "\tBYTE ");
1424 mmix_output_quoted_string (stream, string, chunk_size);
1425 string += chunk_size;
1426 length -= chunk_size;
1427 fprintf (stream, "\n");
1431 /* ASM_OUTPUT_ALIGNED_COMMON. */
1433 void
1434 mmix_asm_output_aligned_common (FILE *stream,
1435 const char *name,
1436 int size,
1437 int align)
1439 /* This is mostly the elfos.h one. There doesn't seem to be a way to
1440 express this in a mmixal-compatible way. */
1441 fprintf (stream, "\t.comm\t");
1442 assemble_name (stream, name);
1443 fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",
1444 size, align / BITS_PER_UNIT);
1447 /* ASM_OUTPUT_ALIGNED_LOCAL. */
1449 void
1450 mmix_asm_output_aligned_local (FILE *stream,
1451 const char *name,
1452 int size,
1453 int align)
1455 switch_to_section (data_section);
1457 ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
1458 assemble_name (stream, name);
1459 fprintf (stream, "\tLOC @+%d\n", size);
1462 /* ASM_OUTPUT_LABEL. */
1464 void
1465 mmix_asm_output_label (FILE *stream, const char *name)
1467 assemble_name (stream, name);
1468 fprintf (stream, "\tIS @\n");
1471 /* ASM_OUTPUT_INTERNAL_LABEL. */
1473 void
1474 mmix_asm_output_internal_label (FILE *stream, const char *name)
1476 assemble_name_raw (stream, name);
1477 fprintf (stream, "\tIS @\n");
1480 /* ASM_DECLARE_REGISTER_GLOBAL. */
1482 void
1483 mmix_asm_declare_register_global (FILE *stream ATTRIBUTE_UNUSED,
1484 tree decl ATTRIBUTE_UNUSED,
1485 int regno ATTRIBUTE_UNUSED,
1486 const char *name ATTRIBUTE_UNUSED)
1488 /* Nothing to do here, but there *will* be, therefore the framework is
1489 here. */
1492 /* ASM_WEAKEN_LABEL. */
1494 void
1495 mmix_asm_weaken_label (FILE *stream ATTRIBUTE_UNUSED,
1496 const char *name ATTRIBUTE_UNUSED)
1498 fprintf (stream, "\t.weak ");
1499 assemble_name (stream, name);
1500 fprintf (stream, " ! mmixal-incompatible\n");
1503 /* MAKE_DECL_ONE_ONLY. */
1505 void
1506 mmix_make_decl_one_only (tree decl)
1508 DECL_WEAK (decl) = 1;
1511 /* ASM_OUTPUT_LABELREF.
1512 Strip GCC's '*' and our own '@'. No order is assumed. */
1514 void
1515 mmix_asm_output_labelref (FILE *stream, const char *name)
1517 int is_extern = 1;
1519 for (; (*name == '@' || *name == '*'); name++)
1520 if (*name == '@')
1521 is_extern = 0;
1523 asm_fprintf (stream, "%s%U%s",
1524 is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
1525 name);
1528 /* ASM_OUTPUT_DEF. */
1530 void
1531 mmix_asm_output_def (FILE *stream, const char *name, const char *value)
1533 assemble_name (stream, name);
1534 fprintf (stream, "\tIS ");
1535 assemble_name (stream, value);
1536 fputc ('\n', stream);
1539 /* TARGET_PRINT_OPERAND. */
1541 static void
1542 mmix_print_operand (FILE *stream, rtx x, int code)
1544 /* When we add support for different codes later, we can, when needed,
1545 drop through to the main handler with a modified operand. */
1546 rtx modified_x = x;
1547 int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
1549 switch (code)
1551 /* Unrelated codes are in alphabetic order. */
1553 case '+':
1554 /* For conditional branches, output "P" for a probable branch. */
1555 if (TARGET_BRANCH_PREDICT)
1557 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
1558 if (x && profile_probability::from_reg_br_prob_note (XINT (x, 0))
1559 > profile_probability::even ())
1560 putc ('P', stream);
1562 return;
1564 case '.':
1565 /* For the %d in POP %d,0. */
1566 fprintf (stream, "%d", MMIX_POP_ARGUMENT ());
1567 return;
1569 case 'B':
1570 if (GET_CODE (x) != CONST_INT)
1571 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1572 fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
1573 return;
1575 case 'H':
1576 /* Highpart. Must be general register, and not the last one, as
1577 that one cannot be part of a consecutive register pair. */
1578 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1579 internal_error ("MMIX Internal: Bad register: %d", regno);
1581 /* This is big-endian, so the high-part is the first one. */
1582 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1583 return;
1585 case 'L':
1586 /* Lowpart. Must be CONST_INT or general register, and not the last
1587 one, as that one cannot be part of a consecutive register pair. */
1588 if (GET_CODE (x) == CONST_INT)
1590 fprintf (stream, "#%lx",
1591 (unsigned long) (INTVAL (x)
1592 & ((unsigned int) 0x7fffffff * 2 + 1)));
1593 return;
1596 if (GET_CODE (x) == SYMBOL_REF)
1598 output_addr_const (stream, x);
1599 return;
1602 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1603 internal_error ("MMIX Internal: Bad register: %d", regno);
1605 /* This is big-endian, so the low-part is + 1. */
1606 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
1607 return;
1609 /* Can't use 'a' because that's a generic modifier for address
1610 output. */
1611 case 'A':
1612 mmix_output_shiftvalue_op_from_str (stream, "ANDN",
1613 ~(uint64_t)
1614 mmix_intval (x));
1615 return;
1617 case 'i':
1618 mmix_output_shiftvalue_op_from_str (stream, "INC",
1619 (uint64_t)
1620 mmix_intval (x));
1621 return;
1623 case 'o':
1624 mmix_output_shiftvalue_op_from_str (stream, "OR",
1625 (uint64_t)
1626 mmix_intval (x));
1627 return;
1629 case 's':
1630 mmix_output_shiftvalue_op_from_str (stream, "SET",
1631 (uint64_t)
1632 mmix_intval (x));
1633 return;
1635 case 'd':
1636 case 'D':
1637 mmix_output_condition (stream, x, (code == 'D'));
1638 return;
1640 case 'e':
1641 /* Output an extra "e" to make fcmpe, fune. */
1642 if (TARGET_FCMP_EPSILON)
1643 fprintf (stream, "e");
1644 return;
1646 case 'm':
1647 /* Output the number minus 1. */
1648 if (GET_CODE (x) != CONST_INT)
1650 fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
1653 fprintf (stream, "%" PRId64,
1654 (int64_t) (mmix_intval (x) - 1));
1655 return;
1657 case 'p':
1658 /* Store the number of registers we want to save. This was setup
1659 by the prologue. The actual operand contains the number of
1660 registers to pass, but we don't use it currently. Anyway, we
1661 need to output the number of saved registers here. */
1662 fprintf (stream, "%d",
1663 cfun->machine->highest_saved_stack_register + 1);
1664 return;
1666 case 'r':
1667 /* Store the register to output a constant to. */
1668 if (! REG_P (x))
1669 fatal_insn ("MMIX Internal: Expected a register, not this", x);
1670 mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
1671 return;
1673 case 'I':
1674 /* Output the constant. Note that we use this for floats as well. */
1675 if (GET_CODE (x) != CONST_INT
1676 && (GET_CODE (x) != CONST_DOUBLE
1677 || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
1678 && GET_MODE (x) != SFmode)))
1679 fatal_insn ("MMIX Internal: Expected a constant, not this", x);
1680 mmix_output_register_setting (stream,
1681 mmix_output_destination_register,
1682 mmix_intval (x), 0);
1683 return;
1685 case 'U':
1686 /* An U for unsigned, if TARGET_ZERO_EXTEND. Ignore the operand. */
1687 if (TARGET_ZERO_EXTEND)
1688 putc ('U', stream);
1689 return;
1691 case 'v':
1692 mmix_output_shifted_value (stream, (int64_t) mmix_intval (x));
1693 return;
1695 case 'V':
1696 mmix_output_shifted_value (stream, (int64_t) ~mmix_intval (x));
1697 return;
1699 case 'W':
1700 if (GET_CODE (x) != CONST_INT)
1701 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1702 fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
1703 return;
1705 case 0:
1706 /* Nothing to do. */
1707 break;
1709 default:
1710 /* Presumably there's a missing case above if we get here. */
1711 internal_error ("MMIX Internal: Missing %qc case in mmix_print_operand", code);
1714 switch (GET_CODE (modified_x))
1716 case REG:
1717 regno = REGNO (modified_x);
1718 if (regno >= FIRST_PSEUDO_REGISTER)
1719 internal_error ("MMIX Internal: Bad register: %d", regno);
1720 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1721 return;
1723 case MEM:
1724 output_address (GET_MODE (modified_x), XEXP (modified_x, 0));
1725 return;
1727 case CONST_INT:
1728 /* For -2147483648, mmixal complains that the constant does not fit
1729 in 4 bytes, so let's output it as hex. Take care to handle hosts
1730 where HOST_WIDE_INT is longer than an int.
1732 Print small constants +-255 using decimal. */
1734 if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
1735 fprintf (stream, "%d", (int) (INTVAL (modified_x)));
1736 else
1737 fprintf (stream, "#%x",
1738 (int) (INTVAL (modified_x)) & (unsigned int) ~0);
1739 return;
1741 case CONST_DOUBLE:
1742 /* Do somewhat as CONST_INT. */
1743 mmix_output_octa (stream, mmix_intval (modified_x), 0);
1744 return;
1746 case CONST:
1747 output_addr_const (stream, modified_x);
1748 return;
1750 default:
1751 /* No need to test for all strange things. Let output_addr_const do
1752 it for us. */
1753 if (CONSTANT_P (modified_x)
1754 /* Strangely enough, this is not included in CONSTANT_P.
1755 FIXME: Ask/check about sanity here. */
1756 || LABEL_P (modified_x))
1758 output_addr_const (stream, modified_x);
1759 return;
1762 /* We need the original here. */
1763 fatal_insn ("MMIX Internal: Cannot decode this operand", x);
1767 /* TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
1769 static bool
1770 mmix_print_operand_punct_valid_p (unsigned char code)
1772 /* A '+' is used for branch prediction, similar to other ports. */
1773 return code == '+'
1774 /* A '.' is used for the %d in the POP %d,0 return insn. */
1775 || code == '.';
1778 /* TARGET_PRINT_OPERAND_ADDRESS. */
1780 static void
1781 mmix_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
1783 if (REG_P (x))
1785 /* I find the generated assembly code harder to read without
1786 the ",0". */
1787 fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
1788 return;
1790 else if (GET_CODE (x) == PLUS)
1792 rtx x1 = XEXP (x, 0);
1793 rtx x2 = XEXP (x, 1);
1795 if (REG_P (x1))
1797 fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
1799 if (REG_P (x2))
1801 fprintf (stream, "%s",
1802 reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
1803 return;
1805 else if (satisfies_constraint_I (x2))
1807 output_addr_const (stream, x2);
1808 return;
1813 if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (Pmode, x))
1815 output_addr_const (stream, x);
1816 return;
1819 fatal_insn ("MMIX Internal: This is not a recognized address", x);
1822 /* ASM_OUTPUT_REG_PUSH. */
1824 void
1825 mmix_asm_output_reg_push (FILE *stream, int regno)
1827 fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
1828 reg_names[MMIX_STACK_POINTER_REGNUM],
1829 reg_names[MMIX_STACK_POINTER_REGNUM],
1830 reg_names[MMIX_OUTPUT_REGNO (regno)],
1831 reg_names[MMIX_STACK_POINTER_REGNUM]);
1834 /* ASM_OUTPUT_REG_POP. */
1836 void
1837 mmix_asm_output_reg_pop (FILE *stream, int regno)
1839 fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
1840 reg_names[MMIX_OUTPUT_REGNO (regno)],
1841 reg_names[MMIX_STACK_POINTER_REGNUM],
1842 reg_names[MMIX_STACK_POINTER_REGNUM]);
1845 /* ASM_OUTPUT_ADDR_DIFF_ELT. */
1847 void
1848 mmix_asm_output_addr_diff_elt (FILE *stream,
1849 rtx body ATTRIBUTE_UNUSED,
1850 int value,
1851 int rel)
1853 fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
1856 /* ASM_OUTPUT_ADDR_VEC_ELT. */
1858 void
1859 mmix_asm_output_addr_vec_elt (FILE *stream, int value)
1861 fprintf (stream, "\tOCTA L:%d\n", value);
1864 /* ASM_OUTPUT_SKIP. */
1866 void
1867 mmix_asm_output_skip (FILE *stream, int nbytes)
1869 fprintf (stream, "\tLOC @+%d\n", nbytes);
1872 /* ASM_OUTPUT_ALIGN. */
1874 void
1875 mmix_asm_output_align (FILE *stream, int power)
1877 /* We need to record the needed alignment of this section in the object,
1878 so we have to output an alignment directive. Use a .p2align (not
1879 .align) so people will never have to wonder about whether the
1880 argument is in number of bytes or the log2 thereof. We do it in
1881 addition to the LOC directive, so nothing needs tweaking when
1882 copy-pasting assembly into mmixal. */
1883 fprintf (stream, "\t.p2align %d\n", power);
1884 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
1887 /* DBX_REGISTER_NUMBER. */
1889 unsigned
1890 mmix_dbx_register_number (unsigned regno)
1892 /* Adjust the register number to the one it will be output as, dammit.
1893 It'd be nice if we could check the assumption that we're filling a
1894 gap, but every register between the last saved register and parameter
1895 registers might be a valid parameter register. */
1896 regno = MMIX_OUTPUT_REGNO (regno);
1898 /* We need to renumber registers to get the number of the return address
1899 register in the range 0..255. It is also space-saving if registers
1900 mentioned in the call-frame information (which uses this function by
1901 defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered
1902 0 .. 63. So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48. */
1903 return regno >= 224 ? (regno - 224) : (regno + 48);
1906 /* End of target macro support functions.
1908 Now the MMIX port's own functions. First the exported ones. */
1910 /* Wrapper for get_hard_reg_initial_val since integrate.h isn't included
1911 from insn-emit.c. */
1914 mmix_get_hard_reg_initial_val (machine_mode mode, int regno)
1916 return get_hard_reg_initial_val (mode, regno);
1919 /* Nonzero when the function epilogue is simple enough that a single
1920 "POP %d,0" should be used even within the function. */
1923 mmix_use_simple_return (void)
1925 int regno;
1927 int stack_space_to_allocate
1928 = (crtl->outgoing_args_size
1929 + crtl->args.pretend_args_size
1930 + get_frame_size () + 7) & ~7;
1932 if (!TARGET_USE_RETURN_INSN || !reload_completed)
1933 return 0;
1935 for (regno = 255;
1936 regno >= MMIX_FIRST_GLOBAL_REGNUM;
1937 regno--)
1938 /* Note that we assume that the frame-pointer-register is one of these
1939 registers, in which case we don't count it here. */
1940 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1941 && df_regs_ever_live_p (regno) && !call_used_regs[regno]))
1942 || IS_MMIX_EH_RETURN_DATA_REG (regno))
1943 return 0;
1945 if (frame_pointer_needed)
1946 stack_space_to_allocate += 8;
1948 if (MMIX_CFUN_HAS_LANDING_PAD)
1949 stack_space_to_allocate += 16;
1950 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
1951 stack_space_to_allocate += 8;
1953 return stack_space_to_allocate == 0;
1957 /* Expands the function prologue into RTX. */
1959 void
1960 mmix_expand_prologue (void)
1962 HOST_WIDE_INT locals_size = get_frame_size ();
1963 int regno;
1964 HOST_WIDE_INT stack_space_to_allocate
1965 = (crtl->outgoing_args_size
1966 + crtl->args.pretend_args_size
1967 + locals_size + 7) & ~7;
1968 HOST_WIDE_INT offset = -8;
1970 /* Add room needed to save global non-register-stack registers. */
1971 for (regno = 255;
1972 regno >= MMIX_FIRST_GLOBAL_REGNUM;
1973 regno--)
1974 /* Note that we assume that the frame-pointer-register is one of these
1975 registers, in which case we don't count it here. */
1976 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
1977 && df_regs_ever_live_p (regno) && !call_used_regs[regno]))
1978 || IS_MMIX_EH_RETURN_DATA_REG (regno))
1979 stack_space_to_allocate += 8;
1981 /* If we do have a frame-pointer, add room for it. */
1982 if (frame_pointer_needed)
1983 stack_space_to_allocate += 8;
1985 /* If we have a non-local label, we need to be able to unwind to it, so
1986 store the current register stack pointer. Also store the return
1987 address if we do that. */
1988 if (MMIX_CFUN_HAS_LANDING_PAD)
1989 stack_space_to_allocate += 16;
1990 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
1991 /* If we do have a saved return-address slot, add room for it. */
1992 stack_space_to_allocate += 8;
1994 /* Make sure we don't get an unaligned stack. */
1995 if ((stack_space_to_allocate % 8) != 0)
1996 internal_error ("stack frame not a multiple of 8 bytes: %wd",
1997 stack_space_to_allocate);
1999 if (crtl->args.pretend_args_size)
2001 int mmix_first_vararg_reg
2002 = (MMIX_FIRST_INCOMING_ARG_REGNUM
2003 + (MMIX_MAX_ARGS_IN_REGS
2004 - crtl->args.pretend_args_size / 8));
2006 for (regno
2007 = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
2008 regno >= mmix_first_vararg_reg;
2009 regno--)
2011 if (offset < 0)
2013 HOST_WIDE_INT stack_chunk
2014 = stack_space_to_allocate > (256 - 8)
2015 ? (256 - 8) : stack_space_to_allocate;
2017 mmix_emit_sp_add (-stack_chunk);
2018 offset += stack_chunk;
2019 stack_space_to_allocate -= stack_chunk;
2022 /* These registers aren't actually saved (as in "will be
2023 restored"), so don't tell DWARF2 they're saved. */
2024 emit_move_insn (gen_rtx_MEM (DImode,
2025 plus_constant (Pmode, stack_pointer_rtx,
2026 offset)),
2027 gen_rtx_REG (DImode, regno));
2028 offset -= 8;
2032 /* Store the frame-pointer. */
2034 if (frame_pointer_needed)
2036 rtx insn;
2038 if (offset < 0)
2040 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2041 HOST_WIDE_INT stack_chunk
2042 = stack_space_to_allocate > (256 - 8 - 8)
2043 ? (256 - 8 - 8) : stack_space_to_allocate;
2045 mmix_emit_sp_add (-stack_chunk);
2047 offset += stack_chunk;
2048 stack_space_to_allocate -= stack_chunk;
2051 insn = emit_move_insn (gen_rtx_MEM (DImode,
2052 plus_constant (Pmode,
2053 stack_pointer_rtx,
2054 offset)),
2055 hard_frame_pointer_rtx);
2056 RTX_FRAME_RELATED_P (insn) = 1;
2057 insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
2058 stack_pointer_rtx,
2059 GEN_INT (offset + 8)));
2060 RTX_FRAME_RELATED_P (insn) = 1;
2061 offset -= 8;
2064 if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2066 rtx tmpreg, retreg;
2067 rtx insn;
2069 /* Store the return-address, if one is needed on the stack. We
2070 usually store it in a register when needed, but that doesn't work
2071 with -fexceptions. */
2073 if (offset < 0)
2075 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2076 HOST_WIDE_INT stack_chunk
2077 = stack_space_to_allocate > (256 - 8 - 8)
2078 ? (256 - 8 - 8) : stack_space_to_allocate;
2080 mmix_emit_sp_add (-stack_chunk);
2082 offset += stack_chunk;
2083 stack_space_to_allocate -= stack_chunk;
2086 tmpreg = gen_rtx_REG (DImode, 255);
2087 retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM);
2089 /* Dwarf2 code is confused by the use of a temporary register for
2090 storing the return address, so we have to express it as a note,
2091 which we attach to the actual store insn. */
2092 emit_move_insn (tmpreg, retreg);
2094 insn = emit_move_insn (gen_rtx_MEM (DImode,
2095 plus_constant (Pmode,
2096 stack_pointer_rtx,
2097 offset)),
2098 tmpreg);
2099 RTX_FRAME_RELATED_P (insn) = 1;
2100 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2101 gen_rtx_SET (gen_rtx_MEM (DImode,
2102 plus_constant (Pmode,
2103 stack_pointer_rtx,
2104 offset)),
2105 retreg));
2107 offset -= 8;
2109 else if (MMIX_CFUN_HAS_LANDING_PAD)
2110 offset -= 8;
2112 if (MMIX_CFUN_HAS_LANDING_PAD)
2114 /* Store the register defining the numbering of local registers, so
2115 we know how long to unwind the register stack. */
2117 if (offset < 0)
2119 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2120 HOST_WIDE_INT stack_chunk
2121 = stack_space_to_allocate > (256 - 8 - 8)
2122 ? (256 - 8 - 8) : stack_space_to_allocate;
2124 mmix_emit_sp_add (-stack_chunk);
2126 offset += stack_chunk;
2127 stack_space_to_allocate -= stack_chunk;
2130 /* We don't tell dwarf2 about this one; we just have it to unwind
2131 the register stack at landing pads. FIXME: It's a kludge because
2132 we can't describe the effect of the PUSHJ and PUSHGO insns on the
2133 register stack at the moment. Best thing would be to handle it
2134 like stack-pointer offsets. Better: some hook into dwarf2out.c
2135 to produce DW_CFA_expression:s that specify the increment of rO,
2136 and unwind it at eh_return (preferred) or at the landing pad.
2137 Then saves to $0..$G-1 could be specified through that register. */
2139 emit_move_insn (gen_rtx_REG (DImode, 255),
2140 gen_rtx_REG (DImode,
2141 MMIX_rO_REGNUM));
2142 emit_move_insn (gen_rtx_MEM (DImode,
2143 plus_constant (Pmode, stack_pointer_rtx,
2144 offset)),
2145 gen_rtx_REG (DImode, 255));
2146 offset -= 8;
2149 /* After the return-address and the frame-pointer, we have the local
2150 variables. They're the ones that may have an "unaligned" size. */
2151 offset -= (locals_size + 7) & ~7;
2153 /* Now store all registers that are global, i.e. not saved by the
2154 register file machinery.
2156 It is assumed that the frame-pointer is one of these registers, so it
2157 is explicitly excluded in the count. */
2159 for (regno = 255;
2160 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2161 regno--)
2162 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2163 && df_regs_ever_live_p (regno) && ! call_used_regs[regno])
2164 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2166 rtx insn;
2168 if (offset < 0)
2170 HOST_WIDE_INT stack_chunk
2171 = (stack_space_to_allocate > (256 - offset - 8)
2172 ? (256 - offset - 8) : stack_space_to_allocate);
2174 mmix_emit_sp_add (-stack_chunk);
2175 offset += stack_chunk;
2176 stack_space_to_allocate -= stack_chunk;
2179 insn = emit_move_insn (gen_rtx_MEM (DImode,
2180 plus_constant (Pmode,
2181 stack_pointer_rtx,
2182 offset)),
2183 gen_rtx_REG (DImode, regno));
2184 RTX_FRAME_RELATED_P (insn) = 1;
2185 offset -= 8;
2188 /* Finally, allocate room for outgoing args and local vars if room
2189 wasn't allocated above. */
2190 if (stack_space_to_allocate)
2191 mmix_emit_sp_add (-stack_space_to_allocate);
2194 /* Expands the function epilogue into RTX. */
2196 void
2197 mmix_expand_epilogue (void)
2199 HOST_WIDE_INT locals_size = get_frame_size ();
2200 int regno;
2201 HOST_WIDE_INT stack_space_to_deallocate
2202 = (crtl->outgoing_args_size
2203 + crtl->args.pretend_args_size
2204 + locals_size + 7) & ~7;
2206 /* The first address to access is beyond the outgoing_args area. */
2207 HOST_WIDE_INT offset = crtl->outgoing_args_size;
2209 /* Add the space for global non-register-stack registers.
2210 It is assumed that the frame-pointer register can be one of these
2211 registers, in which case it is excluded from the count when needed. */
2212 for (regno = 255;
2213 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2214 regno--)
2215 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2216 && df_regs_ever_live_p (regno) && !call_used_regs[regno])
2217 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2218 stack_space_to_deallocate += 8;
2220 /* Add in the space for register stack-pointer. If so, always add room
2221 for the saved PC. */
2222 if (MMIX_CFUN_HAS_LANDING_PAD)
2223 stack_space_to_deallocate += 16;
2224 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2225 /* If we have a saved return-address slot, add it in. */
2226 stack_space_to_deallocate += 8;
2228 /* Add in the frame-pointer. */
2229 if (frame_pointer_needed)
2230 stack_space_to_deallocate += 8;
2232 /* Make sure we don't get an unaligned stack. */
2233 if ((stack_space_to_deallocate % 8) != 0)
2234 internal_error ("stack frame not a multiple of octabyte: %wd",
2235 stack_space_to_deallocate);
2237 /* We will add back small offsets to the stack pointer as we go.
2238 First, we restore all registers that are global, i.e. not saved by
2239 the register file machinery. */
2241 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
2242 regno <= 255;
2243 regno++)
2244 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2245 && df_regs_ever_live_p (regno) && !call_used_regs[regno])
2246 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2248 if (offset > 255)
2250 mmix_emit_sp_add (offset);
2251 stack_space_to_deallocate -= offset;
2252 offset = 0;
2255 emit_move_insn (gen_rtx_REG (DImode, regno),
2256 gen_rtx_MEM (DImode,
2257 plus_constant (Pmode, stack_pointer_rtx,
2258 offset)));
2259 offset += 8;
2262 /* Here is where the local variables were. As in the prologue, they
2263 might be of an unaligned size. */
2264 offset += (locals_size + 7) & ~7;
2266 /* The saved register stack pointer is just below the frame-pointer
2267 register. We don't need to restore it "manually"; the POP
2268 instruction does that. */
2269 if (MMIX_CFUN_HAS_LANDING_PAD)
2270 offset += 16;
2271 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2272 /* The return-address slot is just below the frame-pointer register.
2273 We don't need to restore it because we don't really use it. */
2274 offset += 8;
2276 /* Get back the old frame-pointer-value. */
2277 if (frame_pointer_needed)
2279 if (offset > 255)
2281 mmix_emit_sp_add (offset);
2283 stack_space_to_deallocate -= offset;
2284 offset = 0;
2287 emit_move_insn (hard_frame_pointer_rtx,
2288 gen_rtx_MEM (DImode,
2289 plus_constant (Pmode, stack_pointer_rtx,
2290 offset)));
2291 offset += 8;
2294 /* We do not need to restore pretended incoming args, just add back
2295 offset to sp. */
2296 if (stack_space_to_deallocate != 0)
2297 mmix_emit_sp_add (stack_space_to_deallocate);
2299 if (crtl->calls_eh_return)
2300 /* Adjust the (normal) stack-pointer to that of the receiver.
2301 FIXME: It would be nice if we could also adjust the register stack
2302 here, but we need to express it through DWARF 2 too. */
2303 emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
2304 gen_rtx_REG (DImode,
2305 MMIX_EH_RETURN_STACKADJ_REGNUM)));
2308 /* Output an optimal sequence for setting a register to a specific
2309 constant. Used in an alternative for const_ints in movdi, and when
2310 using large stack-frame offsets.
2312 Use do_begin_end to say if a line-starting TAB and newline before the
2313 first insn and after the last insn is wanted. */
2315 void
2316 mmix_output_register_setting (FILE *stream,
2317 int regno,
2318 int64_t value,
2319 int do_begin_end)
2321 if (do_begin_end)
2322 fprintf (stream, "\t");
2324 if (insn_const_int_ok_for_constraint (value, CONSTRAINT_K))
2325 fprintf (stream, "NEGU %s,0,%" PRId64, reg_names[regno], -value);
2326 else if (mmix_shiftable_wyde_value ((uint64_t) value))
2328 /* First, the one-insn cases. */
2329 mmix_output_shiftvalue_op_from_str (stream, "SET",
2330 (uint64_t)
2331 value);
2332 fprintf (stream, " %s,", reg_names[regno]);
2333 mmix_output_shifted_value (stream, (uint64_t) value);
2335 else if (mmix_shiftable_wyde_value (-(uint64_t) value))
2337 /* We do this to get a bit more legible assembly code. The next
2338 alternative is mostly redundant with this. */
2340 mmix_output_shiftvalue_op_from_str (stream, "SET",
2341 -(uint64_t)
2342 value);
2343 fprintf (stream, " %s,", reg_names[regno]);
2344 mmix_output_shifted_value (stream, -(uint64_t) value);
2345 fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
2346 reg_names[regno]);
2348 else if (mmix_shiftable_wyde_value (~(uint64_t) value))
2350 /* Slightly more expensive, the two-insn cases. */
2352 /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255)
2353 is shiftable, or any other one-insn transformation of the value.
2354 FIXME: Check first if the value is "shiftable" by two loading
2355 with two insns, since it makes more readable assembly code (if
2356 anyone else cares). */
2358 mmix_output_shiftvalue_op_from_str (stream, "SET",
2359 ~(uint64_t)
2360 value);
2361 fprintf (stream, " %s,", reg_names[regno]);
2362 mmix_output_shifted_value (stream, ~(uint64_t) value);
2363 fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
2364 reg_names[regno]);
2366 else
2368 /* The generic case. 2..4 insns. */
2369 static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
2370 const char *op = "SET";
2371 const char *line_begin = "";
2372 int insns = 0;
2373 int i;
2374 int64_t tmpvalue = value;
2376 /* Compute the number of insns needed to output this constant. */
2377 for (i = 0; i < 4 && tmpvalue != 0; i++)
2379 if (tmpvalue & 65535)
2380 insns++;
2381 tmpvalue >>= 16;
2383 if (TARGET_BASE_ADDRESSES && insns == 3)
2385 /* The number three is based on a static observation on
2386 ghostscript-6.52. Two and four are excluded because there
2387 are too many such constants, and each unique constant (maybe
2388 offset by 1..255) were used few times compared to other uses,
2389 e.g. addresses.
2391 We use base-plus-offset addressing to force it into a global
2392 register; we just use a "LDA reg,VALUE", which will cause the
2393 assembler and linker to DTRT (for constants as well as
2394 addresses). */
2395 fprintf (stream, "LDA %s,", reg_names[regno]);
2396 mmix_output_octa (stream, value, 0);
2398 else
2400 /* Output pertinent parts of the 4-wyde sequence.
2401 Still more to do if we want this to be optimal, but hey...
2402 Note that the zero case has been handled above. */
2403 for (i = 0; i < 4 && value != 0; i++)
2405 if (value & 65535)
2407 fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
2408 higher_parts[i], reg_names[regno],
2409 (int) (value & 65535));
2410 /* The first one sets the rest of the bits to 0, the next
2411 ones add set bits. */
2412 op = "INC";
2413 line_begin = "\n\t";
2416 value >>= 16;
2421 if (do_begin_end)
2422 fprintf (stream, "\n");
2425 /* Return 1 if value is 0..65535*2**(16*N) for N=0..3.
2426 else return 0. */
2429 mmix_shiftable_wyde_value (uint64_t value)
2431 /* Shift by 16 bits per group, stop when we've found two groups with
2432 nonzero bits. */
2433 int i;
2434 int has_candidate = 0;
2436 for (i = 0; i < 4; i++)
2438 if (value & 65535)
2440 if (has_candidate)
2441 return 0;
2442 else
2443 has_candidate = 1;
2446 value >>= 16;
2449 return 1;
2452 /* X and Y are two things to compare using CODE. Return the rtx for
2453 the cc-reg in the proper mode. */
2456 mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y)
2458 machine_mode ccmode = SELECT_CC_MODE (code, x, y);
2459 return gen_reg_rtx (ccmode);
2462 /* Local (static) helper functions. */
2464 static void
2465 mmix_emit_sp_add (HOST_WIDE_INT offset)
2467 rtx insn;
2469 if (offset < 0)
2471 /* Negative stack-pointer adjustments are allocations and appear in
2472 the prologue only. We mark them as frame-related so unwind and
2473 debug info is properly emitted for them. */
2474 if (offset > -255)
2475 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2476 stack_pointer_rtx,
2477 GEN_INT (offset)));
2478 else
2480 rtx tmpr = gen_rtx_REG (DImode, 255);
2481 RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1;
2482 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2483 stack_pointer_rtx, tmpr));
2485 RTX_FRAME_RELATED_P (insn) = 1;
2487 else
2489 /* Positive adjustments are in the epilogue only. Don't mark them
2490 as "frame-related" for unwind info. */
2491 if (insn_const_int_ok_for_constraint (offset, CONSTRAINT_L))
2492 emit_insn (gen_adddi3 (stack_pointer_rtx,
2493 stack_pointer_rtx,
2494 GEN_INT (offset)));
2495 else
2497 rtx tmpr = gen_rtx_REG (DImode, 255);
2498 emit_move_insn (tmpr, GEN_INT (offset));
2499 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2500 stack_pointer_rtx, tmpr));
2505 /* Print operator suitable for doing something with a shiftable
2506 wyde. The type of operator is passed as an asm output modifier. */
2508 static void
2509 mmix_output_shiftvalue_op_from_str (FILE *stream,
2510 const char *mainop,
2511 int64_t value)
2513 static const char *const op_part[] = {"L", "ML", "MH", "H"};
2514 int i;
2516 if (! mmix_shiftable_wyde_value (value))
2518 char s[sizeof ("0xffffffffffffffff")];
2519 sprintf (s, "%#" PRIx64, value);
2520 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2523 for (i = 0; i < 4; i++)
2525 /* We know we're through when we find one-bits in the low
2526 16 bits. */
2527 if (value & 0xffff)
2529 fprintf (stream, "%s%s", mainop, op_part[i]);
2530 return;
2532 value >>= 16;
2535 /* No bits set? Then it must have been zero. */
2536 fprintf (stream, "%sL", mainop);
2539 /* Print a 64-bit value, optionally prefixed by assembly pseudo. */
2541 static void
2542 mmix_output_octa (FILE *stream, int64_t value, int do_begin_end)
2544 if (do_begin_end)
2545 fprintf (stream, "\tOCTA ");
2547 /* Provide a few alternative output formats depending on the number, to
2548 improve legibility of assembler output. */
2549 if ((value < (int64_t) 0 && value > (int64_t) -10000)
2550 || (value >= (int64_t) 0 && value <= (int64_t) 16384))
2551 fprintf (stream, "%d", (int) value);
2552 else if (value > (int64_t) 0
2553 && value < ((int64_t) 1 << 31) * 2)
2554 fprintf (stream, "#%x", (unsigned int) value);
2555 else if (sizeof (HOST_WIDE_INT) == sizeof (int64_t))
2556 /* We need to avoid the not-so-universal "0x" prefix; we need the
2557 pure hex-digits together with the mmixal "#" hex prefix. */
2558 fprintf (stream, "#" HOST_WIDE_INT_PRINT_HEX_PURE,
2559 (HOST_WIDE_INT) value);
2560 else /* Need to avoid the hex output; there's no ...WIDEST...HEX_PURE. */
2561 fprintf (stream, "%" PRIu64, value);
2563 if (do_begin_end)
2564 fprintf (stream, "\n");
2567 /* Print the presumed shiftable wyde argument shifted into place (to
2568 be output with an operand). */
2570 static void
2571 mmix_output_shifted_value (FILE *stream, int64_t value)
2573 int i;
2575 if (! mmix_shiftable_wyde_value (value))
2577 char s[16+2+1];
2578 sprintf (s, "%#" PRIx64, value);
2579 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2582 for (i = 0; i < 4; i++)
2584 /* We know we're through when we find one-bits in the low 16 bits. */
2585 if (value & 0xffff)
2587 fprintf (stream, "#%x", (int) (value & 0xffff));
2588 return;
2591 value >>= 16;
2594 /* No bits set? Then it must have been zero. */
2595 fprintf (stream, "0");
2598 /* Output an MMIX condition name corresponding to an operator
2599 and operands:
2600 (comparison_operator [(comparison_operator ...) (const_int 0)])
2601 which means we have to look at *two* operators.
2603 The argument "reversed" refers to reversal of the condition (not the
2604 same as swapping the arguments). */
2606 static void
2607 mmix_output_condition (FILE *stream, const_rtx x, int reversed)
2609 struct cc_conv
2611 RTX_CODE cc;
2613 /* The normal output cc-code. */
2614 const char *const normal;
2616 /* The reversed cc-code, or NULL if invalid. */
2617 const char *const reversed;
2620 struct cc_type_conv
2622 machine_mode cc_mode;
2624 /* Terminated with {UNKNOWN, NULL, NULL} */
2625 const struct cc_conv *const convs;
2628 #undef CCEND
2629 #define CCEND {UNKNOWN, NULL, NULL}
2631 static const struct cc_conv cc_fun_convs[]
2632 = {{ORDERED, "Z", "P"},
2633 {UNORDERED, "P", "Z"},
2634 CCEND};
2635 static const struct cc_conv cc_fp_convs[]
2636 = {{GT, "P", NULL},
2637 {LT, "N", NULL},
2638 CCEND};
2639 static const struct cc_conv cc_fpeq_convs[]
2640 = {{NE, "Z", "P"},
2641 {EQ, "P", "Z"},
2642 CCEND};
2643 static const struct cc_conv cc_uns_convs[]
2644 = {{GEU, "NN", "N"},
2645 {GTU, "P", "NP"},
2646 {LEU, "NP", "P"},
2647 {LTU, "N", "NN"},
2648 CCEND};
2649 static const struct cc_conv cc_signed_convs[]
2650 = {{NE, "NZ", "Z"},
2651 {EQ, "Z", "NZ"},
2652 {GE, "NN", "N"},
2653 {GT, "P", "NP"},
2654 {LE, "NP", "P"},
2655 {LT, "N", "NN"},
2656 CCEND};
2657 static const struct cc_conv cc_di_convs[]
2658 = {{NE, "NZ", "Z"},
2659 {EQ, "Z", "NZ"},
2660 {GE, "NN", "N"},
2661 {GT, "P", "NP"},
2662 {LE, "NP", "P"},
2663 {LT, "N", "NN"},
2664 {GTU, "NZ", "Z"},
2665 {LEU, "Z", "NZ"},
2666 CCEND};
2667 #undef CCEND
2669 static const struct cc_type_conv cc_convs[]
2670 = {{E_CC_FUNmode, cc_fun_convs},
2671 {E_CC_FPmode, cc_fp_convs},
2672 {E_CC_FPEQmode, cc_fpeq_convs},
2673 {E_CC_UNSmode, cc_uns_convs},
2674 {E_CCmode, cc_signed_convs},
2675 {E_DImode, cc_di_convs}};
2677 size_t i;
2678 int j;
2680 machine_mode mode = GET_MODE (XEXP (x, 0));
2681 RTX_CODE cc = GET_CODE (x);
2683 for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
2685 if (mode == cc_convs[i].cc_mode)
2687 for (j = 0; cc_convs[i].convs[j].cc != UNKNOWN; j++)
2688 if (cc == cc_convs[i].convs[j].cc)
2690 const char *mmix_cc
2691 = (reversed ? cc_convs[i].convs[j].reversed
2692 : cc_convs[i].convs[j].normal);
2694 if (mmix_cc == NULL)
2695 fatal_insn ("MMIX Internal: Trying to output invalidly\
2696 reversed condition:", x);
2698 fprintf (stream, "%s", mmix_cc);
2699 return;
2702 fatal_insn ("MMIX Internal: What's the CC of this?", x);
2706 fatal_insn ("MMIX Internal: What is the CC of this?", x);
2709 /* Return the bit-value for a const_int or const_double. */
2711 int64_t
2712 mmix_intval (const_rtx x)
2714 if (GET_CODE (x) == CONST_INT)
2715 return INTVAL (x);
2717 /* We make a little song and dance because converting to long long in
2718 gcc-2.7.2 is broken. I still want people to be able to use it for
2719 cross-compilation to MMIX. */
2720 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
2721 return CONST_DOUBLE_HIGH (x);
2723 if (GET_CODE (x) == CONST_DOUBLE)
2725 if (GET_MODE (x) == DFmode)
2727 long bits[2];
2729 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
2731 /* The double cast is necessary to avoid getting the long
2732 sign-extended to unsigned long long(!) when they're of
2733 different size (usually 32-bit hosts). */
2734 return
2735 ((uint64_t) (unsigned long) bits[0]
2736 << (uint64_t) 32U)
2737 | (uint64_t) (unsigned long) bits[1];
2739 else if (GET_MODE (x) == SFmode)
2741 long bits;
2742 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
2744 return (unsigned long) bits;
2748 fatal_insn ("MMIX Internal: This is not a constant:", x);
2751 /* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */
2753 machine_mode
2754 mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
2755 machine_mode mode,
2756 int *punsignedp ATTRIBUTE_UNUSED,
2757 const_tree fntype ATTRIBUTE_UNUSED,
2758 int for_return)
2760 /* Apparently not doing TRT if int < register-size. FIXME: Perhaps
2761 FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say. */
2762 if (for_return == 1)
2763 return mode;
2765 /* Promotion of modes currently generates slow code, extending before
2766 operation, so we do it only for arguments. */
2767 if (GET_MODE_CLASS (mode) == MODE_INT
2768 && GET_MODE_SIZE (mode) < 8)
2769 return DImode;
2770 else
2771 return mode;
2773 /* Worker function for TARGET_STRUCT_VALUE_RTX. */
2775 static rtx
2776 mmix_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
2777 int incoming ATTRIBUTE_UNUSED)
2779 return gen_rtx_REG (Pmode, MMIX_STRUCT_VALUE_REGNUM);
2782 /* Worker function for TARGET_FRAME_POINTER_REQUIRED.
2784 FIXME: Is this requirement built-in? Anyway, we should try to get rid
2785 of it; we can deduce the value. */
2787 bool
2788 mmix_frame_pointer_required (void)
2790 return (cfun->has_nonlocal_label);
2794 * Local variables:
2795 * eval: (c-set-style "gnu")
2796 * indent-tabs-mode: t
2797 * End: