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