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