OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [mmix/] [mmix.c] - Blame information for rev 709

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.