* target.h (asm_out.file_start, file_start_app_off,
[official-gcc.git] / gcc / config / mmix / mmix.c
blob290b5d83e070b145392d11b6bd18581070abbbd2
1 /* Definitions of target machine for GNU compiler, for MMIX.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Hans-Peter Nilsson (hp@bitrange.com)
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 2, 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 COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "hashtab.h"
30 #include "insn-config.h"
31 #include "output.h"
32 #include "flags.h"
33 #include "tree.h"
34 #include "function.h"
35 #include "expr.h"
36 #include "toplev.h"
37 #include "recog.h"
38 #include "ggc.h"
39 #include "dwarf2.h"
40 #include "debug.h"
41 #include "tm_p.h"
42 #include "integrate.h"
43 #include "target.h"
44 #include "target-def.h"
45 #include "real.h"
47 /* First some local helper definitions. */
48 #define MMIX_FIRST_GLOBAL_REGNUM 32
50 /* We'd need a current_function_has_landing_pad. It's marked as such when
51 a nonlocal_goto_receiver is expanded. Not just a C++ thing, but
52 mostly. */
53 #define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)
55 /* We have no means to tell DWARF 2 about the register stack, so we need
56 to store the return address on the stack if an exception can get into
57 this function. FIXME: Narrow condition. Before any whole-function
58 analysis, regs_ever_live[] isn't initialized. We know it's up-to-date
59 after reload_completed; it may contain incorrect information some time
60 before that. Within a RTL sequence (after a call to start_sequence,
61 such as in RTL expanders), leaf_function_p doesn't see all insns
62 (perhaps any insn). But regs_ever_live is up-to-date when
63 leaf_function_p () isn't, so we "or" them together to get accurate
64 information. FIXME: Some tweak to leaf_function_p might be
65 preferrable. */
66 #define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
67 (flag_exceptions \
68 && ((reload_completed && regs_ever_live[MMIX_rJ_REGNUM]) \
69 || !leaf_function_p ()))
71 #define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \
72 (current_function_calls_eh_return \
73 && (EH_RETURN_DATA_REGNO (0) == REGNO \
74 || EH_RETURN_DATA_REGNO (1) == REGNO \
75 || EH_RETURN_DATA_REGNO (2) == REGNO \
76 || EH_RETURN_DATA_REGNO (3) == REGNO))
78 /* For the default ABI, we rename registers at output-time to fill the gap
79 between the (statically partitioned) saved registers and call-clobbered
80 registers. In effect this makes unused call-saved registers to be used
81 as call-clobbered registers. The benefit comes from keeping the number
82 of local registers (value of rL) low, since there's a cost of
83 increasing rL and clearing unused (unset) registers with lower numbers.
84 Don't translate while outputting the prologue. */
85 #define MMIX_OUTPUT_REGNO(N) \
86 (TARGET_ABI_GNU \
87 || (int) (N) < MMIX_RETURN_VALUE_REGNUM \
88 || (int) (N) > MMIX_LAST_STACK_REGISTER_REGNUM \
89 || cfun == NULL \
90 || cfun->machine == NULL \
91 || cfun->machine->in_prologue \
92 ? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM \
93 + cfun->machine->highest_saved_stack_register + 1))
95 /* The %d in "POP %d,0". */
96 #define MMIX_POP_ARGUMENT() \
97 ((! TARGET_ABI_GNU \
98 && current_function_return_rtx != NULL \
99 && ! current_function_returns_struct) \
100 ? (GET_CODE (current_function_return_rtx) == PARALLEL \
101 ? GET_NUM_ELEM (XVEC (current_function_return_rtx, 0)) : 1) \
102 : 0)
104 /* The canonical saved comparison operands for non-cc0 machines, set in
105 the compare expander. */
106 rtx mmix_compare_op0;
107 rtx mmix_compare_op1;
109 /* We ignore some options with arguments. They are passed to the linker,
110 but also ends up here because they start with "-m". We tell the driver
111 to store them in a variable we don't inspect. */
112 const char *mmix_cc1_ignored_option;
114 /* Declarations of locals. */
116 /* Intermediate for insn output. */
117 static int mmix_output_destination_register;
119 static void mmix_output_shiftvalue_op_from_str
120 PARAMS ((FILE *, const char *, HOST_WIDEST_INT));
121 static void mmix_output_shifted_value PARAMS ((FILE *, HOST_WIDEST_INT));
122 static void mmix_output_condition PARAMS ((FILE *, rtx, int));
123 static HOST_WIDEST_INT mmix_intval PARAMS ((rtx));
124 static void mmix_output_octa PARAMS ((FILE *, HOST_WIDEST_INT, int));
125 static bool mmix_assemble_integer PARAMS ((rtx, unsigned int, int));
126 static struct machine_function * mmix_init_machine_status PARAMS ((void));
127 static void mmix_encode_section_info PARAMS ((tree, rtx, int));
128 static const char *mmix_strip_name_encoding PARAMS ((const char *));
129 static void mmix_emit_sp_add PARAMS ((HOST_WIDE_INT offset));
130 static void mmix_target_asm_function_prologue
131 PARAMS ((FILE *, HOST_WIDE_INT));
132 static void mmix_target_asm_function_end_prologue PARAMS ((FILE *));
133 static void mmix_target_asm_function_epilogue
134 PARAMS ((FILE *, HOST_WIDE_INT));
135 static void mmix_reorg PARAMS ((void));
136 static void mmix_asm_output_mi_thunk
137 PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
138 static void mmix_file_start PARAMS ((void));
139 static void mmix_file_end PARAMS ((void));
140 static bool mmix_rtx_costs
141 PARAMS ((rtx, int, int, int *));
144 /* Target structure macros. Listed by node. See `Using and Porting GCC'
145 for a general description. */
147 /* Node: Function Entry */
149 #undef TARGET_ASM_BYTE_OP
150 #define TARGET_ASM_BYTE_OP NULL
151 #undef TARGET_ASM_ALIGNED_HI_OP
152 #define TARGET_ASM_ALIGNED_HI_OP NULL
153 #undef TARGET_ASM_ALIGNED_SI_OP
154 #define TARGET_ASM_ALIGNED_SI_OP NULL
155 #undef TARGET_ASM_ALIGNED_DI_OP
156 #define TARGET_ASM_ALIGNED_DI_OP NULL
157 #undef TARGET_ASM_INTEGER
158 #define TARGET_ASM_INTEGER mmix_assemble_integer
160 #undef TARGET_ASM_FUNCTION_PROLOGUE
161 #define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
163 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
164 #define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue
166 #undef TARGET_ASM_FUNCTION_EPILOGUE
167 #define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
169 #undef TARGET_ENCODE_SECTION_INFO
170 #define TARGET_ENCODE_SECTION_INFO mmix_encode_section_info
171 #undef TARGET_STRIP_NAME_ENCODING
172 #define TARGET_STRIP_NAME_ENCODING mmix_strip_name_encoding
174 #undef TARGET_ASM_OUTPUT_MI_THUNK
175 #define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
176 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
177 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
178 #undef TARGET_ASM_FILE_START
179 #define TARGET_ASM_FILE_START mmix_file_start
180 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
181 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
182 #undef TARGET_ASM_FILE_END
183 #define TARGET_ASM_FILE_END mmix_file_end
185 #undef TARGET_RTX_COSTS
186 #define TARGET_RTX_COSTS mmix_rtx_costs
187 #undef TARGET_ADDRESS_COST
188 #define TARGET_ADDRESS_COST hook_int_rtx_0
190 #undef TARGET_MACHINE_DEPENDENT_REORG
191 #define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg
193 struct gcc_target targetm = TARGET_INITIALIZER;
195 /* Functions that are expansions for target macros.
196 See Target Macros in `Using and Porting GCC'. */
198 /* OVERRIDE_OPTIONS. */
200 void
201 mmix_override_options ()
203 /* Should we err or should we warn? Hmm. At least we must neutralize
204 it. For example the wrong kind of case-tables will be generated with
205 PIC; we use absolute address items for mmixal compatibility. FIXME:
206 They could be relative if we just elide them to after all pertinent
207 labels. */
208 if (flag_pic)
210 warning ("-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
211 flag_pic = 0;
215 /* INIT_EXPANDERS. */
217 void
218 mmix_init_expanders ()
220 init_machine_status = mmix_init_machine_status;
223 /* Set the per-function data. */
225 static struct machine_function *
226 mmix_init_machine_status ()
228 return ggc_alloc_cleared (sizeof (struct machine_function));
231 /* DATA_ALIGNMENT.
232 We have trouble getting the address of stuff that is located at other
233 than 32-bit alignments (GETA requirements), so try to give everything
234 at least 32-bit alignment. */
237 mmix_data_alignment (type, basic_align)
238 tree type ATTRIBUTE_UNUSED;
239 int basic_align;
241 if (basic_align < 32)
242 return 32;
244 return basic_align;
247 /* CONSTANT_ALIGNMENT. */
250 mmix_constant_alignment (constant, basic_align)
251 tree constant ATTRIBUTE_UNUSED;
252 int basic_align;
254 if (basic_align < 32)
255 return 32;
257 return basic_align;
260 /* LOCAL_ALIGNMENT. */
263 mmix_local_alignment (type, basic_align)
264 tree type ATTRIBUTE_UNUSED;
265 int basic_align;
267 if (basic_align < 32)
268 return 32;
270 return basic_align;
273 /* CONDITIONAL_REGISTER_USAGE. */
275 void
276 mmix_conditional_register_usage ()
278 int i;
280 if (TARGET_ABI_GNU)
282 static const int gnu_abi_reg_alloc_order[]
283 = MMIX_GNU_ABI_REG_ALLOC_ORDER;
285 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
286 reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];
288 /* Change the default from the mmixware ABI. For the GNU ABI,
289 $15..$30 are call-saved just as $0..$14. There must be one
290 call-clobbered local register for the "hole" that holds the
291 number of saved local registers saved by PUSHJ/PUSHGO during the
292 function call, receiving the return value at return. So best is
293 to use the highest, $31. It's already marked call-clobbered for
294 the mmixware ABI. */
295 for (i = 15; i <= 30; i++)
296 call_used_regs[i] = 0;
298 /* "Unfix" the parameter registers. */
299 for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
300 i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
301 i++)
302 fixed_regs[i] = 0;
305 /* Step over the ":" in special register names. */
306 if (! TARGET_TOPLEVEL_SYMBOLS)
307 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
308 if (reg_names[i][0] == ':')
309 reg_names[i]++;
312 /* LOCAL_REGNO.
313 All registers that are part of the register stack and that will be
314 saved are local. */
317 mmix_local_regno (regno)
318 int regno;
320 return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && !call_used_regs[regno];
323 /* PREFERRED_RELOAD_CLASS.
324 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */
326 enum reg_class
327 mmix_preferred_reload_class (x, class)
328 rtx x ATTRIBUTE_UNUSED;
329 enum reg_class class;
331 /* FIXME: Revisit. */
332 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
333 ? REMAINDER_REG : class;
336 /* PREFERRED_OUTPUT_RELOAD_CLASS.
337 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */
339 enum reg_class
340 mmix_preferred_output_reload_class (x, class)
341 rtx x ATTRIBUTE_UNUSED;
342 enum reg_class class;
344 /* FIXME: Revisit. */
345 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
346 ? REMAINDER_REG : class;
349 /* SECONDARY_RELOAD_CLASS.
350 We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere. */
352 enum reg_class
353 mmix_secondary_reload_class (class, mode, x, in_p)
354 enum reg_class class;
355 enum machine_mode mode ATTRIBUTE_UNUSED;
356 rtx x ATTRIBUTE_UNUSED;
357 int in_p ATTRIBUTE_UNUSED;
359 if (class == REMAINDER_REG
360 || class == HIMULT_REG
361 || class == SYSTEM_REGS)
362 return GENERAL_REGS;
364 return NO_REGS;
367 /* CONST_OK_FOR_LETTER_P. */
370 mmix_const_ok_for_letter_p (value, c)
371 HOST_WIDE_INT value;
372 int c;
374 return
375 (c == 'I' ? value >= 0 && value <= 255
376 : c == 'J' ? value >= 0 && value <= 65535
377 : c == 'K' ? value <= 0 && value >= -255
378 : c == 'L' ? mmix_shiftable_wyde_value (value)
379 : c == 'M' ? value == 0
380 : c == 'N' ? mmix_shiftable_wyde_value (~value)
381 : c == 'O' ? (value == 3 || value == 5 || value == 9
382 || value == 17)
383 : 0);
386 /* CONST_DOUBLE_OK_FOR_LETTER_P. */
389 mmix_const_double_ok_for_letter_p (value, c)
390 rtx value;
391 int c;
393 return
394 (c == 'G' ? value == CONST0_RTX (GET_MODE (value))
395 : 0);
398 /* EXTRA_CONSTRAINT.
399 We need this since our constants are not always expressible as
400 CONST_INT:s, but rather often as CONST_DOUBLE:s. */
403 mmix_extra_constraint (x, c, strict)
404 rtx x;
405 int c;
406 int strict;
408 HOST_WIDEST_INT value;
410 /* When checking for an address, we need to handle strict vs. non-strict
411 register checks. Don't use address_operand, but instead its
412 equivalent (its callee, which it is just a wrapper for),
413 memory_operand_p and the strict-equivalent strict_memory_address_p. */
414 if (c == 'U')
415 return
416 strict
417 ? strict_memory_address_p (Pmode, x)
418 : memory_address_p (Pmode, x);
420 /* R asks whether x is to be loaded with GETA or something else. Right
421 now, only a SYMBOL_REF and LABEL_REF can fit for
422 TARGET_BASE_ADDRESSES.
424 Only constant symbolic addresses apply. With TARGET_BASE_ADDRESSES,
425 we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG
426 set right now; only function addresses and code labels. If we change
427 to let SYMBOL_REF_FLAG be set on other symbols, we have to check
428 inside CONST expressions. When TARGET_BASE_ADDRESSES is not in
429 effect, a "raw" constant check together with mmix_constant_address_p
430 is all that's needed; we want all constant addresses to be loaded
431 with GETA then. */
432 if (c == 'R')
433 return
434 GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE
435 && mmix_constant_address_p (x)
436 && (! TARGET_BASE_ADDRESSES
437 || (GET_CODE (x) == LABEL_REF
438 || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));
440 if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)
441 return 0;
443 value = mmix_intval (x);
445 /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any
446 more ('U' taken for address_operand, 'R' similarly). Some letters map
447 outside of CONST_INT, though; we still use 'S' and 'T'. */
448 if (c == 'S')
449 return mmix_shiftable_wyde_value (value);
450 else if (c == 'T')
451 return mmix_shiftable_wyde_value (~value);
452 return 0;
455 /* DYNAMIC_CHAIN_ADDRESS. */
458 mmix_dynamic_chain_address (frame)
459 rtx frame;
461 /* FIXME: the frame-pointer is stored at offset -8 from the current
462 frame-pointer. Unfortunately, the caller assumes that a
463 frame-pointer is present for *all* previous frames. There should be
464 a way to say that that cannot be done, like for RETURN_ADDR_RTX. */
465 return plus_constant (frame, -8);
468 /* STARTING_FRAME_OFFSET. */
471 mmix_starting_frame_offset ()
473 /* The old frame pointer is in the slot below the new one, so
474 FIRST_PARM_OFFSET does not need to depend on whether the
475 frame-pointer is needed or not. We have to adjust for the register
476 stack pointer being located below the saved frame pointer.
477 Similarly, we store the return address on the stack too, for
478 exception handling, and always if we save the register stack pointer. */
479 return
481 + (MMIX_CFUN_HAS_LANDING_PAD
482 ? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0)));
485 /* RETURN_ADDR_RTX. */
488 mmix_return_addr_rtx (count, frame)
489 int count;
490 rtx frame ATTRIBUTE_UNUSED;
492 return count == 0
493 ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS
494 /* FIXME: Set frame_alias_set on the following. (Why?)
495 See mmix_initial_elimination_offset for the reason we can't use
496 get_hard_reg_initial_val for both. Always using a stack slot
497 and not a register would be suboptimal. */
498 ? validize_mem (gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, -16)))
499 : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
500 : NULL_RTX;
503 /* SETUP_FRAME_ADDRESSES. */
505 void
506 mmix_setup_frame_addresses ()
508 /* Nothing needed at the moment. */
511 /* The difference between the (imaginary) frame pointer and the stack
512 pointer. Used to eliminate the frame pointer. */
515 mmix_initial_elimination_offset (fromreg, toreg)
516 int fromreg;
517 int toreg;
519 int regno;
520 int fp_sp_offset
521 = (get_frame_size () + current_function_outgoing_args_size + 7) & ~7;
523 /* There is no actual offset between these two virtual values, but for
524 the frame-pointer, we have the old one in the stack position below
525 it, so the offset for the frame-pointer to the stack-pointer is one
526 octabyte larger. */
527 if (fromreg == MMIX_ARG_POINTER_REGNUM
528 && toreg == MMIX_FRAME_POINTER_REGNUM)
529 return 0;
531 /* The difference is the size of local variables plus the size of
532 outgoing function arguments that would normally be passed as
533 registers but must be passed on stack because we're out of
534 function-argument registers. Only global saved registers are
535 counted; the others go on the register stack.
537 The frame-pointer is counted too if it is what is eliminated, as we
538 need to balance the offset for it from STARTING_FRAME_OFFSET.
540 Also add in the slot for the register stack pointer we save if we
541 have a landing pad.
543 Unfortunately, we can't access $0..$14, from unwinder code easily, so
544 store the return address in a frame slot too. FIXME: Only for
545 non-leaf functions. FIXME: Always with a landing pad, because it's
546 hard to know whether we need the other at the time we know we need
547 the offset for one (and have to state it). It's a kludge until we
548 can express the register stack in the EH frame info.
550 We have to do alignment here; get_frame_size will not return a
551 multiple of STACK_BOUNDARY. FIXME: Add note in manual. */
553 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
554 regno <= 255;
555 regno++)
556 if ((regs_ever_live[regno] && ! call_used_regs[regno])
557 || IS_MMIX_EH_RETURN_DATA_REG (regno))
558 fp_sp_offset += 8;
560 return fp_sp_offset
561 + (MMIX_CFUN_HAS_LANDING_PAD
562 ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0))
563 + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8);
566 /* Return an rtx for a function argument to go in a register, and 0 for
567 one that must go on stack. */
570 mmix_function_arg (argsp, mode, type, named, incoming)
571 const CUMULATIVE_ARGS * argsp;
572 enum machine_mode mode;
573 tree type;
574 int named ATTRIBUTE_UNUSED;
575 int incoming;
577 /* Last-argument marker. */
578 if (type == void_type_node)
579 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
580 ? gen_rtx_REG (mode,
581 (incoming
582 ? MMIX_FIRST_INCOMING_ARG_REGNUM
583 : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
584 : NULL_RTX;
586 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
587 && !MUST_PASS_IN_STACK (mode, type)
588 && (GET_MODE_BITSIZE (mode) <= 64
589 || argsp->lib
590 || TARGET_LIBFUNC))
591 ? gen_rtx_REG (mode,
592 (incoming
593 ? MMIX_FIRST_INCOMING_ARG_REGNUM
594 : MMIX_FIRST_ARG_REGNUM)
595 + argsp->regs)
596 : NULL_RTX;
599 /* Returns nonzero for everything that goes by reference, 0 for
600 everything that goes by value. */
603 mmix_function_arg_pass_by_reference (argsp, mode, type, named)
604 const CUMULATIVE_ARGS * argsp;
605 enum machine_mode mode;
606 tree type;
607 int named ATTRIBUTE_UNUSED;
609 /* FIXME: Check: I'm not sure the MUST_PASS_IN_STACK check is
610 necessary. */
611 return
612 MUST_PASS_IN_STACK (mode, type)
613 || (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
614 && !TARGET_LIBFUNC
615 && !argsp->lib);
618 /* Return nonzero if regno is a register number where a parameter is
619 passed, and 0 otherwise. */
622 mmix_function_arg_regno_p (regno, incoming)
623 int regno;
624 int incoming;
626 int first_arg_regnum
627 = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM;
629 return regno >= first_arg_regnum
630 && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS;
633 /* FUNCTION_OUTGOING_VALUE. */
636 mmix_function_outgoing_value (valtype, func)
637 tree valtype;
638 tree func ATTRIBUTE_UNUSED;
640 enum machine_mode mode = TYPE_MODE (valtype);
641 enum machine_mode cmode;
642 int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
643 rtx vec[MMIX_MAX_REGS_FOR_VALUE];
644 int i;
645 int nregs;
647 /* Return values that fit in a register need no special handling.
648 There's no register hole when parameters are passed in global
649 registers. */
650 if (TARGET_ABI_GNU
651 || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
652 return
653 gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
655 /* A complex type, made up of components. */
656 cmode = TYPE_MODE (TREE_TYPE (valtype));
657 nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
659 /* We need to take care of the effect of the register hole on return
660 values of large sizes; the last register will appear as the first
661 register, with the rest shifted. (For complex modes, this is just
662 swapped registers.) */
664 if (nregs > MMIX_MAX_REGS_FOR_VALUE)
665 internal_error ("too large function value type, needs %d registers,\
666 have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE);
668 /* FIXME: Maybe we should handle structure values like this too
669 (adjusted for BLKmode), perhaps for both ABI:s. */
670 for (i = 0; i < nregs - 1; i++)
671 vec[i]
672 = gen_rtx_EXPR_LIST (VOIDmode,
673 gen_rtx_REG (cmode, first_val_regnum + i),
674 GEN_INT ((i + 1) * BITS_PER_UNIT));
676 vec[nregs - 1]
677 = gen_rtx_EXPR_LIST (VOIDmode,
678 gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
679 GEN_INT (0));
681 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs, vec));
684 /* FUNCTION_VALUE_REGNO_P. */
687 mmix_function_value_regno_p (regno)
688 int regno;
690 return regno == MMIX_RETURN_VALUE_REGNUM;
693 /* EH_RETURN_DATA_REGNO. */
696 mmix_eh_return_data_regno (n)
697 int n ATTRIBUTE_UNUSED;
699 if (n >= 0 && n < 4)
700 return MMIX_EH_RETURN_DATA_REGNO_START + n;
702 return INVALID_REGNUM;
705 /* EH_RETURN_STACKADJ_RTX. */
708 mmix_eh_return_stackadj_rtx ()
710 return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM);
713 /* EH_RETURN_HANDLER_RTX. */
716 mmix_eh_return_handler_rtx ()
718 return
719 gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
722 /* ASM_PREFERRED_EH_DATA_FORMAT. */
725 mmix_asm_preferred_eh_data_format (code, global)
726 int code ATTRIBUTE_UNUSED;
727 int global ATTRIBUTE_UNUSED;
729 /* This is the default (was at 2001-07-20). Revisit when needed. */
730 return DW_EH_PE_absptr;
733 /* Make a note that we've seen the beginning of the prologue. This
734 matters to whether we'll translate register numbers as calculated by
735 mmix_reorg. */
737 static void
738 mmix_target_asm_function_prologue (stream, framesize)
739 FILE *stream ATTRIBUTE_UNUSED;
740 HOST_WIDE_INT framesize ATTRIBUTE_UNUSED;
742 cfun->machine->in_prologue = 1;
745 /* Make a note that we've seen the end of the prologue. */
747 static void
748 mmix_target_asm_function_end_prologue (stream)
749 FILE *stream ATTRIBUTE_UNUSED;
751 cfun->machine->in_prologue = 0;
754 /* Implement TARGET_MACHINE_DEPENDENT_REORG. No actual rearrangements
755 done here; just virtually by calculating the highest saved stack
756 register number used to modify the register numbers at output time. */
758 static void
759 mmix_reorg ()
761 int regno;
763 /* We put the number of the highest saved register-file register in a
764 location convenient for the call-patterns to output. Note that we
765 don't tell dwarf2 about these registers, since it can't restore them
766 anyway. */
767 for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
768 regno >= 0;
769 regno--)
770 if ((regs_ever_live[regno] && !call_used_regs[regno])
771 || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
772 break;
774 /* Regardless of whether they're saved (they might be just read), we
775 mustn't include registers that carry parameters. We could scan the
776 insns to see whether they're actually used (and indeed do other less
777 trivial register usage analysis and transformations), but it seems
778 wasteful to optimize for unused parameter registers. As of
779 2002-04-30, regs_ever_live[n] seems to be set for only-reads too, but
780 that might change. */
781 if (!TARGET_ABI_GNU && regno < current_function_args_info.regs - 1)
783 regno = current_function_args_info.regs - 1;
785 /* We don't want to let this cause us to go over the limit and make
786 incoming parameter registers be misnumbered and treating the last
787 parameter register and incoming return value register call-saved.
788 Stop things at the unmodified scheme. */
789 if (regno > MMIX_RETURN_VALUE_REGNUM - 1)
790 regno = MMIX_RETURN_VALUE_REGNUM - 1;
793 cfun->machine->highest_saved_stack_register = regno;
796 /* TARGET_ASM_FUNCTION_EPILOGUE. */
798 static void
799 mmix_target_asm_function_epilogue (stream, locals_size)
800 FILE *stream;
801 HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED;
804 /* Emit an \n for readability of the generated assembly. */
805 fputc ('\n', stream);
808 /* TARGET_ASM_OUTPUT_MI_THUNK. */
810 static void
811 mmix_asm_output_mi_thunk (stream, fndecl, delta, vcall_offset, func)
812 FILE * stream;
813 tree fndecl ATTRIBUTE_UNUSED;
814 HOST_WIDE_INT delta;
815 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
816 tree func;
818 /* If you define STRUCT_VALUE to 0, rather than use STRUCT_VALUE_REGNUM,
819 (i.e. pass location of structure to return as invisible first
820 argument) you need to tweak this code too. */
821 const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
823 if (delta >= 0 && delta < 65536)
824 fprintf (stream, "\tINCL %s,%d\n", regname, (int)delta);
825 else if (delta < 0 && delta >= -255)
826 fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, (int)-delta);
827 else
829 mmix_output_register_setting (stream, 255, delta, 1);
830 fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname);
833 fprintf (stream, "\tJMP ");
834 assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
835 fprintf (stream, "\n");
838 /* FUNCTION_PROFILER. */
840 void
841 mmix_function_profiler (stream, labelno)
842 FILE *stream ATTRIBUTE_UNUSED;
843 int labelno ATTRIBUTE_UNUSED;
845 sorry ("function_profiler support for MMIX");
848 /* SETUP_INCOMING_VARARGS. */
850 void
851 mmix_setup_incoming_varargs (args_so_farp, mode, vartype, pretend_sizep,
852 second_time)
853 CUMULATIVE_ARGS * args_so_farp;
854 enum machine_mode mode;
855 tree vartype;
856 int * pretend_sizep;
857 int second_time ATTRIBUTE_UNUSED;
859 /* The last named variable has been handled, but
860 args_so_farp has not been advanced for it. */
861 if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS)
862 *pretend_sizep = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8;
864 /* We assume that one argument takes up one register here. That should
865 be true until we start messing with multi-reg parameters. */
866 if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1)
867 internal_error ("MMIX Internal: Last named vararg would not fit in a register");
870 /* EXPAND_BUILTIN_VA_ARG. */
872 /* This is modified from the "standard" implementation of va_arg: read the
873 value from the current (padded) address and increment by the (padded)
874 size. The difference for MMIX is that if the type is
875 pass-by-reference, then perform an indirection. */
878 mmix_expand_builtin_va_arg (valist, type)
879 tree valist;
880 tree type;
882 tree ptr_size = size_int (BITS_PER_WORD / BITS_PER_UNIT);
883 tree addr_tree, type_size = NULL;
884 tree align, alignm1;
885 tree rounded_size;
886 rtx addr;
888 /* Compute the rounded size of the type. */
890 /* Get AP. */
891 addr_tree = valist;
892 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
893 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
894 if (type == error_mark_node
895 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
896 || TREE_OVERFLOW (type_size))
897 /* Presumably an error; the size isn't computable. A message has
898 supposedly been emitted elsewhere. */
899 rounded_size = size_zero_node;
900 else
901 rounded_size = fold (build (MULT_EXPR, sizetype,
902 fold (build (TRUNC_DIV_EXPR, sizetype,
903 fold (build (PLUS_EXPR, sizetype,
904 type_size, alignm1)),
905 align)),
906 align));
908 if (AGGREGATE_TYPE_P (type)
909 && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) < 8
910 && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) != 0)
912 /* Adjust for big-endian the location of aggregates passed in a
913 register, but where the aggregate is accessed in a shorter mode
914 than the natural register mode (i.e. it is accessed as SFmode(?),
915 SImode, HImode or QImode rather than DImode or DFmode(?)). FIXME:
916 Or should we adjust the mode in which the aggregate is read, to be
917 a register size mode? (Hum, nah, a small offset is generally
918 cheaper than a wider memory access on MMIX.) */
919 addr_tree
920 = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
921 size_int ((BITS_PER_WORD / BITS_PER_UNIT)
922 - GET_MODE_UNIT_SIZE (TYPE_MODE (type))));
924 else if (!integer_zerop (rounded_size))
926 if (!really_constant_p (type_size))
927 /* Varying-size types come in by reference. */
928 addr_tree
929 = build1 (INDIRECT_REF, build_pointer_type (type), addr_tree);
930 else
932 /* If the size is less than a register, then we need to pad the
933 address by adding the difference. */
934 tree addend
935 = fold (build (COND_EXPR, sizetype,
936 fold (build (GT_EXPR, sizetype,
937 rounded_size,
938 align)),
939 size_zero_node,
940 fold (build (MINUS_EXPR, sizetype,
941 rounded_size,
942 type_size))));
943 tree addr_tree1
944 = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
945 addend));
947 /* If this type is larger than what fits in a register, then it
948 is passed by reference. */
949 addr_tree
950 = fold (build (COND_EXPR, TREE_TYPE (addr_tree1),
951 fold (build (GT_EXPR, sizetype,
952 rounded_size,
953 ptr_size)),
954 build1 (INDIRECT_REF, build_pointer_type (type),
955 addr_tree1),
956 addr_tree1));
960 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
961 addr = copy_to_reg (addr);
963 if (!integer_zerop (rounded_size))
965 /* Compute new value for AP. For MMIX, it is always advanced by the
966 size of a register. */
967 tree t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
968 build (PLUS_EXPR, TREE_TYPE (valist), valist,
969 ptr_size));
970 TREE_SIDE_EFFECTS (t) = 1;
971 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
974 return addr;
977 /* TRAMPOLINE_SIZE. */
978 /* Four 4-byte insns plus two 8-byte values. */
979 int mmix_trampoline_size = 32;
982 /* TRAMPOLINE_TEMPLATE. */
984 void
985 mmix_trampoline_template (stream)
986 FILE * stream;
988 /* Read a value into the static-chain register and jump somewhere. The
989 static chain is stored at offset 16, and the function address is
990 stored at offset 24. */
991 /* FIXME: GCC copies this using *intsize* (tetra), when it should use
992 register size (octa). */
993 fprintf (stream, "\tGETA $255,1F\n\t");
994 fprintf (stream, "LDOU %s,$255,0\n\t",
995 reg_names[MMIX_STATIC_CHAIN_REGNUM]);
996 fprintf (stream, "LDOU $255,$255,8\n\t");
997 fprintf (stream, "GO $255,$255,0\n");
998 fprintf (stream, "1H\tOCTA 0\n\t");
999 fprintf (stream, "OCTA 0\n");
1002 /* INITIALIZE_TRAMPOLINE. */
1003 /* Set the static chain and function pointer field in the trampoline.
1004 We also SYNCID here to be sure (doesn't matter in the simulator, but
1005 some day it will). */
1007 void
1008 mmix_initialize_trampoline (trampaddr, fnaddr, static_chain)
1009 rtx trampaddr;
1010 rtx fnaddr;
1011 rtx static_chain;
1013 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (trampaddr, 16)),
1014 static_chain);
1015 emit_move_insn (gen_rtx_MEM (DImode,
1016 plus_constant (trampaddr, 24)),
1017 fnaddr);
1018 emit_insn (gen_sync_icache (validize_mem (gen_rtx_MEM (DImode,
1019 trampaddr)),
1020 GEN_INT (mmix_trampoline_size - 1)));
1023 /* We must exclude constant addresses that have an increment that is not a
1024 multiple of four bytes because of restrictions of the GETA
1025 instruction, unless TARGET_BASE_ADDRESSES. */
1028 mmix_constant_address_p (x)
1029 rtx x;
1031 RTX_CODE code = GET_CODE (x);
1032 int addend = 0;
1033 /* When using "base addresses", anything constant goes. */
1034 int constant_ok = TARGET_BASE_ADDRESSES != 0;
1036 switch (code)
1038 case LABEL_REF:
1039 case SYMBOL_REF:
1040 return 1;
1042 case CONSTANT_P_RTX:
1043 case HIGH:
1044 /* FIXME: Don't know how to dissect these. Avoid them for now,
1045 except we know they're constants. */
1046 return constant_ok;
1048 case CONST_INT:
1049 addend = INTVAL (x);
1050 break;
1052 case CONST_DOUBLE:
1053 if (GET_MODE (x) != VOIDmode)
1054 /* Strange that we got here. FIXME: Check if we do. */
1055 return constant_ok;
1056 addend = CONST_DOUBLE_LOW (x);
1057 break;
1059 case CONST:
1060 /* Note that expressions with arithmetic on forward references don't
1061 work in mmixal. People using gcc assembly code with mmixal might
1062 need to move arrays and such to before the point of use. */
1063 if (GET_CODE (XEXP (x, 0)) == PLUS)
1065 rtx x0 = XEXP (XEXP (x, 0), 0);
1066 rtx x1 = XEXP (XEXP (x, 0), 1);
1068 if ((GET_CODE (x0) == SYMBOL_REF
1069 || GET_CODE (x0) == LABEL_REF)
1070 && (GET_CODE (x1) == CONST_INT
1071 || (GET_CODE (x1) == CONST_DOUBLE
1072 && GET_MODE (x1) == VOIDmode)))
1073 addend = mmix_intval (x1);
1074 else
1075 return constant_ok;
1077 else
1078 return constant_ok;
1079 break;
1081 default:
1082 return 0;
1085 return constant_ok || (addend & 3) == 0;
1088 /* Return 1 if the address is OK, otherwise 0.
1089 Used by GO_IF_LEGITIMATE_ADDRESS. */
1092 mmix_legitimate_address (mode, x, strict_checking)
1093 enum machine_mode mode ATTRIBUTE_UNUSED;
1094 rtx x;
1095 int strict_checking;
1097 #define MMIX_REG_OK(X) \
1098 ((strict_checking \
1099 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
1100 || (reg_renumber[REGNO (X)] > 0 \
1101 && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER))) \
1102 || (!strict_checking \
1103 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
1104 || REGNO (X) >= FIRST_PSEUDO_REGISTER \
1105 || REGNO (X) == ARG_POINTER_REGNUM)))
1107 /* We only accept:
1108 (mem reg)
1109 (mem (plus reg reg))
1110 (mem (plus reg 0..255)).
1111 unless TARGET_BASE_ADDRESSES, in which case we accept all
1112 (mem constant_address) too. */
1115 /* (mem reg) */
1116 if (REG_P (x) && MMIX_REG_OK (x))
1117 return 1;
1119 if (GET_CODE(x) == PLUS)
1121 rtx x1 = XEXP (x, 0);
1122 rtx x2 = XEXP (x, 1);
1124 /* Try swapping the order. FIXME: Do we need this? */
1125 if (! REG_P (x1))
1127 rtx tem = x1;
1128 x1 = x2;
1129 x2 = tem;
1132 /* (mem (plus (reg?) (?))) */
1133 if (!REG_P (x1) || !MMIX_REG_OK (x1))
1134 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1136 /* (mem (plus (reg) (reg?))) */
1137 if (REG_P (x2) && MMIX_REG_OK (x2))
1138 return 1;
1140 /* (mem (plus (reg) (0..255?))) */
1141 if (GET_CODE (x2) == CONST_INT
1142 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
1143 return 1;
1145 return 0;
1148 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
1151 /* LEGITIMATE_CONSTANT_P. */
1154 mmix_legitimate_constant_p (x)
1155 rtx x;
1157 RTX_CODE code = GET_CODE (x);
1159 /* We must allow any number due to the way the cse passes works; if we
1160 do not allow any number here, general_operand will fail, and insns
1161 will fatally fail recognition instead of "softly". */
1162 if (code == CONST_INT || code == CONST_DOUBLE)
1163 return 1;
1165 return CONSTANT_ADDRESS_P (x);
1168 /* SELECT_CC_MODE. */
1170 enum machine_mode
1171 mmix_select_cc_mode (op, x, y)
1172 RTX_CODE op;
1173 rtx x;
1174 rtx y ATTRIBUTE_UNUSED;
1176 /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to
1177 output different compare insns. Note that we do not check the
1178 validity of the comparison here. */
1180 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
1182 if (op == ORDERED || op == UNORDERED || op == UNGE
1183 || op == UNGT || op == UNLE || op == UNLT)
1184 return CC_FUNmode;
1186 if (op == EQ || op == NE)
1187 return CC_FPEQmode;
1189 return CC_FPmode;
1192 if (op == GTU || op == LTU || op == GEU || op == LEU)
1193 return CC_UNSmode;
1195 return CCmode;
1198 /* REVERSIBLE_CC_MODE. */
1201 mmix_reversible_cc_mode (mode)
1202 enum machine_mode mode;
1204 /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float
1205 compares. */
1206 return mode != CC_FPmode;
1209 /* TARGET_RTX_COSTS. */
1211 static bool
1212 mmix_rtx_costs (x, code, outer_code, total)
1213 rtx x ATTRIBUTE_UNUSED;
1214 int code ATTRIBUTE_UNUSED;
1215 int outer_code ATTRIBUTE_UNUSED;
1216 int *total ATTRIBUTE_UNUSED;
1218 /* For the time being, this is just a stub and we'll accept the
1219 generic calculations, until we can do measurements, at least.
1220 Say we did not modify any calculated costs. */
1221 return false;
1224 /* REGISTER_MOVE_COST. */
1227 mmix_register_move_cost (mode, from, to)
1228 enum machine_mode mode ATTRIBUTE_UNUSED;
1229 enum reg_class from;
1230 enum reg_class to;
1232 return (from == GENERAL_REGS && from == to) ? 2 : 3;
1235 /* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a
1236 compile-time constant; it's used in an asm in crtstuff.c, compiled for
1237 the target. */
1239 /* DATA_SECTION_ASM_OP. */
1241 const char *
1242 mmix_data_section_asm_op ()
1244 return "\t.data ! mmixal:= 8H LOC 9B";
1247 static void
1248 mmix_encode_section_info (decl, rtl, first)
1249 tree decl;
1250 rtx rtl;
1251 int first;
1253 /* Test for an external declaration, and do nothing if it is one. */
1254 if ((TREE_CODE (decl) == VAR_DECL
1255 && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))
1256 || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))
1258 else if (first && DECL_P (decl))
1260 /* For non-visible declarations, add a "@" prefix, which we skip
1261 when the label is output. If the label does not have this
1262 prefix, a ":" is output if -mtoplevel-symbols.
1264 Note that this does not work for data that is declared extern and
1265 later defined as static. If there's code in between, that code
1266 will refer to the extern declaration, and vice versa. This just
1267 means that when -mtoplevel-symbols is in use, we can just handle
1268 well-behaved ISO-compliant code. */
1270 const char *str = XSTR (XEXP (rtl, 0), 0);
1271 int len = strlen (str);
1272 char *newstr;
1274 /* Why is the return type of ggc_alloc_string const? */
1275 newstr = (char *) ggc_alloc_string ("", len + 1);
1277 strcpy (newstr + 1, str);
1278 *newstr = '@';
1279 XSTR (XEXP (rtl, 0), 0) = newstr;
1282 /* Set SYMBOL_REF_FLAG for things that we want to access with GETA. We
1283 may need different options to reach for different things with GETA.
1284 For now, functions and things we know or have been told are constant. */
1285 if (TREE_CODE (decl) == FUNCTION_DECL
1286 || TREE_CONSTANT (decl)
1287 || (TREE_CODE (decl) == VAR_DECL
1288 && TREE_READONLY (decl)
1289 && !TREE_SIDE_EFFECTS (decl)
1290 && (!DECL_INITIAL (decl)
1291 || TREE_CONSTANT (DECL_INITIAL (decl)))))
1292 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
1295 static const char *
1296 mmix_strip_name_encoding (name)
1297 const char *name;
1299 for (; (*name == '@' || *name == '*'); name++)
1302 return name;
1305 /* TARGET_ASM_FILE_START.
1306 We just emit a little comment for the time being. */
1308 static void
1309 mmix_file_start ()
1311 default_file_start ();
1313 fputs ("! mmixal:= 8H LOC Data_Section\n", asm_out_file);
1315 /* Make sure each file starts with the text section. */
1316 text_section ();
1319 /* TARGET_ASM_FILE_END. */
1321 static void
1322 mmix_file_end ()
1324 /* Make sure each file ends with the data section. */
1325 data_section ();
1328 /* ASM_OUTPUT_SOURCE_FILENAME. */
1330 void
1331 mmix_asm_output_source_filename (stream, name)
1332 FILE * stream;
1333 const char * name;
1335 fprintf (stream, "# 1 ");
1336 OUTPUT_QUOTED_STRING (stream, name);
1337 fprintf (stream, "\n");
1340 /* OUTPUT_QUOTED_STRING. */
1342 void
1343 mmix_output_quoted_string (stream, string, length)
1344 FILE * stream;
1345 const char * string;
1346 int length;
1348 const char * string_end = string + length;
1349 static const char *const unwanted_chars = "\"[]\\";
1351 /* Output "any character except newline and double quote character". We
1352 play it safe and avoid all control characters too. We also do not
1353 want [] as characters, should input be passed through m4 with [] as
1354 quotes. Further, we avoid "\", because the GAS port handles it as a
1355 quoting character. */
1356 while (string < string_end)
1358 if (*string
1359 && (unsigned char) *string < 128
1360 && !ISCNTRL (*string)
1361 && strchr (unwanted_chars, *string) == NULL)
1363 fputc ('"', stream);
1364 while (*string
1365 && (unsigned char) *string < 128
1366 && !ISCNTRL (*string)
1367 && strchr (unwanted_chars, *string) == NULL
1368 && string < string_end)
1370 fputc (*string, stream);
1371 string++;
1373 fputc ('"', stream);
1374 if (string < string_end)
1375 fprintf (stream, ",");
1377 if (string < string_end)
1379 fprintf (stream, "#%x", *string & 255);
1380 string++;
1381 if (string < string_end)
1382 fprintf (stream, ",");
1387 /* ASM_OUTPUT_SOURCE_LINE. */
1389 void
1390 mmix_asm_output_source_line (stream, lineno)
1391 FILE * stream;
1392 int lineno;
1394 fprintf (stream, "# %d ", lineno);
1395 OUTPUT_QUOTED_STRING (stream, main_input_filename);
1396 fprintf (stream, "\n");
1399 /* Target hook for assembling integer objects. Use mmix_print_operand
1400 for WYDE and TETRA. Use mmix_output_octa to output 8-byte
1401 CONST_DOUBLEs. */
1403 static bool
1404 mmix_assemble_integer (x, size, aligned_p)
1405 rtx x;
1406 unsigned int size;
1407 int aligned_p;
1409 if (aligned_p)
1410 switch (size)
1412 /* We handle a limited number of types of operands in here. But
1413 that's ok, because we can punt to generic functions. We then
1414 pretend that aligned data isn't needed, so the usual .<pseudo>
1415 syntax is used (which works for aligned data too). We actually
1416 *must* do that, since we say we don't have simple aligned
1417 pseudos, causing this function to be called. We just try and
1418 keep as much compatibility as possible with mmixal syntax for
1419 normal cases (i.e. without GNU extensions and C only). */
1420 case 1:
1421 if (GET_CODE (x) != CONST_INT)
1423 aligned_p = 0;
1424 break;
1426 fputs ("\tBYTE\t", asm_out_file);
1427 mmix_print_operand (asm_out_file, x, 'B');
1428 fputc ('\n', asm_out_file);
1429 return true;
1431 case 2:
1432 if (GET_CODE (x) != CONST_INT)
1434 aligned_p = 0;
1435 break;
1437 fputs ("\tWYDE\t", asm_out_file);
1438 mmix_print_operand (asm_out_file, x, 'W');
1439 fputc ('\n', asm_out_file);
1440 return true;
1442 case 4:
1443 if (GET_CODE (x) != CONST_INT)
1445 aligned_p = 0;
1446 break;
1448 fputs ("\tTETRA\t", asm_out_file);
1449 mmix_print_operand (asm_out_file, x, 'L');
1450 fputc ('\n', asm_out_file);
1451 return true;
1453 case 8:
1454 if (GET_CODE (x) == CONST_DOUBLE)
1455 /* We don't get here anymore for CONST_DOUBLE, because DImode
1456 isn't expressed as CONST_DOUBLE, and DFmode is handled
1457 elsewhere. */
1458 abort ();
1459 assemble_integer_with_op ("\tOCTA\t", x);
1460 return true;
1462 return default_assemble_integer (x, size, aligned_p);
1465 /* ASM_OUTPUT_ASCII. */
1467 void
1468 mmix_asm_output_ascii (stream, string, length)
1469 FILE *stream;
1470 const char *string;
1471 int length;
1473 while (length > 0)
1475 int chunk_size = length > 60 ? 60 : length;
1476 fprintf (stream, "\tBYTE ");
1477 mmix_output_quoted_string (stream, string, chunk_size);
1478 string += chunk_size;
1479 length -= chunk_size;
1480 fprintf (stream, "\n");
1484 /* ASM_OUTPUT_ALIGNED_COMMON. */
1486 void
1487 mmix_asm_output_aligned_common (stream, name, size, align)
1488 FILE *stream;
1489 const char *name;
1490 int size;
1491 int align;
1493 /* This is mostly the elfos.h one. There doesn't seem to be a way to
1494 express this in a mmixal-compatible way. */
1495 fprintf (stream, "\t.comm\t");
1496 assemble_name (stream, name);
1497 fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",
1498 size, align / BITS_PER_UNIT);
1501 /* ASM_OUTPUT_ALIGNED_LOCAL. */
1503 void
1504 mmix_asm_output_aligned_local (stream, name, size, align)
1505 FILE * stream;
1506 const char * name;
1507 int size;
1508 int align;
1510 data_section ();
1512 ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
1513 assemble_name (stream, name);
1514 fprintf (stream, "\tLOC @+%d\n", size);
1517 /* ASM_OUTPUT_LABEL. */
1519 void
1520 mmix_asm_output_label (stream, name)
1521 FILE *stream;
1522 const char * name;
1524 assemble_name (stream, name);
1525 fprintf (stream, "\tIS @\n");
1528 /* ASM_DECLARE_REGISTER_GLOBAL. */
1530 void
1531 mmix_asm_declare_register_global (stream, decl, regno, name)
1532 FILE *stream ATTRIBUTE_UNUSED;
1533 tree decl ATTRIBUTE_UNUSED;
1534 int regno ATTRIBUTE_UNUSED;
1535 const char *name ATTRIBUTE_UNUSED;
1537 /* Nothing to do here, but there *will* be, therefore the framework is
1538 here. */
1541 /* ASM_WEAKEN_LABEL. */
1543 void
1544 mmix_asm_weaken_label (stream, name)
1545 FILE * stream ATTRIBUTE_UNUSED;
1546 const char * name ATTRIBUTE_UNUSED;
1548 fprintf (stream, "\t.weak ");
1549 assemble_name (stream, name);
1550 fprintf (stream, " ! mmixal-incompatible\n");
1553 /* MAKE_DECL_ONE_ONLY. */
1555 void
1556 mmix_make_decl_one_only (decl)
1557 tree decl;
1559 DECL_WEAK (decl) = 1;
1562 /* ASM_OUTPUT_LABELREF.
1563 Strip GCC's '*' and our own '@'. No order is assumed. */
1565 void
1566 mmix_asm_output_labelref (stream, name)
1567 FILE *stream;
1568 const char *name;
1570 int is_extern = 1;
1572 for (; (*name == '@' || *name == '*'); name++)
1573 if (*name == '@')
1574 is_extern = 0;
1576 asm_fprintf (stream, "%s%U%s",
1577 is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
1578 name);
1581 /* ASM_OUTPUT_DEF. */
1583 void
1584 mmix_asm_output_def (stream, name, value)
1585 FILE * stream;
1586 const char * name;
1587 const char * value;
1589 assemble_name (stream, name);
1590 fprintf (stream, "\tIS ");
1591 assemble_name (stream, value);
1592 fputc ('\n', stream);
1595 /* PRINT_OPERAND. */
1597 void
1598 mmix_print_operand (stream, x, code)
1599 FILE * stream;
1600 rtx x;
1601 int code;
1603 /* When we add support for different codes later, we can, when needed,
1604 drop through to the main handler with a modified operand. */
1605 rtx modified_x = x;
1606 int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
1608 switch (code)
1610 /* Unrelated codes are in alphabetic order. */
1612 case '+':
1613 /* For conditional branches, output "P" for a probable branch. */
1614 if (TARGET_BRANCH_PREDICT)
1616 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
1617 if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)
1618 putc ('P', stream);
1620 return;
1622 case '.':
1623 /* For the %d in POP %d,0. */
1624 fprintf (stream, "%d", MMIX_POP_ARGUMENT ());
1625 return;
1627 case 'B':
1628 if (GET_CODE (x) != CONST_INT)
1629 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1630 fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
1631 return;
1633 case 'H':
1634 /* Highpart. Must be general register, and not the last one, as
1635 that one cannot be part of a consecutive register pair. */
1636 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1637 internal_error ("MMIX Internal: Bad register: %d", regno);
1639 /* This is big-endian, so the high-part is the first one. */
1640 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1641 return;
1643 case 'L':
1644 /* Lowpart. Must be CONST_INT or general register, and not the last
1645 one, as that one cannot be part of a consecutive register pair. */
1646 if (GET_CODE (x) == CONST_INT)
1648 fprintf (stream, "#%lx",
1649 (unsigned long) (INTVAL (x)
1650 & ((unsigned int) 0x7fffffff * 2 + 1)));
1651 return;
1654 if (GET_CODE (x) == SYMBOL_REF)
1656 output_addr_const (stream, x);
1657 return;
1660 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1661 internal_error ("MMIX Internal: Bad register: %d", regno);
1663 /* This is big-endian, so the low-part is + 1. */
1664 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
1665 return;
1667 /* Can't use 'a' because that's a generic modifier for address
1668 output. */
1669 case 'A':
1670 mmix_output_shiftvalue_op_from_str (stream, "ANDN",
1671 ~(unsigned HOST_WIDEST_INT)
1672 mmix_intval (x));
1673 return;
1675 case 'i':
1676 mmix_output_shiftvalue_op_from_str (stream, "INC",
1677 (unsigned HOST_WIDEST_INT)
1678 mmix_intval (x));
1679 return;
1681 case 'o':
1682 mmix_output_shiftvalue_op_from_str (stream, "OR",
1683 (unsigned HOST_WIDEST_INT)
1684 mmix_intval (x));
1685 return;
1687 case 's':
1688 mmix_output_shiftvalue_op_from_str (stream, "SET",
1689 (unsigned HOST_WIDEST_INT)
1690 mmix_intval (x));
1691 return;
1693 case 'd':
1694 case 'D':
1695 mmix_output_condition (stream, x, (code == 'D'));
1696 return;
1698 case 'e':
1699 /* Output an extra "e" to make fcmpe, fune. */
1700 if (TARGET_FCMP_EPSILON)
1701 fprintf (stream, "e");
1702 return;
1704 case 'm':
1705 /* Output the number minus 1. */
1706 if (GET_CODE (x) != CONST_INT)
1708 fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
1711 fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
1712 (HOST_WIDEST_INT) (mmix_intval (x) - 1));
1713 return;
1715 case 'p':
1716 /* Store the number of registers we want to save. This was setup
1717 by the prologue. The actual operand contains the number of
1718 registers to pass, but we don't use it currently. Anyway, we
1719 need to output the number of saved registers here. */
1720 fprintf (stream, "%d",
1721 cfun->machine->highest_saved_stack_register + 1);
1722 return;
1724 case 'r':
1725 /* Store the register to output a constant to. */
1726 if (! REG_P (x))
1727 fatal_insn ("MMIX Internal: Expected a register, not this", x);
1728 mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
1729 return;
1731 case 'I':
1732 /* Output the constant. Note that we use this for floats as well. */
1733 if (GET_CODE (x) != CONST_INT
1734 && (GET_CODE (x) != CONST_DOUBLE
1735 || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
1736 && GET_MODE (x) != SFmode)))
1737 fatal_insn ("MMIX Internal: Expected a constant, not this", x);
1738 mmix_output_register_setting (stream,
1739 mmix_output_destination_register,
1740 mmix_intval (x), 0);
1741 return;
1743 case 'U':
1744 /* An U for unsigned, if TARGET_ZERO_EXTEND. Ignore the operand. */
1745 if (TARGET_ZERO_EXTEND)
1746 putc ('U', stream);
1747 return;
1749 case 'v':
1750 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
1751 return;
1753 case 'V':
1754 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
1755 return;
1757 case 'W':
1758 if (GET_CODE (x) != CONST_INT)
1759 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1760 fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
1761 return;
1763 case 0:
1764 /* Nothing to do. */
1765 break;
1767 default:
1768 /* Presumably there's a missing case above if we get here. */
1769 internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);
1772 switch (GET_CODE (modified_x))
1774 case REG:
1775 regno = REGNO (modified_x);
1776 if (regno >= FIRST_PSEUDO_REGISTER)
1777 internal_error ("MMIX Internal: Bad register: %d", regno);
1778 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
1779 return;
1781 case MEM:
1782 output_address (XEXP (modified_x, 0));
1783 return;
1785 case CONST_INT:
1786 /* For -2147483648, mmixal complains that the constant does not fit
1787 in 4 bytes, so let's output it as hex. Take care to handle hosts
1788 where HOST_WIDE_INT is longer than an int.
1790 Print small constants +-255 using decimal. */
1792 if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
1793 fprintf (stream, "%d", (int) (INTVAL (modified_x)));
1794 else
1795 fprintf (stream, "#%x",
1796 (int) (INTVAL (modified_x)) & (unsigned int) ~0);
1797 return;
1799 case CONST_DOUBLE:
1800 /* Do somewhat as CONST_INT. */
1801 mmix_output_octa (stream, mmix_intval (modified_x), 0);
1802 return;
1804 case CONST:
1805 output_addr_const (stream, modified_x);
1806 return;
1808 default:
1809 /* No need to test for all strange things. Let output_addr_const do
1810 it for us. */
1811 if (CONSTANT_P (modified_x)
1812 /* Strangely enough, this is not included in CONSTANT_P.
1813 FIXME: Ask/check about sanity here. */
1814 || GET_CODE (modified_x) == CODE_LABEL)
1816 output_addr_const (stream, modified_x);
1817 return;
1820 /* We need the original here. */
1821 fatal_insn ("MMIX Internal: Cannot decode this operand", x);
1825 /* PRINT_OPERAND_PUNCT_VALID_P. */
1828 mmix_print_operand_punct_valid_p (code)
1829 int code ATTRIBUTE_UNUSED;
1831 /* A '+' is used for branch prediction, similar to other ports. */
1832 return code == '+'
1833 /* A '.' is used for the %d in the POP %d,0 return insn. */
1834 || code == '.';
1837 /* PRINT_OPERAND_ADDRESS. */
1839 void
1840 mmix_print_operand_address (stream, x)
1841 FILE *stream;
1842 rtx x;
1844 if (REG_P (x))
1846 /* I find the generated assembly code harder to read without
1847 the ",0". */
1848 fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
1849 return;
1851 else if (GET_CODE (x) == PLUS)
1853 rtx x1 = XEXP (x, 0);
1854 rtx x2 = XEXP (x, 1);
1856 if (REG_P (x1))
1858 fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
1860 if (REG_P (x2))
1862 fprintf (stream, "%s",
1863 reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
1864 return;
1866 else if (GET_CODE (x2) == CONST_INT
1867 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
1869 output_addr_const (stream, x2);
1870 return;
1875 if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x))
1877 output_addr_const (stream, x);
1878 return;
1881 fatal_insn ("MMIX Internal: This is not a recognized address", x);
1884 /* ASM_OUTPUT_REG_PUSH. */
1886 void
1887 mmix_asm_output_reg_push (stream, regno)
1888 FILE * stream;
1889 int regno;
1891 fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
1892 reg_names[MMIX_STACK_POINTER_REGNUM],
1893 reg_names[MMIX_STACK_POINTER_REGNUM],
1894 reg_names[MMIX_OUTPUT_REGNO (regno)],
1895 reg_names[MMIX_STACK_POINTER_REGNUM]);
1898 /* ASM_OUTPUT_REG_POP. */
1900 void
1901 mmix_asm_output_reg_pop (stream, regno)
1902 FILE * stream;
1903 int regno;
1905 fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
1906 reg_names[MMIX_OUTPUT_REGNO (regno)],
1907 reg_names[MMIX_STACK_POINTER_REGNUM],
1908 reg_names[MMIX_STACK_POINTER_REGNUM]);
1911 /* ASM_OUTPUT_ADDR_DIFF_ELT. */
1913 void
1914 mmix_asm_output_addr_diff_elt (stream, body, value, rel)
1915 FILE *stream;
1916 rtx body ATTRIBUTE_UNUSED;
1917 int value;
1918 int rel;
1920 fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
1923 /* ASM_OUTPUT_ADDR_VEC_ELT. */
1925 void
1926 mmix_asm_output_addr_vec_elt (stream, value)
1927 FILE *stream;
1928 int value;
1930 fprintf (stream, "\tOCTA L:%d\n", value);
1933 /* ASM_OUTPUT_SKIP. */
1935 void
1936 mmix_asm_output_skip (stream, nbytes)
1937 FILE *stream;
1938 int nbytes;
1940 fprintf (stream, "\tLOC @+%d\n", nbytes);
1943 /* ASM_OUTPUT_ALIGN. */
1945 void
1946 mmix_asm_output_align (stream, power)
1947 FILE *stream;
1948 int power;
1950 /* We need to record the needed alignment of this section in the object,
1951 so we have to output an alignment directive. Use a .p2align (not
1952 .align) so people will never have to wonder about whether the
1953 argument is in number of bytes or the log2 thereof. We do it in
1954 addition to the LOC directive, so nothing needs tweaking when
1955 copy-pasting assembly into mmixal. */
1956 fprintf (stream, "\t.p2align %d\n", power);
1957 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
1960 /* DBX_REGISTER_NUMBER. */
1963 mmix_dbx_register_number (regno)
1964 int regno;
1966 /* Adjust the register number to the one it will be output as, dammit.
1967 It'd be nice if we could check the assumption that we're filling a
1968 gap, but every register between the last saved register and parameter
1969 registers might be a valid parameter register. */
1970 regno = MMIX_OUTPUT_REGNO (regno);
1972 /* We need to renumber registers to get the number of the return address
1973 register in the range 0..255. It is also space-saving if registers
1974 mentioned in the call-frame information (which uses this function by
1975 defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered
1976 0 .. 63. So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48. */
1977 return regno >= 224 ? (regno - 224) : (regno + 48);
1980 /* End of target macro support functions.
1982 Now MMIX's own functions. First the exported ones. */
1984 /* Wrapper for get_hard_reg_initial_val since integrate.h isn't included
1985 from insn-emit.c. */
1988 mmix_get_hard_reg_initial_val (mode, regno)
1989 enum machine_mode mode;
1990 int regno;
1992 return get_hard_reg_initial_val (mode, regno);
1995 /* Nonzero when the function epilogue is simple enough that a single
1996 "POP %d,0" should be used even within the function. */
1999 mmix_use_simple_return ()
2001 int regno;
2003 int stack_space_to_allocate
2004 = (current_function_outgoing_args_size
2005 + current_function_pretend_args_size
2006 + get_frame_size () + 7) & ~7;
2008 if (!TARGET_USE_RETURN_INSN || !reload_completed)
2009 return 0;
2011 for (regno = 255;
2012 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2013 regno--)
2014 /* Note that we assume that the frame-pointer-register is one of these
2015 registers, in which case we don't count it here. */
2016 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2017 && regs_ever_live[regno] && !call_used_regs[regno]))
2018 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2019 return 0;
2021 if (frame_pointer_needed)
2022 stack_space_to_allocate += 8;
2024 if (MMIX_CFUN_HAS_LANDING_PAD)
2025 stack_space_to_allocate += 16;
2026 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2027 stack_space_to_allocate += 8;
2029 return stack_space_to_allocate == 0;
2033 /* Expands the function prologue into RTX. */
2035 void
2036 mmix_expand_prologue ()
2038 HOST_WIDE_INT locals_size = get_frame_size ();
2039 int regno;
2040 HOST_WIDE_INT stack_space_to_allocate
2041 = (current_function_outgoing_args_size
2042 + current_function_pretend_args_size
2043 + locals_size + 7) & ~7;
2044 HOST_WIDE_INT offset = -8;
2046 /* Add room needed to save global non-register-stack registers. */
2047 for (regno = 255;
2048 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2049 regno--)
2050 /* Note that we assume that the frame-pointer-register is one of these
2051 registers, in which case we don't count it here. */
2052 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2053 && regs_ever_live[regno] && !call_used_regs[regno]))
2054 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2055 stack_space_to_allocate += 8;
2057 /* If we do have a frame-pointer, add room for it. */
2058 if (frame_pointer_needed)
2059 stack_space_to_allocate += 8;
2061 /* If we have a non-local label, we need to be able to unwind to it, so
2062 store the current register stack pointer. Also store the return
2063 address if we do that. */
2064 if (MMIX_CFUN_HAS_LANDING_PAD)
2065 stack_space_to_allocate += 16;
2066 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2067 /* If we do have a saved return-address slot, add room for it. */
2068 stack_space_to_allocate += 8;
2070 /* Make sure we don't get an unaligned stack. */
2071 if ((stack_space_to_allocate % 8) != 0)
2072 internal_error ("stack frame not a multiple of 8 bytes: %d",
2073 stack_space_to_allocate);
2075 if (current_function_pretend_args_size)
2077 int mmix_first_vararg_reg
2078 = (MMIX_FIRST_INCOMING_ARG_REGNUM
2079 + (MMIX_MAX_ARGS_IN_REGS
2080 - current_function_pretend_args_size / 8));
2082 for (regno
2083 = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
2084 regno >= mmix_first_vararg_reg;
2085 regno--)
2087 if (offset < 0)
2089 HOST_WIDE_INT stack_chunk
2090 = stack_space_to_allocate > (256 - 8)
2091 ? (256 - 8) : stack_space_to_allocate;
2093 mmix_emit_sp_add (-stack_chunk);
2094 offset += stack_chunk;
2095 stack_space_to_allocate -= stack_chunk;
2098 /* These registers aren't actually saved (as in "will be
2099 restored"), so don't tell DWARF2 they're saved. */
2100 emit_move_insn (gen_rtx_MEM (DImode,
2101 plus_constant (stack_pointer_rtx,
2102 offset)),
2103 gen_rtx_REG (DImode, regno));
2104 offset -= 8;
2108 /* Store the frame-pointer. */
2110 if (frame_pointer_needed)
2112 rtx insn;
2114 if (offset < 0)
2116 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2117 HOST_WIDE_INT stack_chunk
2118 = stack_space_to_allocate > (256 - 8 - 8)
2119 ? (256 - 8 - 8) : stack_space_to_allocate;
2121 mmix_emit_sp_add (-stack_chunk);
2123 offset += stack_chunk;
2124 stack_space_to_allocate -= stack_chunk;
2127 insn = emit_move_insn (gen_rtx_MEM (DImode,
2128 plus_constant (stack_pointer_rtx,
2129 offset)),
2130 hard_frame_pointer_rtx);
2131 RTX_FRAME_RELATED_P (insn) = 1;
2132 insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
2133 stack_pointer_rtx,
2134 GEN_INT (offset + 8)));
2135 RTX_FRAME_RELATED_P (insn) = 1;
2136 offset -= 8;
2139 if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2141 rtx tmpreg, retreg;
2142 rtx insn;
2144 /* Store the return-address, if one is needed on the stack. We
2145 usually store it in a register when needed, but that doesn't work
2146 with -fexceptions. */
2148 if (offset < 0)
2150 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2151 HOST_WIDE_INT stack_chunk
2152 = stack_space_to_allocate > (256 - 8 - 8)
2153 ? (256 - 8 - 8) : stack_space_to_allocate;
2155 mmix_emit_sp_add (-stack_chunk);
2157 offset += stack_chunk;
2158 stack_space_to_allocate -= stack_chunk;
2161 tmpreg = gen_rtx_REG (DImode, 255);
2162 retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM);
2164 /* Dwarf2 code is confused by the use of a temporary register for
2165 storing the return address, so we have to express it as a note,
2166 which we attach to the actual store insn. */
2167 emit_move_insn (tmpreg, retreg);
2169 insn = emit_move_insn (gen_rtx_MEM (DImode,
2170 plus_constant (stack_pointer_rtx,
2171 offset)),
2172 tmpreg);
2173 RTX_FRAME_RELATED_P (insn) = 1;
2174 REG_NOTES (insn)
2175 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
2176 gen_rtx_SET (VOIDmode,
2177 gen_rtx_MEM (DImode,
2178 plus_constant (stack_pointer_rtx,
2179 offset)),
2180 retreg),
2181 REG_NOTES (insn));
2183 offset -= 8;
2185 else if (MMIX_CFUN_HAS_LANDING_PAD)
2186 offset -= 8;
2188 if (MMIX_CFUN_HAS_LANDING_PAD)
2190 /* Store the register defining the numbering of local registers, so
2191 we know how long to unwind the register stack. */
2193 if (offset < 0)
2195 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2196 HOST_WIDE_INT stack_chunk
2197 = stack_space_to_allocate > (256 - 8 - 8)
2198 ? (256 - 8 - 8) : stack_space_to_allocate;
2200 mmix_emit_sp_add (-stack_chunk);
2202 offset += stack_chunk;
2203 stack_space_to_allocate -= stack_chunk;
2206 /* We don't tell dwarf2 about this one; we just have it to unwind
2207 the register stack at landing pads. FIXME: It's a kludge because
2208 we can't describe the effect of the PUSHJ and PUSHGO insns on the
2209 register stack at the moment. Best thing would be to handle it
2210 like stack-pointer offsets. Better: some hook into dwarf2out.c
2211 to produce DW_CFA_expression:s that specify the increment of rO,
2212 and unwind it at eh_return (preferred) or at the landing pad.
2213 Then saves to $0..$G-1 could be specified through that register. */
2215 emit_move_insn (gen_rtx_REG (DImode, 255),
2216 gen_rtx_REG (DImode,
2217 MMIX_rO_REGNUM));
2218 emit_move_insn (gen_rtx_MEM (DImode,
2219 plus_constant (stack_pointer_rtx, offset)),
2220 gen_rtx_REG (DImode, 255));
2221 offset -= 8;
2224 /* After the return-address and the frame-pointer, we have the local
2225 variables. They're the ones that may have an "unaligned" size. */
2226 offset -= (locals_size + 7) & ~7;
2228 /* Now store all registers that are global, i.e. not saved by the
2229 register file machinery.
2231 It is assumed that the frame-pointer is one of these registers, so it
2232 is explicitly excluded in the count. */
2234 for (regno = 255;
2235 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2236 regno--)
2237 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2238 && regs_ever_live[regno] && ! call_used_regs[regno])
2239 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2241 rtx insn;
2243 if (offset < 0)
2245 HOST_WIDE_INT stack_chunk
2246 = (stack_space_to_allocate > (256 - offset - 8)
2247 ? (256 - offset - 8) : stack_space_to_allocate);
2249 mmix_emit_sp_add (-stack_chunk);
2250 offset += stack_chunk;
2251 stack_space_to_allocate -= stack_chunk;
2254 insn = emit_move_insn (gen_rtx_MEM (DImode,
2255 plus_constant (stack_pointer_rtx,
2256 offset)),
2257 gen_rtx_REG (DImode, regno));
2258 RTX_FRAME_RELATED_P (insn) = 1;
2259 offset -= 8;
2262 /* Finally, allocate room for outgoing args and local vars if room
2263 wasn't allocated above. */
2264 if (stack_space_to_allocate)
2265 mmix_emit_sp_add (-stack_space_to_allocate);
2268 /* Expands the function epilogue into RTX. */
2270 void
2271 mmix_expand_epilogue ()
2273 HOST_WIDE_INT locals_size = get_frame_size ();
2274 int regno;
2275 HOST_WIDE_INT stack_space_to_deallocate
2276 = (current_function_outgoing_args_size
2277 + current_function_pretend_args_size
2278 + locals_size + 7) & ~7;
2280 /* The assumption that locals_size fits in an int is asserted in
2281 mmix_expand_prologue. */
2283 /* The first address to access is beyond the outgoing_args area. */
2284 int offset = current_function_outgoing_args_size;
2286 /* Add the space for global non-register-stack registers.
2287 It is assumed that the frame-pointer register can be one of these
2288 registers, in which case it is excluded from the count when needed. */
2289 for (regno = 255;
2290 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2291 regno--)
2292 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2293 && regs_ever_live[regno] && !call_used_regs[regno])
2294 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2295 stack_space_to_deallocate += 8;
2297 /* Add in the space for register stack-pointer. If so, always add room
2298 for the saved PC. */
2299 if (MMIX_CFUN_HAS_LANDING_PAD)
2300 stack_space_to_deallocate += 16;
2301 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2302 /* If we have a saved return-address slot, add it in. */
2303 stack_space_to_deallocate += 8;
2305 /* Add in the frame-pointer. */
2306 if (frame_pointer_needed)
2307 stack_space_to_deallocate += 8;
2309 /* Make sure we don't get an unaligned stack. */
2310 if ((stack_space_to_deallocate % 8) != 0)
2311 internal_error ("stack frame not a multiple of octabyte: %d",
2312 stack_space_to_deallocate);
2314 /* We will add back small offsets to the stack pointer as we go.
2315 First, we restore all registers that are global, i.e. not saved by
2316 the register file machinery. */
2318 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
2319 regno <= 255;
2320 regno++)
2321 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2322 && regs_ever_live[regno] && !call_used_regs[regno])
2323 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2325 if (offset > 255)
2327 mmix_emit_sp_add (offset);
2328 stack_space_to_deallocate -= offset;
2329 offset = 0;
2332 emit_move_insn (gen_rtx_REG (DImode, regno),
2333 gen_rtx_MEM (DImode,
2334 plus_constant (stack_pointer_rtx,
2335 offset)));
2336 offset += 8;
2339 /* Here is where the local variables were. As in the prologue, they
2340 might be of an unaligned size. */
2341 offset += (locals_size + 7) & ~7;
2344 /* The saved register stack pointer is just below the frame-pointer
2345 register. We don't need to restore it "manually"; the POP
2346 instruction does that. */
2347 if (MMIX_CFUN_HAS_LANDING_PAD)
2348 offset += 16;
2349 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2350 /* The return-address slot is just below the frame-pointer register.
2351 We don't need to restore it because we don't really use it. */
2352 offset += 8;
2354 /* Get back the old frame-pointer-value. */
2355 if (frame_pointer_needed)
2357 if (offset > 255)
2359 mmix_emit_sp_add (offset);
2361 stack_space_to_deallocate -= offset;
2362 offset = 0;
2365 emit_move_insn (hard_frame_pointer_rtx,
2366 gen_rtx_MEM (DImode,
2367 plus_constant (stack_pointer_rtx,
2368 offset)));
2369 offset += 8;
2372 /* We do not need to restore pretended incoming args, just add back
2373 offset to sp. */
2374 if (stack_space_to_deallocate != 0)
2375 mmix_emit_sp_add (stack_space_to_deallocate);
2377 if (current_function_calls_eh_return)
2378 /* Adjust the (normal) stack-pointer to that of the receiver.
2379 FIXME: It would be nice if we could also adjust the register stack
2380 here, but we need to express it through DWARF 2 too. */
2381 emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
2382 gen_rtx_REG (DImode,
2383 MMIX_EH_RETURN_STACKADJ_REGNUM)));
2386 /* Output an optimal sequence for setting a register to a specific
2387 constant. Used in an alternative for const_ints in movdi, and when
2388 using large stack-frame offsets.
2390 Use do_begin_end to say if a line-starting TAB and newline before the
2391 first insn and after the last insn is wanted. */
2393 void
2394 mmix_output_register_setting (stream, regno, value, do_begin_end)
2395 FILE *stream;
2396 int regno;
2397 HOST_WIDEST_INT value;
2398 int do_begin_end;
2400 if (do_begin_end)
2401 fprintf (stream, "\t");
2403 if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
2405 /* First, the one-insn cases. */
2406 mmix_output_shiftvalue_op_from_str (stream, "SET",
2407 (unsigned HOST_WIDEST_INT)
2408 value);
2409 fprintf (stream, " %s,", reg_names[regno]);
2410 mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
2412 else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
2414 /* We do this to get a bit more legible assembly code. The next
2415 alternative is mostly redundant with this. */
2417 mmix_output_shiftvalue_op_from_str (stream, "SET",
2418 -(unsigned HOST_WIDEST_INT)
2419 value);
2420 fprintf (stream, " %s,", reg_names[regno]);
2421 mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
2422 fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
2423 reg_names[regno]);
2425 else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
2427 /* Slightly more expensive, the two-insn cases. */
2429 /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255)
2430 is shiftable, or any other one-insn transformation of the value.
2431 FIXME: Check first if the value is "shiftable" by two loading
2432 with two insns, since it makes more readable assembly code (if
2433 anyone else cares). */
2435 mmix_output_shiftvalue_op_from_str (stream, "SET",
2436 ~(unsigned HOST_WIDEST_INT)
2437 value);
2438 fprintf (stream, " %s,", reg_names[regno]);
2439 mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
2440 fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
2441 reg_names[regno]);
2443 else
2445 /* The generic case. 2..4 insns. */
2446 static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
2447 const char *op = "SET";
2448 const char *line_begin = "";
2449 int insns = 0;
2450 int i;
2451 HOST_WIDEST_INT tmpvalue = value;
2453 /* Compute the number of insns needed to output this constant. */
2454 for (i = 0; i < 4 && tmpvalue != 0; i++)
2456 if (tmpvalue & 65535)
2457 insns++;
2458 tmpvalue >>= 16;
2460 if (TARGET_BASE_ADDRESSES && insns == 3)
2462 /* The number three is based on a static observation on
2463 ghostscript-6.52. Two and four are excluded because there
2464 are too many such constants, and each unique constant (maybe
2465 offset by 1..255) were used few times compared to other uses,
2466 e.g. addresses.
2468 We use base-plus-offset addressing to force it into a global
2469 register; we just use a "LDA reg,VALUE", which will cause the
2470 assembler and linker to DTRT (for constants as well as
2471 addresses). */
2472 fprintf (stream, "LDA %s,", reg_names[regno]);
2473 mmix_output_octa (stream, value, 0);
2475 else
2477 /* Output pertinent parts of the 4-wyde sequence.
2478 Still more to do if we want this to be optimal, but hey...
2479 Note that the zero case has been handled above. */
2480 for (i = 0; i < 4 && value != 0; i++)
2482 if (value & 65535)
2484 fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
2485 higher_parts[i], reg_names[regno],
2486 (int) (value & 65535));
2487 /* The first one sets the rest of the bits to 0, the next
2488 ones add set bits. */
2489 op = "INC";
2490 line_begin = "\n\t";
2493 value >>= 16;
2498 if (do_begin_end)
2499 fprintf (stream, "\n");
2502 /* Return 1 if value is 0..65535*2**(16*N) for N=0..3.
2503 else return 0. */
2506 mmix_shiftable_wyde_value (value)
2507 unsigned HOST_WIDEST_INT value;
2509 /* Shift by 16 bits per group, stop when we've found two groups with
2510 nonzero bits. */
2511 int i;
2512 int has_candidate = 0;
2514 for (i = 0; i < 4; i++)
2516 if (value & 65535)
2518 if (has_candidate)
2519 return 0;
2520 else
2521 has_candidate = 1;
2524 value >>= 16;
2527 return 1;
2530 /* True if this is an address_operand or a symbolic operand. */
2533 mmix_symbolic_or_address_operand (op, mode)
2534 rtx op;
2535 enum machine_mode mode;
2537 switch (GET_CODE (op))
2539 case SYMBOL_REF:
2540 case LABEL_REF:
2541 return 1;
2542 case CONST:
2543 op = XEXP (op, 0);
2544 if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
2545 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
2546 && (GET_CODE (XEXP (op, 1)) == CONST_INT
2547 || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
2548 && GET_MODE (XEXP (op, 1)) == VOIDmode)))
2549 return 1;
2550 /* FALLTHROUGH */
2551 default:
2552 return address_operand (op, mode);
2556 /* True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
2557 We could narrow the value down with a couple of predicated, but that
2558 doesn't seem to be worth it at the moment. */
2561 mmix_reg_or_constant_operand (op, mode)
2562 rtx op;
2563 enum machine_mode mode;
2565 return register_operand (op, mode)
2566 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
2567 || GET_CODE (op) == CONST_INT;
2570 /* True if this is a register with a condition-code mode. */
2573 mmix_reg_cc_operand (op, mode)
2574 rtx op;
2575 enum machine_mode mode;
2577 if (mode == VOIDmode)
2578 mode = GET_MODE (op);
2580 return register_operand (op, mode)
2581 && (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
2582 || mode == CC_FPEQmode || mode == CC_FUNmode);
2585 /* True if this is a foldable comparison operator
2586 - one where a the result of (compare:CC (reg) (const_int 0)) can be
2587 replaced by (reg). */
2590 mmix_foldable_comparison_operator (op, mode)
2591 rtx op;
2592 enum machine_mode mode;
2594 RTX_CODE code = GET_CODE (op);
2596 if (mode == VOIDmode)
2597 mode = GET_MODE (op);
2599 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2600 mode = GET_MODE (XEXP (op, 0));
2602 return ((mode == CCmode || mode == DImode)
2603 && (code == NE || code == EQ || code == GE || code == GT
2604 || code == LE))
2605 /* FIXME: This may be a stupid trick. What happens when GCC wants to
2606 reverse the condition? Can it do that by itself? Maybe it can
2607 even reverse the condition to fit a foldable one in the first
2608 place? */
2609 || (mode == CC_UNSmode && (code == GTU || code == LEU));
2612 /* Like comparison_operator, but only true if this comparison operator is
2613 applied to a valid mode. Needed to avoid jump.c generating invalid
2614 code with -ffast-math (gcc.dg/20001228-1.c). */
2617 mmix_comparison_operator (op, mode)
2618 rtx op;
2619 enum machine_mode mode;
2621 RTX_CODE code = GET_CODE (op);
2623 /* Comparison operators usually don't have a mode, but let's try and get
2624 one anyway for the day that changes. */
2625 if (mode == VOIDmode)
2626 mode = GET_MODE (op);
2628 /* Get the mode from the first operand if we don't have one. */
2629 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2630 mode = GET_MODE (XEXP (op, 0));
2632 /* FIXME: This needs to be kept in sync with the tables in
2633 mmix_output_condition. */
2634 return
2635 (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2636 || (mode == CC_FUNmode
2637 && (code == ORDERED || code == UNORDERED))
2638 || (mode == CC_FPmode
2639 && (code == GT || code == LT))
2640 || (mode == CC_FPEQmode
2641 && (code == NE || code == EQ))
2642 || (mode == CC_UNSmode
2643 && (code == GEU || code == GTU || code == LEU || code == LTU))
2644 || (mode == CCmode
2645 && (code == NE || code == EQ || code == GE || code == GT
2646 || code == LE || code == LT))
2647 || (mode == DImode
2648 && (code == NE || code == EQ || code == GE || code == GT
2649 || code == LE || code == LT || code == LEU || code == GTU));
2652 /* True if this is a register or 0 (int or float). */
2655 mmix_reg_or_0_operand (op, mode)
2656 rtx op;
2657 enum machine_mode mode;
2659 /* FIXME: Is mode calculation necessary and correct? */
2660 return
2661 op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
2662 || register_operand (op, mode);
2665 /* True if this is a register or an int 0..255. */
2668 mmix_reg_or_8bit_operand (op, mode)
2669 rtx op;
2670 enum machine_mode mode;
2672 return register_operand (op, mode)
2673 || (GET_CODE (op) == CONST_INT
2674 && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
2677 /* Returns zero if code and mode is not a valid condition from a
2678 compare-type insn. Nonzero if it is. The parameter op, if non-NULL,
2679 is the comparison of mode is CC-somethingmode. */
2682 mmix_valid_comparison (code, mode, op)
2683 RTX_CODE code;
2684 enum machine_mode mode;
2685 rtx op;
2687 if (mode == VOIDmode && op != NULL_RTX)
2688 mode = GET_MODE (op);
2690 /* We don't care to look at these, they should always be valid. */
2691 if (mode == CCmode || mode == CC_UNSmode || mode == DImode)
2692 return 1;
2694 if ((mode == CC_FPmode || mode == DFmode)
2695 && (code == GT || code == LT))
2696 return 1;
2698 if ((mode == CC_FPEQmode || mode == DFmode)
2699 && (code == EQ || code == NE))
2700 return 1;
2702 if ((mode == CC_FUNmode || mode == DFmode)
2703 && (code == ORDERED || code == UNORDERED))
2704 return 1;
2706 return 0;
2709 /* X and Y are two things to compare using CODE. Emit a compare insn if
2710 possible and return the rtx for the cc-reg in the proper mode, or
2711 NULL_RTX if this is not a valid comparison. */
2714 mmix_gen_compare_reg (code, x, y)
2715 RTX_CODE code;
2716 rtx x, y;
2718 enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
2719 rtx cc_reg;
2721 /* FIXME: Do we get constants here? Of double mode? */
2722 enum machine_mode mode
2723 = GET_MODE (x) == VOIDmode
2724 ? GET_MODE (y)
2725 : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode;
2727 if (! mmix_valid_comparison (code, mode, x))
2728 return NULL_RTX;
2730 cc_reg = gen_reg_rtx (ccmode);
2732 /* FIXME: Can we avoid emitting a compare insn here? */
2733 if (! REG_P (x) && ! REG_P (y))
2734 x = force_reg (mode, x);
2736 /* If it's not quite right yet, put y in a register. */
2737 if (! REG_P (y)
2738 && (GET_CODE (y) != CONST_INT
2739 || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I')))
2740 y = force_reg (mode, y);
2742 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
2743 gen_rtx_COMPARE (ccmode, x, y)));
2745 return cc_reg;
2748 /* Local (static) helper functions. */
2750 static void
2751 mmix_emit_sp_add (offset)
2752 HOST_WIDE_INT offset;
2754 rtx insn;
2756 if (offset < 0)
2758 /* Negative stack-pointer adjustments are allocations and appear in
2759 the prologue only. We mark them as frame-related so unwind and
2760 debug info is properly emitted for them. */
2761 if (offset > -255)
2762 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2763 stack_pointer_rtx,
2764 GEN_INT (offset)));
2765 else
2767 rtx tmpr = gen_rtx_REG (DImode, 255);
2768 RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1;
2769 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2770 stack_pointer_rtx, tmpr));
2772 RTX_FRAME_RELATED_P (insn) = 1;
2774 else
2776 /* Positive adjustments are in the epilogue only. Don't mark them
2777 as "frame-related" for unwind info. */
2778 if (CONST_OK_FOR_LETTER_P (offset, 'L'))
2779 emit_insn (gen_adddi3 (stack_pointer_rtx,
2780 stack_pointer_rtx,
2781 GEN_INT (offset)));
2782 else
2784 rtx tmpr = gen_rtx_REG (DImode, 255);
2785 emit_move_insn (tmpr, GEN_INT (offset));
2786 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2787 stack_pointer_rtx, tmpr));
2792 /* Print operator suitable for doing something with a shiftable
2793 wyde. The type of operator is passed as an asm output modifier. */
2795 static void
2796 mmix_output_shiftvalue_op_from_str (stream, mainop, value)
2797 FILE *stream;
2798 const char *mainop;
2799 HOST_WIDEST_INT value;
2801 static const char *const op_part[] = {"L", "ML", "MH", "H"};
2802 int i;
2804 if (! mmix_shiftable_wyde_value (value))
2806 char s[sizeof ("0xffffffffffffffff")];
2807 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
2808 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2811 for (i = 0; i < 4; i++)
2813 /* We know we're through when we find one-bits in the low
2814 16 bits. */
2815 if (value & 0xffff)
2817 fprintf (stream, "%s%s", mainop, op_part[i]);
2818 return;
2820 value >>= 16;
2823 /* No bits set? Then it must have been zero. */
2824 fprintf (stream, "%sL", mainop);
2827 /* Print a 64-bit value, optionally prefixed by assembly pseudo. */
2829 static void
2830 mmix_output_octa (stream, value, do_begin_end)
2831 FILE *stream;
2832 HOST_WIDEST_INT value;
2833 int do_begin_end;
2835 /* Snipped from final.c:output_addr_const. We need to avoid the
2836 presumed universal "0x" prefix. We can do it by replacing "0x" with
2837 "#0" here; we must avoid a space in the operands and no, the zero
2838 won't cause the number to be assumed in octal format. */
2839 char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)];
2841 if (do_begin_end)
2842 fprintf (stream, "\tOCTA ");
2844 strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX);
2845 hex_format[0] = '#';
2846 hex_format[1] = '0';
2848 /* Provide a few alternative output formats depending on the number, to
2849 improve legibility of assembler output. */
2850 if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
2851 || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
2852 fprintf (stream, "%d", (int) value);
2853 else if (value > (HOST_WIDEST_INT) 0
2854 && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
2855 fprintf (stream, "#%x", (unsigned int) value);
2856 else
2857 fprintf (stream, hex_format, value);
2859 if (do_begin_end)
2860 fprintf (stream, "\n");
2863 /* Print the presumed shiftable wyde argument shifted into place (to
2864 be output with an operand). */
2866 static void
2867 mmix_output_shifted_value (stream, value)
2868 FILE * stream;
2869 HOST_WIDEST_INT value;
2871 int i;
2873 if (! mmix_shiftable_wyde_value (value))
2875 char s[16+2+1];
2876 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
2877 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2880 for (i = 0; i < 4; i++)
2882 /* We know we're through when we find one-bits in the low 16 bits. */
2883 if (value & 0xffff)
2885 fprintf (stream, "#%x", (int) (value & 0xffff));
2886 return;
2889 value >>= 16;
2892 /* No bits set? Then it must have been zero. */
2893 fprintf (stream, "0");
2896 /* Output an MMIX condition name corresponding to an operator
2897 and operands:
2898 (comparison_operator [(comparison_operator ...) (const_int 0)])
2899 which means we have to look at *two* operators.
2901 The argument "reversed" refers to reversal of the condition (not the
2902 same as swapping the arguments). */
2904 static void
2905 mmix_output_condition (stream, x, reversed)
2906 FILE *stream;
2907 rtx x;
2908 int reversed;
2910 struct cc_conv
2912 RTX_CODE cc;
2914 /* The normal output cc-code. */
2915 const char *const normal;
2917 /* The reversed cc-code, or NULL if invalid. */
2918 const char *const reversed;
2921 struct cc_type_conv
2923 enum machine_mode cc_mode;
2925 /* Terminated with {NIL, NULL, NULL} */
2926 const struct cc_conv *const convs;
2929 #undef CCEND
2930 #define CCEND {NIL, NULL, NULL}
2932 static const struct cc_conv cc_fun_convs[]
2933 = {{ORDERED, "Z", "P"},
2934 {UNORDERED, "P", "Z"},
2935 CCEND};
2936 static const struct cc_conv cc_fp_convs[]
2937 = {{GT, "P", NULL},
2938 {LT, "N", NULL},
2939 CCEND};
2940 static const struct cc_conv cc_fpeq_convs[]
2941 = {{NE, "Z", "P"},
2942 {EQ, "P", "Z"},
2943 CCEND};
2944 static const struct cc_conv cc_uns_convs[]
2945 = {{GEU, "NN", "N"},
2946 {GTU, "P", "NP"},
2947 {LEU, "NP", "P"},
2948 {LTU, "N", "NN"},
2949 CCEND};
2950 static const struct cc_conv cc_signed_convs[]
2951 = {{NE, "NZ", "Z"},
2952 {EQ, "Z", "NZ"},
2953 {GE, "NN", "N"},
2954 {GT, "P", "NP"},
2955 {LE, "NP", "P"},
2956 {LT, "N", "NN"},
2957 CCEND};
2958 static const struct cc_conv cc_di_convs[]
2959 = {{NE, "NZ", "Z"},
2960 {EQ, "Z", "NZ"},
2961 {GE, "NN", "N"},
2962 {GT, "P", "NP"},
2963 {LE, "NP", "P"},
2964 {LT, "N", "NN"},
2965 {GTU, "NZ", "Z"},
2966 {LEU, "Z", "NZ"},
2967 CCEND};
2968 #undef CCEND
2970 static const struct cc_type_conv cc_convs[]
2971 = {{CC_FUNmode, cc_fun_convs},
2972 {CC_FPmode, cc_fp_convs},
2973 {CC_FPEQmode, cc_fpeq_convs},
2974 {CC_UNSmode, cc_uns_convs},
2975 {CCmode, cc_signed_convs},
2976 {DImode, cc_di_convs}};
2978 size_t i;
2979 int j;
2981 enum machine_mode mode = GET_MODE (XEXP (x, 0));
2982 RTX_CODE cc = GET_CODE (x);
2984 for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
2986 if (mode == cc_convs[i].cc_mode)
2988 for (j = 0; cc_convs[i].convs[j].cc != NIL; j++)
2989 if (cc == cc_convs[i].convs[j].cc)
2991 const char *mmix_cc
2992 = (reversed ? cc_convs[i].convs[j].reversed
2993 : cc_convs[i].convs[j].normal);
2995 if (mmix_cc == NULL)
2996 fatal_insn ("MMIX Internal: Trying to output invalidly\
2997 reversed condition:", x);
2999 fprintf (stream, "%s", mmix_cc);
3000 return;
3003 fatal_insn ("MMIX Internal: What's the CC of this?", x);
3007 fatal_insn ("MMIX Internal: What is the CC of this?", x);
3010 /* Return the bit-value for a const_int or const_double. */
3012 static HOST_WIDEST_INT
3013 mmix_intval (x)
3014 rtx x;
3016 unsigned HOST_WIDEST_INT retval;
3018 if (GET_CODE (x) == CONST_INT)
3019 return INTVAL (x);
3021 /* We make a little song and dance because converting to long long in
3022 gcc-2.7.2 is broken. I still want people to be able to use it for
3023 cross-compilation to MMIX. */
3024 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
3026 if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
3028 retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
3029 retval *= 2;
3030 retval |= CONST_DOUBLE_LOW (x) & 1;
3032 retval |=
3033 (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
3034 << (HOST_BITS_PER_LONG);
3036 else
3037 retval = CONST_DOUBLE_HIGH (x);
3039 return retval;
3042 if (GET_CODE (x) == CONST_DOUBLE)
3044 REAL_VALUE_TYPE value;
3046 /* FIXME: This macro is not in the manual but should be. */
3047 REAL_VALUE_FROM_CONST_DOUBLE (value, x);
3049 if (GET_MODE (x) == DFmode)
3051 long bits[2];
3053 REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
3055 if (sizeof (long) < sizeof (HOST_WIDEST_INT))
3057 retval = (unsigned long) bits[1] / 2;
3058 retval *= 2;
3059 retval |= (unsigned long) bits[1] & 1;
3060 retval
3061 |= (unsigned HOST_WIDEST_INT) bits[0]
3062 << (sizeof (bits[0]) * 8);
3064 else
3065 retval = (unsigned long) bits[1];
3067 return retval;
3069 else if (GET_MODE (x) == SFmode)
3071 long bits;
3072 REAL_VALUE_TO_TARGET_SINGLE (value, bits);
3074 return (unsigned long) bits;
3078 fatal_insn ("MMIX Internal: This is not a constant:", x);
3082 * Local variables:
3083 * eval: (c-set-style "gnu")
3084 * indent-tabs-mode: t
3085 * End: