]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/mmix/mmix.c
Daily bump.
[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
28c2d844 696/* Make a note that we've seen the beginning of the prologue. This
d3310704 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
4448bfa5 763static void
68cbb7e3 764mmix_target_asm_function_epilogue (stream, locals_size)
765 FILE *stream;
4448bfa5 766 HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED;
68cbb7e3 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)
7fe1d31c 788 fprintf (stream, "\tINCL %s,%d\n", regname, delta);
d3310704 789 else if (delta < 0 && delta >= -255)
7fe1d31c 790 fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, -delta);
d3310704 791 else
0b123c47 792 {
d3310704 793 mmix_output_register_setting (stream, 255, delta, 1);
7fe1d31c 794 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
68cbb7e3 1523/* ASM_WEAKEN_LABEL. */
1524
1525void
1526mmix_asm_weaken_label (stream, name)
1527 FILE * stream ATTRIBUTE_UNUSED;
1528 const char * name ATTRIBUTE_UNUSED;
1529{
7fe1d31c 1530 fprintf (stream, "\t.weak ");
68cbb7e3 1531 assemble_name (stream, name);
7fe1d31c 1532 fprintf (stream, " ! mmixal-incompatible\n");
68cbb7e3 1533}
1534
1535/* MAKE_DECL_ONE_ONLY. */
1536
1537void
1538mmix_make_decl_one_only (decl)
1539 tree decl;
1540{
1541 DECL_WEAK (decl) = 1;
1542}
1543
1544/* ASM_OUTPUT_LABELREF.
1545 Strip GCC's '*' and our own '@'. No order is assumed. */
1546
1547void
1548mmix_asm_output_labelref (stream, name)
1549 FILE *stream;
1550 const char *name;
1551{
91009d64 1552 int is_extern = 1;
68cbb7e3 1553
1554 for (; (*name == '@' || *name == '*'); name++)
1555 if (*name == '@')
91009d64 1556 is_extern = 0;
68cbb7e3 1557
1558 asm_fprintf (stream, "%s%U%s",
1559 is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
1560 name);
1561}
1562
1563/* ASM_OUTPUT_INTERNAL_LABEL. */
1564
1565void
1566mmix_asm_output_internal_label (stream, name, num)
1567 FILE * stream;
1568 const char * name;
1569 int num;
1570{
1571 fprintf (stream, "%s:%d\tIS @\n", name, num);
1572}
1573
1574/* ASM_OUTPUT_DEF. */
1575
1576void
1577mmix_asm_output_def (stream, name, value)
1578 FILE * stream;
1579 const char * name;
1580 const char * value;
1581{
1582 assemble_name (stream, name);
1583 fprintf (stream, "\tIS ");
1584 assemble_name (stream, value);
1585 fputc ('\n', stream);
1586}
1587
68cbb7e3 1588/* PRINT_OPERAND. */
1589
1590void
1591mmix_print_operand (stream, x, code)
1592 FILE * stream;
1593 rtx x;
1594 int code;
1595{
1596 /* When we add support for different codes later, we can, when needed,
1597 drop through to the main handler with a modified operand. */
1598 rtx modified_x = x;
d68ffc6f 1599 int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
68cbb7e3 1600
1601 switch (code)
1602 {
1603 /* Unrelated codes are in alphabetic order. */
1604
91009d64 1605 case '+':
1606 /* For conditional branches, output "P" for a probable branch. */
1607 if (TARGET_BRANCH_PREDICT)
1608 {
1609 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
1610 if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)
1611 putc ('P', stream);
1612 }
1613 return;
1614
0b123c47 1615 case '.':
1616 /* For the %d in POP %d,0. */
1617 fprintf (stream, "%d", MMIX_POP_ARGUMENT ());
1618 return;
1619
68cbb7e3 1620 case 'B':
1621 if (GET_CODE (x) != CONST_INT)
1622 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1623 fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
1624 return;
1625
1626 case 'H':
1627 /* Highpart. Must be general register, and not the last one, as
1628 that one cannot be part of a consecutive register pair. */
d68ffc6f 1629 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1630 internal_error ("MMIX Internal: Bad register: %d", regno);
68cbb7e3 1631
1632 /* This is big-endian, so the high-part is the first one. */
d68ffc6f 1633 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
68cbb7e3 1634 return;
1635
1636 case 'L':
1637 /* Lowpart. Must be CONST_INT or general register, and not the last
1638 one, as that one cannot be part of a consecutive register pair. */
1639 if (GET_CODE (x) == CONST_INT)
1640 {
1641 fprintf (stream, "#%lx",
1642 (unsigned long) (INTVAL (x)
1643 & ((unsigned int) 0x7fffffff * 2 + 1)));
1644 return;
1645 }
1646
1647 if (GET_CODE (x) == SYMBOL_REF)
1648 {
1649 output_addr_const (stream, x);
1650 return;
1651 }
1652
d68ffc6f 1653 if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
1654 internal_error ("MMIX Internal: Bad register: %d", regno);
68cbb7e3 1655
1656 /* This is big-endian, so the low-part is + 1. */
d68ffc6f 1657 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
68cbb7e3 1658 return;
1659
1660 /* Can't use 'a' because that's a generic modifier for address
1661 output. */
1662 case 'A':
1663 mmix_output_shiftvalue_op_from_str (stream, "ANDN",
1664 ~(unsigned HOST_WIDEST_INT)
1665 mmix_intval (x));
1666 return;
1667
1668 case 'i':
1669 mmix_output_shiftvalue_op_from_str (stream, "INC",
1670 (unsigned HOST_WIDEST_INT)
1671 mmix_intval (x));
1672 return;
1673
1674 case 'o':
1675 mmix_output_shiftvalue_op_from_str (stream, "OR",
1676 (unsigned HOST_WIDEST_INT)
1677 mmix_intval (x));
1678 return;
1679
1680 case 's':
1681 mmix_output_shiftvalue_op_from_str (stream, "SET",
1682 (unsigned HOST_WIDEST_INT)
1683 mmix_intval (x));
1684 return;
1685
1686 case 'd':
1687 case 'D':
1688 mmix_output_condition (stream, x, (code == 'D'));
1689 return;
1690
1691 case 'e':
1692 /* Output an extra "e" to make fcmpe, fune. */
1693 if (TARGET_FCMP_EPSILON)
1694 fprintf (stream, "e");
1695 return;
1696
1697 case 'm':
1698 /* Output the number minus 1. */
1699 if (GET_CODE (x) != CONST_INT)
1700 {
1701 fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
1702 x);
1703 }
1704 fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
1705 (HOST_WIDEST_INT) (mmix_intval (x) - 1));
1706 return;
1707
1708 case 'p':
1709 /* Store the number of registers we want to save. This was setup
1710 by the prologue. The actual operand contains the number of
1711 registers to pass, but we don't use it currently. Anyway, we
1712 need to output the number of saved registers here. */
d68ffc6f 1713 fprintf (stream, "%d",
1714 cfun->machine->highest_saved_stack_register + 1);
68cbb7e3 1715 return;
1716
1717 case 'r':
1718 /* Store the register to output a constant to. */
1719 if (! REG_P (x))
68435912 1720 fatal_insn ("MMIX Internal: Expected a register, not this", x);
d68ffc6f 1721 mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
68cbb7e3 1722 return;
1723
1724 case 'I':
1725 /* Output the constant. Note that we use this for floats as well. */
1726 if (GET_CODE (x) != CONST_INT
1727 && (GET_CODE (x) != CONST_DOUBLE
1728 || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
1729 && GET_MODE (x) != SFmode)))
68435912 1730 fatal_insn ("MMIX Internal: Expected a constant, not this", x);
68cbb7e3 1731 mmix_output_register_setting (stream,
1732 mmix_output_destination_register,
1733 mmix_intval (x), 0);
1734 return;
1735
1736 case 'U':
1737 /* An U for unsigned, if TARGET_ZERO_EXTEND. Ignore the operand. */
1738 if (TARGET_ZERO_EXTEND)
1739 putc ('U', stream);
1740 return;
1741
1742 case 'v':
1743 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
1744 return;
1745
1746 case 'V':
1747 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
1748 return;
1749
1750 case 'W':
1751 if (GET_CODE (x) != CONST_INT)
1752 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
1753 fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
1754 return;
1755
1756 case 0:
1757 /* Nothing to do. */
1758 break;
1759
1760 default:
1761 /* Presumably there's a missing case above if we get here. */
1762 internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);
1763 }
1764
1765 switch (GET_CODE (modified_x))
1766 {
1767 case REG:
d68ffc6f 1768 regno = REGNO (modified_x);
1769 if (regno >= FIRST_PSEUDO_REGISTER)
1770 internal_error ("MMIX Internal: Bad register: %d", regno);
1771 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
68cbb7e3 1772 return;
1773
1774 case MEM:
1775 output_address (XEXP (modified_x, 0));
1776 return;
1777
1778 case CONST_INT:
1779 /* For -2147483648, mmixal complains that the constant does not fit
1780 in 4 bytes, so let's output it as hex. Take care to handle hosts
1781 where HOST_WIDE_INT is longer than an int.
1782
1783 Print small constants +-255 using decimal. */
1784
1785 if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
1786 fprintf (stream, "%d", (int) (INTVAL (modified_x)));
1787 else
1788 fprintf (stream, "#%x",
1789 (int) (INTVAL (modified_x)) & (unsigned int) ~0);
1790 return;
1791
1792 case CONST_DOUBLE:
1793 /* Do somewhat as CONST_INT. */
58356836 1794 mmix_output_octa (stream, mmix_intval (modified_x), 0);
68cbb7e3 1795 return;
1796
1797 case CONST:
1798 output_addr_const (stream, modified_x);
1799 return;
1800
1801 default:
1802 /* No need to test for all strange things. Let output_addr_const do
1803 it for us. */
1804 if (CONSTANT_P (modified_x)
1805 /* Strangely enough, this is not included in CONSTANT_P.
1806 FIXME: Ask/check about sanity here. */
1807 || GET_CODE (modified_x) == CODE_LABEL)
1808 {
1809 output_addr_const (stream, modified_x);
1810 return;
1811 }
1812
1813 /* We need the original here. */
1814 fatal_insn ("MMIX Internal: Cannot decode this operand", x);
1815 }
1816}
1817
1818/* PRINT_OPERAND_PUNCT_VALID_P. */
1819
1820int
1821mmix_print_operand_punct_valid_p (code)
1822 int code ATTRIBUTE_UNUSED;
1823{
91009d64 1824 /* A '+' is used for branch prediction, similar to other ports. */
0b123c47 1825 return code == '+'
1826 /* A '.' is used for the %d in the POP %d,0 return insn. */
1827 || code == '.';
68cbb7e3 1828}
1829
1830/* PRINT_OPERAND_ADDRESS. */
1831
1832void
1833mmix_print_operand_address (stream, x)
1834 FILE *stream;
1835 rtx x;
1836{
1837 if (REG_P (x))
1838 {
1839 /* I find the generated assembly code harder to read without
1840 the ",0". */
d68ffc6f 1841 fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
68cbb7e3 1842 return;
1843 }
1844 else if (GET_CODE (x) == PLUS)
1845 {
1846 rtx x1 = XEXP (x, 0);
1847 rtx x2 = XEXP (x, 1);
1848
68cbb7e3 1849 if (REG_P (x1))
1850 {
d68ffc6f 1851 fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
68cbb7e3 1852
1853 if (REG_P (x2))
1854 {
d68ffc6f 1855 fprintf (stream, "%s",
1856 reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
68cbb7e3 1857 return;
1858 }
1859 else if (GET_CODE (x2) == CONST_INT
1860 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
1861 {
1862 output_addr_const (stream, x2);
1863 return;
1864 }
1865 }
1866 }
1867
f0b228a5 1868 if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x))
1869 {
1870 output_addr_const (stream, x);
1871 return;
1872 }
1873
68cbb7e3 1874 fatal_insn ("MMIX Internal: This is not a recognized address", x);
1875}
1876
1877/* ASM_OUTPUT_REG_PUSH. */
1878
1879void
1880mmix_asm_output_reg_push (stream, regno)
1881 FILE * stream;
1882 int regno;
1883{
1884 fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
1885 reg_names[MMIX_STACK_POINTER_REGNUM],
1886 reg_names[MMIX_STACK_POINTER_REGNUM],
d68ffc6f 1887 reg_names[MMIX_OUTPUT_REGNO (regno)],
68cbb7e3 1888 reg_names[MMIX_STACK_POINTER_REGNUM]);
1889}
1890
1891/* ASM_OUTPUT_REG_POP. */
1892
1893void
1894mmix_asm_output_reg_pop (stream, regno)
1895 FILE * stream;
1896 int regno;
1897{
1898 fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
d68ffc6f 1899 reg_names[MMIX_OUTPUT_REGNO (regno)],
68cbb7e3 1900 reg_names[MMIX_STACK_POINTER_REGNUM],
1901 reg_names[MMIX_STACK_POINTER_REGNUM]);
1902}
1903
1904/* ASM_OUTPUT_ADDR_DIFF_ELT. */
1905
1906void
1907mmix_asm_output_addr_diff_elt (stream, body, value, rel)
1908 FILE *stream;
1909 rtx body ATTRIBUTE_UNUSED;
1910 int value;
1911 int rel;
1912{
1913 fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
1914}
1915
1916/* ASM_OUTPUT_ADDR_VEC_ELT. */
1917
1918void
1919mmix_asm_output_addr_vec_elt (stream, value)
1920 FILE *stream;
1921 int value;
1922{
1923 fprintf (stream, "\tOCTA L:%d\n", value);
1924}
1925
1926/* ASM_OUTPUT_SKIP. */
1927
1928void
1929mmix_asm_output_skip (stream, nbytes)
1930 FILE *stream;
1931 int nbytes;
1932{
1933 fprintf (stream, "\tLOC @+%d\n", nbytes);
1934}
1935
1936/* ASM_OUTPUT_ALIGN. */
1937
1938void
1939mmix_asm_output_align (stream, power)
1940 FILE *stream;
1941 int power;
1942{
1943 /* We need to record the needed alignment of this section in the object,
1944 so we have to output an alignment directive. Use a .p2align (not
1945 .align) so people will never have to wonder about whether the
1946 argument is in number of bytes or the log2 thereof. We do it in
1947 addition to the LOC directive, so nothing needs tweaking when
1948 copy-pasting assembly into mmixal. */
1949 fprintf (stream, "\t.p2align %d\n", power);
1950 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
1951}
1952
1953/* DBX_REGISTER_NUMBER. */
1954
1955int
1956mmix_dbx_register_number (regno)
1957 int regno;
1958{
d68ffc6f 1959 /* Adjust the register number to the one it will be output as, dammit.
1960 It'd be nice if we could check the assumption that we're filling a
1961 gap, but every register between the last saved register and parameter
1962 registers might be a valid parameter register. */
1963 regno = MMIX_OUTPUT_REGNO (regno);
68cbb7e3 1964
1965 /* We need to renumber registers to get the number of the return address
1966 register in the range 0..255. It is also space-saving if registers
1967 mentioned in the call-frame information (which uses this function by
1968 defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered
1969 0 .. 63. So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48. */
1970 return regno >= 224 ? (regno - 224) : (regno + 48);
1971}
1972
35a3065a 1973/* End of target macro support functions.
68cbb7e3 1974
1975 Now MMIX's own functions. First the exported ones. */
1976
d3310704 1977/* Wrapper for get_hard_reg_initial_val since integrate.h isn't included
1978 from insn-emit.c. */
1979
1980rtx
1981mmix_get_hard_reg_initial_val (mode, regno)
1982 enum machine_mode mode;
1983 int regno;
1984{
1985 return get_hard_reg_initial_val (mode, regno);
1986}
1987
e911aedf 1988/* Nonzero when the function epilogue is simple enough that a single
d3310704 1989 "POP %d,0" should be used even within the function. */
0b123c47 1990
1991int
1992mmix_use_simple_return ()
1993{
1994 int regno;
1995
1996 int stack_space_to_allocate
1997 = (current_function_outgoing_args_size
1998 + current_function_pretend_args_size
1999 + get_frame_size () + 7) & ~7;
2000
2001 if (!TARGET_USE_RETURN_INSN || !reload_completed)
2002 return 0;
2003
2004 for (regno = 255;
2005 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2006 regno--)
2007 /* Note that we assume that the frame-pointer-register is one of these
2008 registers, in which case we don't count it here. */
2009 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2010 && regs_ever_live[regno] && !call_used_regs[regno]))
2011 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2012 return 0;
2013
2014 if (frame_pointer_needed)
2015 stack_space_to_allocate += 8;
2016
2017 if (MMIX_CFUN_HAS_LANDING_PAD)
2018 stack_space_to_allocate += 16;
2019 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2020 stack_space_to_allocate += 8;
2021
2022 return stack_space_to_allocate == 0;
2023}
2024
d3310704 2025
2026/* Expands the function prologue into RTX. */
2027
2028void
2029mmix_expand_prologue ()
2030{
2031 HOST_WIDE_INT locals_size = get_frame_size ();
2032 int regno;
2033 HOST_WIDE_INT stack_space_to_allocate
2034 = (current_function_outgoing_args_size
2035 + current_function_pretend_args_size
2036 + locals_size + 7) & ~7;
2037 HOST_WIDE_INT offset = -8;
2038
2039 /* Add room needed to save global non-register-stack registers. */
2040 for (regno = 255;
2041 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2042 regno--)
2043 /* Note that we assume that the frame-pointer-register is one of these
2044 registers, in which case we don't count it here. */
2045 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2046 && regs_ever_live[regno] && !call_used_regs[regno]))
2047 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2048 stack_space_to_allocate += 8;
2049
2050 /* If we do have a frame-pointer, add room for it. */
2051 if (frame_pointer_needed)
2052 stack_space_to_allocate += 8;
2053
2054 /* If we have a non-local label, we need to be able to unwind to it, so
2055 store the current register stack pointer. Also store the return
2056 address if we do that. */
2057 if (MMIX_CFUN_HAS_LANDING_PAD)
2058 stack_space_to_allocate += 16;
2059 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2060 /* If we do have a saved return-address slot, add room for it. */
2061 stack_space_to_allocate += 8;
2062
2063 /* Make sure we don't get an unaligned stack. */
2064 if ((stack_space_to_allocate % 8) != 0)
2065 internal_error ("stack frame not a multiple of 8 bytes: %d",
2066 stack_space_to_allocate);
2067
2068 if (current_function_pretend_args_size)
2069 {
2070 int mmix_first_vararg_reg
2071 = (MMIX_FIRST_INCOMING_ARG_REGNUM
2072 + (MMIX_MAX_ARGS_IN_REGS
2073 - current_function_pretend_args_size / 8));
2074
2075 for (regno
2076 = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
2077 regno >= mmix_first_vararg_reg;
2078 regno--)
2079 {
2080 if (offset < 0)
2081 {
2082 HOST_WIDE_INT stack_chunk
2083 = stack_space_to_allocate > (256 - 8)
2084 ? (256 - 8) : stack_space_to_allocate;
2085
2086 mmix_emit_sp_add (-stack_chunk);
2087 offset += stack_chunk;
2088 stack_space_to_allocate -= stack_chunk;
2089 }
2090
2091 /* These registers aren't actually saved (as in "will be
2092 restored"), so don't tell DWARF2 they're saved. */
2093 emit_move_insn (gen_rtx_MEM (DImode,
2094 plus_constant (stack_pointer_rtx,
2095 offset)),
2096 gen_rtx_REG (DImode, regno));
2097 offset -= 8;
2098 }
2099 }
2100
2101 /* Store the frame-pointer. */
2102
2103 if (frame_pointer_needed)
2104 {
2105 rtx insn;
2106
2107 if (offset < 0)
2108 {
2109 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2110 HOST_WIDE_INT stack_chunk
2111 = stack_space_to_allocate > (256 - 8 - 8)
2112 ? (256 - 8 - 8) : stack_space_to_allocate;
2113
2114 mmix_emit_sp_add (-stack_chunk);
2115
2116 offset += stack_chunk;
2117 stack_space_to_allocate -= stack_chunk;
2118 }
2119
2120 insn = emit_move_insn (gen_rtx_MEM (DImode,
2121 plus_constant (stack_pointer_rtx,
2122 offset)),
2123 hard_frame_pointer_rtx);
2124 RTX_FRAME_RELATED_P (insn) = 1;
2125 insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
2126 stack_pointer_rtx,
2127 GEN_INT (offset + 8)));
2128 RTX_FRAME_RELATED_P (insn) = 1;
2129 offset -= 8;
2130 }
2131
2132 if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2133 {
2134 rtx tmpreg, retreg;
2135 rtx insn;
2136
2137 /* Store the return-address, if one is needed on the stack. We
2138 usually store it in a register when needed, but that doesn't work
2139 with -fexceptions. */
2140
2141 if (offset < 0)
2142 {
2143 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2144 HOST_WIDE_INT stack_chunk
2145 = stack_space_to_allocate > (256 - 8 - 8)
2146 ? (256 - 8 - 8) : stack_space_to_allocate;
2147
2148 mmix_emit_sp_add (-stack_chunk);
2149
2150 offset += stack_chunk;
2151 stack_space_to_allocate -= stack_chunk;
2152 }
2153
2154 tmpreg = gen_rtx_REG (DImode, 255);
2155 retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM);
2156
2157 /* Dwarf2 code is confused by the use of a temporary register for
2158 storing the return address, so we have to express it as a note,
2159 which we attach to the actual store insn. */
2160 emit_move_insn (tmpreg, retreg);
2161
2162 insn = emit_move_insn (gen_rtx_MEM (DImode,
2163 plus_constant (stack_pointer_rtx,
2164 offset)),
2165 tmpreg);
2166 RTX_FRAME_RELATED_P (insn) = 1;
2167 REG_NOTES (insn)
2168 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
2169 gen_rtx_SET (VOIDmode,
2170 gen_rtx_MEM (DImode,
2171 plus_constant (stack_pointer_rtx,
2172 offset)),
2173 retreg),
2174 REG_NOTES (insn));
2175
2176 offset -= 8;
2177 }
2178 else if (MMIX_CFUN_HAS_LANDING_PAD)
2179 offset -= 8;
2180
2181 if (MMIX_CFUN_HAS_LANDING_PAD)
2182 {
2183 /* Store the register defining the numbering of local registers, so
2184 we know how long to unwind the register stack. */
2185
2186 if (offset < 0)
2187 {
2188 /* Get 8 less than otherwise, since we need to reach offset + 8. */
2189 HOST_WIDE_INT stack_chunk
2190 = stack_space_to_allocate > (256 - 8 - 8)
2191 ? (256 - 8 - 8) : stack_space_to_allocate;
2192
2193 mmix_emit_sp_add (-stack_chunk);
2194
2195 offset += stack_chunk;
2196 stack_space_to_allocate -= stack_chunk;
2197 }
2198
2199 /* We don't tell dwarf2 about this one; we just have it to unwind
2200 the register stack at landing pads. FIXME: It's a kludge because
2201 we can't describe the effect of the PUSHJ and PUSHGO insns on the
2202 register stack at the moment. Best thing would be to handle it
2203 like stack-pointer offsets. Better: some hook into dwarf2out.c
2204 to produce DW_CFA_expression:s that specify the increment of rO,
2205 and unwind it at eh_return (preferred) or at the landing pad.
2206 Then saves to $0..$G-1 could be specified through that register. */
2207
2208 emit_move_insn (gen_rtx_REG (DImode, 255),
2209 gen_rtx_REG (DImode,
2210 MMIX_rO_REGNUM));
2211 emit_move_insn (gen_rtx_MEM (DImode,
2212 plus_constant (stack_pointer_rtx, offset)),
2213 gen_rtx_REG (DImode, 255));
2214 offset -= 8;
2215 }
2216
2217 /* After the return-address and the frame-pointer, we have the local
2218 variables. They're the ones that may have an "unaligned" size. */
2219 offset -= (locals_size + 7) & ~7;
2220
2221 /* Now store all registers that are global, i.e. not saved by the
2222 register file machinery.
2223
2224 It is assumed that the frame-pointer is one of these registers, so it
2225 is explicitly excluded in the count. */
2226
2227 for (regno = 255;
2228 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2229 regno--)
2230 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2231 && regs_ever_live[regno] && ! call_used_regs[regno])
2232 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2233 {
2234 rtx insn;
2235
2236 if (offset < 0)
2237 {
2238 HOST_WIDE_INT stack_chunk
2239 = (stack_space_to_allocate > (256 - offset - 8)
2240 ? (256 - offset - 8) : stack_space_to_allocate);
2241
2242 mmix_emit_sp_add (-stack_chunk);
2243 offset += stack_chunk;
2244 stack_space_to_allocate -= stack_chunk;
2245 }
2246
2247 insn = emit_move_insn (gen_rtx_MEM (DImode,
2248 plus_constant (stack_pointer_rtx,
2249 offset)),
2250 gen_rtx_REG (DImode, regno));
2251 RTX_FRAME_RELATED_P (insn) = 1;
2252 offset -= 8;
2253 }
2254
2255 /* Finally, allocate room for outgoing args and local vars if room
2256 wasn't allocated above. */
2257 if (stack_space_to_allocate)
2258 mmix_emit_sp_add (-stack_space_to_allocate);
2259}
2260
2261/* Expands the function epilogue into RTX. */
2262
2263void
2264mmix_expand_epilogue ()
2265{
2266 HOST_WIDE_INT locals_size = get_frame_size ();
2267 int regno;
2268 HOST_WIDE_INT stack_space_to_deallocate
2269 = (current_function_outgoing_args_size
2270 + current_function_pretend_args_size
2271 + locals_size + 7) & ~7;
2272
2273 /* The assumption that locals_size fits in an int is asserted in
2274 mmix_expand_prologue. */
2275
2276 /* The first address to access is beyond the outgoing_args area. */
2277 int offset = current_function_outgoing_args_size;
2278
2279 /* Add the space for global non-register-stack registers.
2280 It is assumed that the frame-pointer register can be one of these
2281 registers, in which case it is excluded from the count when needed. */
2282 for (regno = 255;
2283 regno >= MMIX_FIRST_GLOBAL_REGNUM;
2284 regno--)
2285 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2286 && regs_ever_live[regno] && !call_used_regs[regno])
2287 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2288 stack_space_to_deallocate += 8;
2289
2290 /* Add in the space for register stack-pointer. If so, always add room
2291 for the saved PC. */
2292 if (MMIX_CFUN_HAS_LANDING_PAD)
2293 stack_space_to_deallocate += 16;
2294 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2295 /* If we have a saved return-address slot, add it in. */
2296 stack_space_to_deallocate += 8;
2297
2298 /* Add in the frame-pointer. */
2299 if (frame_pointer_needed)
2300 stack_space_to_deallocate += 8;
2301
2302 /* Make sure we don't get an unaligned stack. */
2303 if ((stack_space_to_deallocate % 8) != 0)
2304 internal_error ("stack frame not a multiple of octabyte: %d",
2305 stack_space_to_deallocate);
2306
2307 /* We will add back small offsets to the stack pointer as we go.
2308 First, we restore all registers that are global, i.e. not saved by
2309 the register file machinery. */
2310
2311 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
2312 regno <= 255;
2313 regno++)
2314 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
2315 && regs_ever_live[regno] && !call_used_regs[regno])
2316 || IS_MMIX_EH_RETURN_DATA_REG (regno))
2317 {
2318 if (offset > 255)
2319 {
2320 mmix_emit_sp_add (offset);
2321 stack_space_to_deallocate -= offset;
2322 offset = 0;
2323 }
2324
2325 emit_move_insn (gen_rtx_REG (DImode, regno),
2326 gen_rtx_MEM (DImode,
2327 plus_constant (stack_pointer_rtx,
2328 offset)));
2329 offset += 8;
2330 }
2331
2332 /* Here is where the local variables were. As in the prologue, they
2333 might be of an unaligned size. */
2334 offset += (locals_size + 7) & ~7;
2335
2336
2337 /* The saved register stack pointer is just below the frame-pointer
2338 register. We don't need to restore it "manually"; the POP
2339 instruction does that. */
2340 if (MMIX_CFUN_HAS_LANDING_PAD)
2341 offset += 16;
2342 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
2343 /* The return-address slot is just below the frame-pointer register.
2344 We don't need to restore it because we don't really use it. */
2345 offset += 8;
2346
2347 /* Get back the old frame-pointer-value. */
2348 if (frame_pointer_needed)
2349 {
2350 if (offset > 255)
2351 {
2352 mmix_emit_sp_add (offset);
2353
2354 stack_space_to_deallocate -= offset;
2355 offset = 0;
2356 }
2357
2358 emit_move_insn (hard_frame_pointer_rtx,
2359 gen_rtx_MEM (DImode,
2360 plus_constant (stack_pointer_rtx,
2361 offset)));
2362 offset += 8;
2363 }
2364
2365 /* We do not need to restore pretended incoming args, just add back
2366 offset to sp. */
2367 if (stack_space_to_deallocate != 0)
2368 mmix_emit_sp_add (stack_space_to_deallocate);
2369
2370 if (current_function_calls_eh_return)
2371 /* Adjust the (normal) stack-pointer to that of the receiver.
2372 FIXME: It would be nice if we could also adjust the register stack
2373 here, but we need to express it through DWARF 2 too. */
2374 emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
2375 gen_rtx_REG (DImode,
2376 MMIX_EH_RETURN_STACKADJ_REGNUM)));
2377}
2378
68cbb7e3 2379/* Output an optimal sequence for setting a register to a specific
2380 constant. Used in an alternative for const_ints in movdi, and when
2381 using large stack-frame offsets.
2382
2383 Use do_begin_end to say if a line-starting TAB and newline before the
2384 first insn and after the last insn is wanted. */
2385
2386void
2387mmix_output_register_setting (stream, regno, value, do_begin_end)
2388 FILE *stream;
2389 int regno;
2390 HOST_WIDEST_INT value;
2391 int do_begin_end;
2392{
2393 if (do_begin_end)
2394 fprintf (stream, "\t");
2395
2396 if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
2397 {
2398 /* First, the one-insn cases. */
2399 mmix_output_shiftvalue_op_from_str (stream, "SET",
2400 (unsigned HOST_WIDEST_INT)
2401 value);
2402 fprintf (stream, " %s,", reg_names[regno]);
2403 mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
2404 }
2405 else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
2406 {
2407 /* We do this to get a bit more legible assembly code. The next
2408 alternative is mostly redundant with this. */
2409
2410 mmix_output_shiftvalue_op_from_str (stream, "SET",
2411 -(unsigned HOST_WIDEST_INT)
2412 value);
2413 fprintf (stream, " %s,", reg_names[regno]);
2414 mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
2415 fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
2416 reg_names[regno]);
2417 }
2418 else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
2419 {
2420 /* Slightly more expensive, the two-insn cases. */
2421
2422 /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255)
2423 is shiftable, or any other one-insn transformation of the value.
2424 FIXME: Check first if the value is "shiftable" by two loading
2425 with two insns, since it makes more readable assembly code (if
2426 anyone else cares). */
2427
2428 mmix_output_shiftvalue_op_from_str (stream, "SET",
2429 ~(unsigned HOST_WIDEST_INT)
2430 value);
2431 fprintf (stream, " %s,", reg_names[regno]);
2432 mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
2433 fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
2434 reg_names[regno]);
2435 }
2436 else
2437 {
2438 /* The generic case. 2..4 insns. */
25037517 2439 static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
68cbb7e3 2440 const char *op = "SET";
2441 const char *line_begin = "";
f0b228a5 2442 int insns = 0;
68cbb7e3 2443 int i;
f0b228a5 2444 HOST_WIDEST_INT tmpvalue = value;
68cbb7e3 2445
f0b228a5 2446 /* Compute the number of insns needed to output this constant. */
2447 for (i = 0; i < 4 && tmpvalue != 0; i++)
2448 {
2449 if (tmpvalue & 65535)
2450 insns++;
2451 tmpvalue >>= 16;
2452 }
2453 if (TARGET_BASE_ADDRESSES && insns == 3)
2454 {
2455 /* The number three is based on a static observation on
2456 ghostscript-6.52. Two and four are excluded because there
2457 are too many such constants, and each unique constant (maybe
2458 offset by 1..255) were used few times compared to other uses,
2459 e.g. addresses.
2460
2461 We use base-plus-offset addressing to force it into a global
2462 register; we just use a "LDA reg,VALUE", which will cause the
2463 assembler and linker to DTRT (for constants as well as
2464 addresses). */
2465 fprintf (stream, "LDA %s,", reg_names[regno]);
2466 mmix_output_octa (stream, value, 0);
2467 }
2468 else
68cbb7e3 2469 {
f0b228a5 2470 /* Output pertinent parts of the 4-wyde sequence.
2471 Still more to do if we want this to be optimal, but hey...
2472 Note that the zero case has been handled above. */
2473 for (i = 0; i < 4 && value != 0; i++)
68cbb7e3 2474 {
f0b228a5 2475 if (value & 65535)
2476 {
2477 fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
2478 higher_parts[i], reg_names[regno],
2479 (int) (value & 65535));
2480 /* The first one sets the rest of the bits to 0, the next
2481 ones add set bits. */
2482 op = "INC";
2483 line_begin = "\n\t";
2484 }
68cbb7e3 2485
f0b228a5 2486 value >>= 16;
2487 }
68cbb7e3 2488 }
2489 }
2490
2491 if (do_begin_end)
2492 fprintf (stream, "\n");
2493}
2494
2495/* Return 1 if value is 0..65535*2**(16*N) for N=0..3.
2496 else return 0. */
2497
2498int
2499mmix_shiftable_wyde_value (value)
2500 unsigned HOST_WIDEST_INT value;
2501{
2502 /* Shift by 16 bits per group, stop when we've found two groups with
2503 nonzero bits. */
2504 int i;
2505 int has_candidate = 0;
2506
2507 for (i = 0; i < 4; i++)
2508 {
2509 if (value & 65535)
2510 {
2511 if (has_candidate)
2512 return 0;
2513 else
2514 has_candidate = 1;
2515 }
2516
2517 value >>= 16;
2518 }
2519
2520 return 1;
2521}
2522
2523/* True if this is an address_operand or a symbolic operand. */
2524
2525int
2526mmix_symbolic_or_address_operand (op, mode)
2527 rtx op;
2528 enum machine_mode mode;
2529{
2530 switch (GET_CODE (op))
2531 {
2532 case SYMBOL_REF:
2533 case LABEL_REF:
2534 return 1;
2535 case CONST:
2536 op = XEXP (op, 0);
2537 if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
2538 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
2539 && (GET_CODE (XEXP (op, 1)) == CONST_INT
2540 || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
2541 && GET_MODE (XEXP (op, 1)) == VOIDmode)))
2542 return 1;
2543 /* FALLTHROUGH */
2544 default:
2545 return address_operand (op, mode);
2546 }
2547}
2548
2549/* True if this is a register or CONST_INT (or CONST_DOUBLE for DImode).
2550 We could narrow the value down with a couple of predicated, but that
2551 doesn't seem to be worth it at the moment. */
2552
2553int
2554mmix_reg_or_constant_operand (op, mode)
2555 rtx op;
2556 enum machine_mode mode;
2557{
2558 return register_operand (op, mode)
2559 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
2560 || GET_CODE (op) == CONST_INT;
2561}
2562
2563/* True if this is a register with a condition-code mode. */
2564
2565int
2566mmix_reg_cc_operand (op, mode)
2567 rtx op;
2568 enum machine_mode mode;
2569{
2570 if (mode == VOIDmode)
2571 mode = GET_MODE (op);
2572
2573 return register_operand (op, mode)
2574 && (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
2575 || mode == CC_FPEQmode || mode == CC_FUNmode);
2576}
2577
2578/* True if this is a foldable comparison operator
2579 - one where a the result of (compare:CC (reg) (const_int 0)) can be
2580 replaced by (reg). */
2581
2582int
2583mmix_foldable_comparison_operator (op, mode)
2584 rtx op;
2585 enum machine_mode mode;
2586{
2587 RTX_CODE code = GET_CODE (op);
2588
2589 if (mode == VOIDmode)
2590 mode = GET_MODE (op);
2591
2592 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2593 mode = GET_MODE (XEXP (op, 0));
2594
2595 return ((mode == CCmode || mode == DImode)
2596 && (code == NE || code == EQ || code == GE || code == GT
2597 || code == LE))
2598 /* FIXME: This may be a stupid trick. What happens when GCC wants to
2599 reverse the condition? Can it do that by itself? Maybe it can
2600 even reverse the condition to fit a foldable one in the first
2601 place? */
2602 || (mode == CC_UNSmode && (code == GTU || code == LEU));
2603}
2604
2605/* Like comparison_operator, but only true if this comparison operator is
2606 applied to a valid mode. Needed to avoid jump.c generating invalid
2607 code with -ffast-math (gcc.dg/20001228-1.c). */
2608
2609int
2610mmix_comparison_operator (op, mode)
2611 rtx op;
2612 enum machine_mode mode;
2613{
2614 RTX_CODE code = GET_CODE (op);
2615
2616 /* Comparison operators usually don't have a mode, but let's try and get
2617 one anyway for the day that changes. */
2618 if (mode == VOIDmode)
2619 mode = GET_MODE (op);
2620
2621 /* Get the mode from the first operand if we don't have one. */
2622 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2623 mode = GET_MODE (XEXP (op, 0));
2624
2625 /* FIXME: This needs to be kept in sync with the tables in
2626 mmix_output_condition. */
2627 return
2628 (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
2629 || (mode == CC_FUNmode
2630 && (code == ORDERED || code == UNORDERED))
2631 || (mode == CC_FPmode
2632 && (code == GT || code == LT))
2633 || (mode == CC_FPEQmode
2634 && (code == NE || code == EQ))
2635 || (mode == CC_UNSmode
2636 && (code == GEU || code == GTU || code == LEU || code == LTU))
2637 || (mode == CCmode
2638 && (code == NE || code == EQ || code == GE || code == GT
2639 || code == LE || code == LT))
2640 || (mode == DImode
2641 && (code == NE || code == EQ || code == GE || code == GT
2642 || code == LE || code == LT || code == LEU || code == GTU));
2643}
2644
2645/* True if this is a register or 0 (int or float). */
2646
2647int
2648mmix_reg_or_0_operand (op, mode)
2649 rtx op;
2650 enum machine_mode mode;
2651{
2652 /* FIXME: Is mode calculation necessary and correct? */
2653 return
2654 op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
2655 || register_operand (op, mode);
2656}
2657
2658/* True if this is a register or an int 0..255. */
2659
2660int
2661mmix_reg_or_8bit_operand (op, mode)
2662 rtx op;
2663 enum machine_mode mode;
2664{
2665 return register_operand (op, mode)
2666 || (GET_CODE (op) == CONST_INT
2667 && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
2668}
2669
68cbb7e3 2670/* Returns zero if code and mode is not a valid condition from a
2671 compare-type insn. Nonzero if it is. The parameter op, if non-NULL,
2672 is the comparison of mode is CC-somethingmode. */
2673
2674int
2675mmix_valid_comparison (code, mode, op)
2676 RTX_CODE code;
2677 enum machine_mode mode;
2678 rtx op;
2679{
2680 if (mode == VOIDmode && op != NULL_RTX)
2681 mode = GET_MODE (op);
2682
2683 /* We don't care to look at these, they should always be valid. */
2684 if (mode == CCmode || mode == CC_UNSmode || mode == DImode)
2685 return 1;
2686
2687 if ((mode == CC_FPmode || mode == DFmode)
2688 && (code == GT || code == LT))
2689 return 1;
2690
2691 if ((mode == CC_FPEQmode || mode == DFmode)
2692 && (code == EQ || code == NE))
2693 return 1;
2694
2695 if ((mode == CC_FUNmode || mode == DFmode)
2696 && (code == ORDERED || code == UNORDERED))
2697 return 1;
2698
2699 return 0;
2700}
2701
2702/* X and Y are two things to compare using CODE. Emit a compare insn if
2703 possible and return the rtx for the cc-reg in the proper mode, or
2704 NULL_RTX if this is not a valid comparison. */
2705
2706rtx
2707mmix_gen_compare_reg (code, x, y)
2708 RTX_CODE code;
2709 rtx x, y;
2710{
2711 enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
2712 rtx cc_reg;
2713
2714 /* FIXME: Do we get constants here? Of double mode? */
2715 enum machine_mode mode
2716 = GET_MODE (x) == VOIDmode
2717 ? GET_MODE (y)
2718 : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode;
2719
2720 if (! mmix_valid_comparison (code, mode, x))
2721 return NULL_RTX;
2722
2723 cc_reg = gen_reg_rtx (ccmode);
2724
2725 /* FIXME: Can we avoid emitting a compare insn here? */
2726 if (! REG_P (x) && ! REG_P (y))
2727 x = force_reg (mode, x);
2728
68cbb7e3 2729 /* If it's not quite right yet, put y in a register. */
2730 if (! REG_P (y)
2731 && (GET_CODE (y) != CONST_INT
2732 || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I')))
2733 y = force_reg (mode, y);
2734
2735 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
2736 gen_rtx_COMPARE (ccmode, x, y)));
2737
2738 return cc_reg;
2739}
2740
2741/* Local (static) helper functions. */
2742
d3310704 2743static void
2744mmix_emit_sp_add (offset)
2745 HOST_WIDE_INT offset;
2746{
2747 rtx insn;
2748
2749 if (offset < 0)
2750 {
2751 /* Negative stack-pointer adjustments are allocations and appear in
2752 the prologue only. We mark them as frame-related so unwind and
2753 debug info is properly emitted for them. */
2754 if (offset > -255)
2755 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2756 stack_pointer_rtx,
2757 GEN_INT (offset)));
2758 else
2759 {
2760 rtx tmpr = gen_rtx_REG (DImode, 255);
2761 RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1;
2762 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2763 stack_pointer_rtx, tmpr));
2764 }
2765 RTX_FRAME_RELATED_P (insn) = 1;
2766 }
2767 else
2768 {
2769 /* Positive adjustments are in the epilogue only. Don't mark them
2770 as "frame-related" for unwind info. */
2771 if (CONST_OK_FOR_LETTER_P (offset, 'L'))
2772 emit_insn (gen_adddi3 (stack_pointer_rtx,
2773 stack_pointer_rtx,
2774 GEN_INT (offset)));
2775 else
2776 {
2777 rtx tmpr = gen_rtx_REG (DImode, 255);
2778 emit_move_insn (tmpr, GEN_INT (offset));
2779 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
2780 stack_pointer_rtx, tmpr));
2781 }
2782 }
2783}
2784
68cbb7e3 2785/* Print operator suitable for doing something with a shiftable
ebb11c7b 2786 wyde. The type of operator is passed as an asm output modifier. */
68cbb7e3 2787
2788static void
2789mmix_output_shiftvalue_op_from_str (stream, mainop, value)
2790 FILE *stream;
2791 const char *mainop;
2792 HOST_WIDEST_INT value;
2793{
25037517 2794 static const char *const op_part[] = {"L", "ML", "MH", "H"};
68cbb7e3 2795 int i;
2796
2797 if (! mmix_shiftable_wyde_value (value))
2798 {
2799 char s[sizeof ("0xffffffffffffffff")];
2800 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
2801 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2802 }
2803
2804 for (i = 0; i < 4; i++)
2805 {
2806 /* We know we're through when we find one-bits in the low
2807 16 bits. */
2808 if (value & 0xffff)
2809 {
2810 fprintf (stream, "%s%s", mainop, op_part[i]);
2811 return;
2812 }
2813 value >>= 16;
2814 }
2815
2816 /* No bits set? Then it must have been zero. */
2817 fprintf (stream, "%sL", mainop);
2818}
2819
2820/* Print a 64-bit value, optionally prefixed by assembly pseudo. */
2821
2822static void
2823mmix_output_octa (stream, value, do_begin_end)
2824 FILE *stream;
2825 HOST_WIDEST_INT value;
2826 int do_begin_end;
2827{
2828 /* Snipped from final.c:output_addr_const. We need to avoid the
2829 presumed universal "0x" prefix. We can do it by replacing "0x" with
2830 "#0" here; we must avoid a space in the operands and no, the zero
2831 won't cause the number to be assumed in octal format. */
2832 char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)];
2833
2834 if (do_begin_end)
2835 fprintf (stream, "\tOCTA ");
2836
2837 strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX);
2838 hex_format[0] = '#';
2839 hex_format[1] = '0';
2840
2841 /* Provide a few alternative output formats depending on the number, to
2842 improve legibility of assembler output. */
2843 if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
2844 || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
2845 fprintf (stream, "%d", (int) value);
2846 else if (value > (HOST_WIDEST_INT) 0
2847 && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
2848 fprintf (stream, "#%x", (unsigned int) value);
2849 else
2850 fprintf (stream, hex_format, value);
2851
2852 if (do_begin_end)
2853 fprintf (stream, "\n");
2854}
2855
2856/* Print the presumed shiftable wyde argument shifted into place (to
2857 be output with an operand). */
2858
2859static void
2860mmix_output_shifted_value (stream, value)
2861 FILE * stream;
2862 HOST_WIDEST_INT value;
2863{
2864 int i;
2865
2866 if (! mmix_shiftable_wyde_value (value))
2867 {
2868 char s[16+2+1];
2869 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
2870 internal_error ("MMIX Internal: %s is not a shiftable int", s);
2871 }
2872
2873 for (i = 0; i < 4; i++)
2874 {
2875 /* We know we're through when we find one-bits in the low 16 bits. */
2876 if (value & 0xffff)
2877 {
2878 fprintf (stream, "#%x", (int) (value & 0xffff));
2879 return;
2880 }
2881
2882 value >>= 16;
2883 }
2884
2885 /* No bits set? Then it must have been zero. */
2886 fprintf (stream, "0");
2887}
2888
2889/* Output an MMIX condition name corresponding to an operator
2890 and operands:
2891 (comparison_operator [(comparison_operator ...) (const_int 0)])
2892 which means we have to look at *two* operators.
2893
2894 The argument "reversed" refers to reversal of the condition (not the
2895 same as swapping the arguments). */
2896
2897static void
2898mmix_output_condition (stream, x, reversed)
2899 FILE *stream;
2900 rtx x;
2901 int reversed;
2902{
2903 struct cc_conv
2904 {
2905 RTX_CODE cc;
2906
2907 /* The normal output cc-code. */
2908 const char *const normal;
2909
2910 /* The reversed cc-code, or NULL if invalid. */
2911 const char *const reversed;
2912 };
2913
2914 struct cc_type_conv
2915 {
2916 enum machine_mode cc_mode;
2917
2918 /* Terminated with {NIL, NULL, NULL} */
2919 const struct cc_conv *const convs;
2920 };
2921
2922#undef CCEND
2923#define CCEND {NIL, NULL, NULL}
2924
2925 static const struct cc_conv cc_fun_convs[]
2926 = {{ORDERED, "Z", "P"},
2927 {UNORDERED, "P", "Z"},
2928 CCEND};
2929 static const struct cc_conv cc_fp_convs[]
2930 = {{GT, "P", NULL},
2931 {LT, "N", NULL},
2932 CCEND};
2933 static const struct cc_conv cc_fpeq_convs[]
2934 = {{NE, "Z", "P"},
2935 {EQ, "P", "Z"},
2936 CCEND};
2937 static const struct cc_conv cc_uns_convs[]
2938 = {{GEU, "NN", "N"},
2939 {GTU, "P", "NP"},
2940 {LEU, "NP", "P"},
2941 {LTU, "N", "NN"},
2942 CCEND};
2943 static const struct cc_conv cc_signed_convs[]
2944 = {{NE, "NZ", "Z"},
2945 {EQ, "Z", "NZ"},
2946 {GE, "NN", "N"},
2947 {GT, "P", "NP"},
2948 {LE, "NP", "P"},
2949 {LT, "N", "NN"},
2950 CCEND};
2951 static const struct cc_conv cc_di_convs[]
2952 = {{NE, "NZ", "Z"},
2953 {EQ, "Z", "NZ"},
2954 {GE, "NN", "N"},
2955 {GT, "P", "NP"},
2956 {LE, "NP", "P"},
2957 {LT, "N", "NN"},
2958 {GTU, "NZ", "Z"},
2959 {LEU, "Z", "NZ"},
2960 CCEND};
2961#undef CCEND
2962
2963 static const struct cc_type_conv cc_convs[]
2964 = {{CC_FUNmode, cc_fun_convs},
2965 {CC_FPmode, cc_fp_convs},
2966 {CC_FPEQmode, cc_fpeq_convs},
2967 {CC_UNSmode, cc_uns_convs},
2968 {CCmode, cc_signed_convs},
2969 {DImode, cc_di_convs}};
2970
3585dac7 2971 size_t i;
68cbb7e3 2972 int j;
2973
2974 enum machine_mode mode = GET_MODE (XEXP (x, 0));
2975 RTX_CODE cc = GET_CODE (x);
2976
3585dac7 2977 for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
68cbb7e3 2978 {
2979 if (mode == cc_convs[i].cc_mode)
2980 {
2981 for (j = 0; cc_convs[i].convs[j].cc != NIL; j++)
2982 if (cc == cc_convs[i].convs[j].cc)
2983 {
2984 const char *mmix_cc
2985 = (reversed ? cc_convs[i].convs[j].reversed
2986 : cc_convs[i].convs[j].normal);
2987
2988 if (mmix_cc == NULL)
2989 fatal_insn ("MMIX Internal: Trying to output invalidly\
2990 reversed condition:", x);
2991
2992 fprintf (stream, "%s", mmix_cc);
2993 return;
2994 }
2995
2996 fatal_insn ("MMIX Internal: What's the CC of this?", x);
2997 }
2998 }
2999
3000 fatal_insn ("MMIX Internal: What is the CC of this?", x);
3001}
3002
3003/* Return the bit-value for a const_int or const_double. */
3004
3005static HOST_WIDEST_INT
3006mmix_intval (x)
3007 rtx x;
3008{
3009 unsigned HOST_WIDEST_INT retval;
3010
3011 if (GET_CODE (x) == CONST_INT)
3012 return INTVAL (x);
3013
3014 /* We make a little song and dance because converting to long long in
3015 gcc-2.7.2 is broken. I still want people to be able to use it for
3016 cross-compilation to MMIX. */
3017 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
3018 {
3019 if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
3020 {
3021 retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
3022 retval *= 2;
3023 retval |= CONST_DOUBLE_LOW (x) & 1;
3024
3025 retval |=
3026 (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
3027 << (HOST_BITS_PER_LONG);
3028 }
3029 else
3030 retval = CONST_DOUBLE_HIGH (x);
3031
3032 return retval;
3033 }
3034
3035 if (GET_CODE (x) == CONST_DOUBLE)
3036 {
3037 REAL_VALUE_TYPE value;
3038
3039 /* FIXME: This macro is not in the manual but should be. */
3040 REAL_VALUE_FROM_CONST_DOUBLE (value, x);
3041
3042 if (GET_MODE (x) == DFmode)
3043 {
3044 long bits[2];
dc8dc4ce 3045
68cbb7e3 3046 REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
3047
3048 if (sizeof (long) < sizeof (HOST_WIDEST_INT))
3049 {
3050 retval = (unsigned long) bits[1] / 2;
3051 retval *= 2;
3052 retval |= (unsigned long) bits[1] & 1;
3053 retval
3054 |= (unsigned HOST_WIDEST_INT) bits[0]
3055 << (sizeof (bits[0]) * 8);
3056 }
3057 else
3058 retval = (unsigned long) bits[1];
3059
3060 return retval;
3061 }
3062 else if (GET_MODE (x) == SFmode)
3063 {
3064 long bits;
3065 REAL_VALUE_TO_TARGET_SINGLE (value, bits);
3066
3067 return (unsigned long) bits;
3068 }
3069 }
3070
3071 fatal_insn ("MMIX Internal: This is not a constant:", x);
3072}
3073
3074/*
3075 * Local variables:
3076 * eval: (c-set-style "gnu")
3077 * indent-tabs-mode: t
3078 * End:
3079 */