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