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

Subversion Repositories openrisc

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
/* Subroutines for gcc2 for pdp11.
2
   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005,
3
   2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
   Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
11
any later version.
12
 
13
GCC is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "regs.h"
28
#include "hard-reg-set.h"
29
#include "insn-config.h"
30
#include "conditions.h"
31
#include "function.h"
32
#include "output.h"
33
#include "insn-attr.h"
34
#include "flags.h"
35
#include "recog.h"
36
#include "tree.h"
37
#include "expr.h"
38
#include "diagnostic-core.h"
39
#include "tm_p.h"
40
#include "target.h"
41
#include "target-def.h"
42
#include "df.h"
43
#include "opts.h"
44
 
45
/* this is the current value returned by the macro FIRST_PARM_OFFSET
46
   defined in tm.h */
47
int current_first_parm_offset;
48
 
49
/* Routines to encode/decode pdp11 floats */
50
static void encode_pdp11_f (const struct real_format *fmt,
51
                            long *, const REAL_VALUE_TYPE *);
52
static void decode_pdp11_f (const struct real_format *,
53
                            REAL_VALUE_TYPE *, const long *);
54
static void encode_pdp11_d (const struct real_format *fmt,
55
                            long *, const REAL_VALUE_TYPE *);
56
static void decode_pdp11_d (const struct real_format *,
57
                            REAL_VALUE_TYPE *, const long *);
58
 
59
/* These two are taken from the corresponding vax descriptors
60
   in real.c, changing only the encode/decode routine pointers.  */
61
const struct real_format pdp11_f_format =
62
  {
63
    encode_pdp11_f,
64
    decode_pdp11_f,
65
    2,
66
    24,
67
    24,
68
    -127,
69
    127,
70
    15,
71
    15,
72
    false,
73
    false,
74
    false,
75
    false,
76
    false,
77
    false,
78
    false,
79
    false
80
  };
81
 
82
const struct real_format pdp11_d_format =
83
  {
84
    encode_pdp11_d,
85
    decode_pdp11_d,
86
    2,
87
    56,
88
    56,
89
    -127,
90
    127,
91
    15,
92
    15,
93
    false,
94
    false,
95
    false,
96
    false,
97
    false,
98
    false,
99
    false,
100
    false
101
  };
102
 
103
static void
104
encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
105
                const REAL_VALUE_TYPE *r)
106
{
107
  (*vax_f_format.encode) (fmt, buf, r);
108
  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
109
}
110
 
111
static void
112
decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
113
                REAL_VALUE_TYPE *r, const long *buf)
114
{
115
  long tbuf;
116
  tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
117
  (*vax_f_format.decode) (fmt, r, &tbuf);
118
}
119
 
120
static void
121
encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
122
                const REAL_VALUE_TYPE *r)
123
{
124
  (*vax_d_format.encode) (fmt, buf, r);
125
  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
126
  buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
127
}
128
 
129
static void
130
decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
131
                REAL_VALUE_TYPE *r, const long *buf)
132
{
133
  long tbuf[2];
134
  tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
135
  tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
136
  (*vax_d_format.decode) (fmt, r, tbuf);
137
}
138
 
139
/* This is where the condition code register lives.  */
140
/* rtx cc0_reg_rtx; - no longer needed? */
141
 
142
static const char *singlemove_string (rtx *);
143
static bool pdp11_assemble_integer (rtx, unsigned int, int);
144
static bool pdp11_rtx_costs (rtx, int, int, int, int *, bool);
145
static bool pdp11_return_in_memory (const_tree, const_tree);
146
static rtx pdp11_function_value (const_tree, const_tree, bool);
147
static rtx pdp11_libcall_value (enum machine_mode, const_rtx);
148
static bool pdp11_function_value_regno_p (const unsigned int);
149
static void pdp11_trampoline_init (rtx, tree, rtx);
150
static rtx pdp11_function_arg (cumulative_args_t, enum machine_mode,
151
                               const_tree, bool);
152
static void pdp11_function_arg_advance (cumulative_args_t,
153
                                        enum machine_mode, const_tree, bool);
154
static void pdp11_conditional_register_usage (void);
155
static bool pdp11_legitimate_constant_p (enum machine_mode, rtx);
156
 
157
/* Initialize the GCC target structure.  */
158
#undef TARGET_ASM_BYTE_OP
159
#define TARGET_ASM_BYTE_OP NULL
160
#undef TARGET_ASM_ALIGNED_HI_OP
161
#define TARGET_ASM_ALIGNED_HI_OP NULL
162
#undef TARGET_ASM_ALIGNED_SI_OP
163
#define TARGET_ASM_ALIGNED_SI_OP NULL
164
#undef TARGET_ASM_INTEGER
165
#define TARGET_ASM_INTEGER pdp11_assemble_integer
166
 
167
#undef TARGET_ASM_OPEN_PAREN
168
#define TARGET_ASM_OPEN_PAREN "["
169
#undef TARGET_ASM_CLOSE_PAREN
170
#define TARGET_ASM_CLOSE_PAREN "]"
171
 
172
#undef TARGET_RTX_COSTS
173
#define TARGET_RTX_COSTS pdp11_rtx_costs
174
 
175
#undef TARGET_FUNCTION_ARG
176
#define TARGET_FUNCTION_ARG pdp11_function_arg
177
#undef TARGET_FUNCTION_ARG_ADVANCE
178
#define TARGET_FUNCTION_ARG_ADVANCE pdp11_function_arg_advance
179
 
180
#undef TARGET_RETURN_IN_MEMORY
181
#define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
182
 
183
#undef TARGET_FUNCTION_VALUE
184
#define TARGET_FUNCTION_VALUE pdp11_function_value
185
#undef TARGET_LIBCALL_VALUE
186
#define TARGET_LIBCALL_VALUE pdp11_libcall_value
187
#undef TARGET_FUNCTION_VALUE_REGNO_P
188
#define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
189
 
190
#undef TARGET_TRAMPOLINE_INIT
191
#define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
192
 
193
#undef  TARGET_SECONDARY_RELOAD
194
#define TARGET_SECONDARY_RELOAD pdp11_secondary_reload
195
 
196
#undef  TARGET_REGISTER_MOVE_COST 
197
#define TARGET_REGISTER_MOVE_COST pdp11_register_move_cost
198
 
199
#undef  TARGET_PREFERRED_RELOAD_CLASS
200
#define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class
201
 
202
#undef  TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
203
#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class
204
 
205
#undef  TARGET_LEGITIMATE_ADDRESS_P
206
#define TARGET_LEGITIMATE_ADDRESS_P pdp11_legitimate_address_p
207
 
208
#undef  TARGET_CONDITIONAL_REGISTER_USAGE
209
#define TARGET_CONDITIONAL_REGISTER_USAGE pdp11_conditional_register_usage
210
 
211
#undef  TARGET_ASM_FUNCTION_SECTION
212
#define TARGET_ASM_FUNCTION_SECTION pdp11_function_section
213
 
214
#undef  TARGET_PRINT_OPERAND
215
#define TARGET_PRINT_OPERAND pdp11_asm_print_operand
216
 
217
#undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
218
#define TARGET_PRINT_OPERAND_PUNCT_VALID_P pdp11_asm_print_operand_punct_valid_p
219
 
220
#undef  TARGET_LEGITIMATE_CONSTANT_P
221
#define TARGET_LEGITIMATE_CONSTANT_P pdp11_legitimate_constant_p
222
 
223
/* A helper function to determine if REGNO should be saved in the
224
   current function's stack frame.  */
225
 
226
static inline bool
227
pdp11_saved_regno (unsigned regno)
228
{
229
  return !call_used_regs[regno] && df_regs_ever_live_p (regno);
230
}
231
 
232
/* Expand the function prologue.  */
233
 
234
void
235
pdp11_expand_prologue (void)
236
{
237
  HOST_WIDE_INT fsize = get_frame_size ();
238
  unsigned regno;
239
  rtx x, via_ac = NULL;
240
 
241
  /* If we are outputting code for main, the switch FPU to the
242
     right mode if TARGET_FPU.  */
243
  if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
244
    {
245
      emit_insn (gen_setd ());
246
      emit_insn (gen_seti ());
247
    }
248
 
249
  if (frame_pointer_needed)
250
    {
251
      x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
252
      x = gen_frame_mem (Pmode, x);
253
      emit_move_insn (x, hard_frame_pointer_rtx);
254
 
255
      emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
256
    }
257
 
258
  /* Make frame.  */
259
  if (fsize)
260
    {
261
      emit_insn (gen_addhi3 (stack_pointer_rtx, stack_pointer_rtx,
262
                             GEN_INT (-fsize)));
263
 
264
      /* Prevent frame references via the frame pointer from being
265
         scheduled before the frame is allocated.  */
266
      if (frame_pointer_needed)
267
        emit_insn (gen_blockage ());
268
    }
269
 
270
  /* Save CPU registers.  */
271
  for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++)
272
    if (pdp11_saved_regno (regno)
273
        && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed))
274
      {
275
        x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
276
        x = gen_frame_mem (Pmode, x);
277
        emit_move_insn (x, gen_rtx_REG (Pmode, regno));
278
      }
279
 
280
  /* Save FPU registers.  */
281
  for (regno = AC0_REGNUM; regno <= AC3_REGNUM; regno++)
282
    if (pdp11_saved_regno (regno))
283
      {
284
        x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
285
        x = gen_frame_mem (DFmode, x);
286
        via_ac = gen_rtx_REG (DFmode, regno);
287
        emit_move_insn (x, via_ac);
288
      }
289
 
290
  /* ??? Maybe make ac4, ac5 call used regs?? */
291
  for (regno = AC4_REGNUM; regno <= AC5_REGNUM; regno++)
292
    if (pdp11_saved_regno (regno))
293
      {
294
        gcc_assert (via_ac != NULL);
295
        emit_move_insn (via_ac, gen_rtx_REG (DFmode, regno));
296
 
297
        x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
298
        x = gen_frame_mem (DFmode, x);
299
        emit_move_insn (x, via_ac);
300
      }
301
}
302
 
303
/* The function epilogue should not depend on the current stack pointer!
304
   It should use the frame pointer only.  This is mandatory because
305
   of alloca; we also take advantage of it to omit stack adjustments
306
   before returning.  */
307
 
308
/* Maybe we can make leaf functions faster by switching to the
309
   second register file - this way we don't have to save regs!
310
   leaf functions are ~ 50% of all functions (dynamically!)
311
 
312
   set/clear bit 11 (dec. 2048) of status word for switching register files -
313
   but how can we do this? the pdp11/45 manual says bit may only
314
   be set (p.24), but not cleared!
315
 
316
   switching to kernel is probably more expensive, so we'll leave it
317
   like this and not use the second set of registers...
318
 
319
   maybe as option if you want to generate code for kernel mode? */
320
 
321
void
322
pdp11_expand_epilogue (void)
323
{
324
  HOST_WIDE_INT fsize = get_frame_size ();
325
  unsigned regno;
326
  rtx x, reg, via_ac = NULL;
327
 
328
  if (pdp11_saved_regno (AC4_REGNUM) || pdp11_saved_regno (AC5_REGNUM))
329
    {
330
      /* Find a temporary with which to restore AC4/5.  */
331
      for (regno = AC0_REGNUM; regno <= AC3_REGNUM; regno++)
332
        if (pdp11_saved_regno (regno))
333
          {
334
            via_ac = gen_rtx_REG (DFmode, regno);
335
            break;
336
          }
337
    }
338
 
339
  /* If possible, restore registers via pops.  */
340
  if (!frame_pointer_needed || current_function_sp_is_unchanging)
341
    {
342
      /* Restore registers via pops.  */
343
 
344
      for (regno = AC5_REGNUM; regno >= AC0_REGNUM; regno--)
345
        if (pdp11_saved_regno (regno))
346
          {
347
            x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
348
            x = gen_frame_mem (DFmode, x);
349
            reg = gen_rtx_REG (DFmode, regno);
350
 
351
            if (LOAD_FPU_REG_P (regno))
352
              emit_move_insn (reg, x);
353
            else
354
              {
355
                emit_move_insn (via_ac, x);
356
                emit_move_insn (reg, via_ac);
357
              }
358
          }
359
 
360
      for (regno = PC_REGNUM; regno >= R0_REGNUM + 2; regno--)
361
        if (pdp11_saved_regno (regno)
362
            && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed))
363
          {
364
            x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
365
            x = gen_frame_mem (Pmode, x);
366
            emit_move_insn (gen_rtx_REG (Pmode, regno), x);
367
          }
368
    }
369
  else
370
    {
371
      /* Restore registers via moves.  */
372
      /* ??? If more than a few registers need to be restored, it's smaller
373
         to generate a pointer through which we can emit pops.  Consider
374
         that moves cost 2*NREG words and pops cost NREG+3 words.  This
375
         means that the crossover is NREG=3.
376
 
377
         Possible registers to use are:
378
          (1) The first call-saved general register.  This register will
379
                be restored with the last pop.
380
          (2) R1, if it's not used as a return register.
381
          (3) FP itself.  This option may result in +4 words, since we
382
                may need two add imm,rn instructions instead of just one.
383
                This also has the downside that we're not representing
384
                the unwind info in any way, so during the epilogue the
385
                debugger may get lost.  */
386
 
387
      HOST_WIDE_INT ofs = -pdp11_sp_frame_offset ();
388
 
389
      for (regno = AC5_REGNUM; regno >= AC0_REGNUM; regno--)
390
        if (pdp11_saved_regno (regno))
391
          {
392
            x = plus_constant (hard_frame_pointer_rtx, ofs);
393
            x = gen_frame_mem (DFmode, x);
394
            reg = gen_rtx_REG (DFmode, regno);
395
 
396
            if (LOAD_FPU_REG_P (regno))
397
              emit_move_insn (reg, x);
398
            else
399
              {
400
                emit_move_insn (via_ac, x);
401
                emit_move_insn (reg, via_ac);
402
              }
403
            ofs += 8;
404
          }
405
 
406
      for (regno = PC_REGNUM; regno >= R0_REGNUM + 2; regno--)
407
        if (pdp11_saved_regno (regno)
408
            && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed))
409
          {
410
            x = plus_constant (hard_frame_pointer_rtx, ofs);
411
            x = gen_frame_mem (Pmode, x);
412
            emit_move_insn (gen_rtx_REG (Pmode, regno), x);
413
            ofs += 2;
414
          }
415
    }
416
 
417
  /* Deallocate the stack frame.  */
418
  if (fsize)
419
    {
420
      /* Prevent frame references via any pointer from being
421
         scheduled after the frame is deallocated.  */
422
      emit_insn (gen_blockage ());
423
 
424
      if (frame_pointer_needed)
425
        {
426
          /* We can deallocate the frame with a single move.  */
427
          emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
428
        }
429
      else
430
        emit_insn (gen_addhi3 (stack_pointer_rtx, stack_pointer_rtx,
431
                               GEN_INT (fsize)));
432
    }
433
 
434
  if (frame_pointer_needed)
435
    {
436
      x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
437
      x = gen_frame_mem (Pmode, x);
438
      emit_move_insn (hard_frame_pointer_rtx, x);
439
    }
440
 
441
  emit_jump_insn (gen_return ());
442
}
443
 
444
/* Return the best assembler insn template
445
   for moving operands[1] into operands[0] as a fullword.  */
446
static const char *
447
singlemove_string (rtx *operands)
448
{
449
  if (operands[1] != const0_rtx)
450
    return "mov %1,%0";
451
 
452
  return "clr %0";
453
}
454
 
455
 
456
/* Expand multi-word operands (SImode or DImode) into the 2 or 4
457
   corresponding HImode operands.  The number of operands is given
458
   as the third argument, and the required order of the parts as
459
   the fourth argument.  */
460
bool
461
pdp11_expand_operands (rtx *operands, rtx exops[][2], int opcount,
462
                       pdp11_action *action, pdp11_partorder order)
463
{
464
  int words, op, w, i, sh;
465
  pdp11_partorder useorder;
466
  bool sameoff = false;
467
  enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype;
468
  REAL_VALUE_TYPE r;
469
  long sval[2];
470
 
471
  words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16;
472
 
473
  /* If either piece order is accepted and one is pre-decrement
474
     while the other is post-increment, set order to be high order
475
     word first.  That will force the pre-decrement to be turned
476
     into a pointer adjust, then offset addressing.
477
     Otherwise, if either operand uses pre-decrement, that means
478
     the order is low order first.
479
     Otherwise, if both operands are registers and destination is
480
     higher than source and they overlap, do low order word (highest
481
     register number) first.  */
482
  useorder = either;
483
  if (opcount == 2)
484
    {
485
      if (!REG_P (operands[0]) && !REG_P (operands[1]) &&
486
          !(CONSTANT_P (operands[1]) ||
487
            GET_CODE (operands[1]) == CONST_DOUBLE) &&
488
          ((GET_CODE (XEXP (operands[0], 0)) == POST_INC &&
489
            GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) ||
490
           (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC &&
491
            GET_CODE (XEXP (operands[1], 0)) == POST_INC)))
492
            useorder = big;
493
      else if ((!REG_P (operands[0]) &&
494
                GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) ||
495
               (!REG_P (operands[1]) &&
496
                !(CONSTANT_P (operands[1]) ||
497
                  GET_CODE (operands[1]) == CONST_DOUBLE) &&
498
                GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))
499
        useorder = little;
500
      else if (REG_P (operands[0]) && REG_P (operands[1]) &&
501
               REGNO (operands[0]) > REGNO (operands[1]) &&
502
               REGNO (operands[0]) < REGNO (operands[1]) + words)
503
            useorder = little;
504
 
505
      /* Check for source == offset from register and dest == push of
506
         the same register.  In that case, we have to use the same
507
         offset (the one for the low order word) for all words, because
508
         the push increases the offset to each source word.
509
         In theory there are other cases like this, for example dest == pop,
510
         but those don't occur in real life so ignore those.  */
511
      if (GET_CODE (operands[0]) ==  MEM
512
          && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
513
          && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
514
          && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
515
        sameoff = true;
516
    }
517
 
518
  /* If the caller didn't specify order, use the one we computed,
519
     or high word first if we don't care either.  If the caller did
520
     specify, verify we don't have a problem with that order.
521
     (If it matters to the caller, constraints need to be used to
522
     ensure this case doesn't occur).  */
523
  if (order == either)
524
    order = (useorder == either) ? big : useorder;
525
  else
526
    gcc_assert (useorder == either || useorder == order);
527
 
528
 
529
  for (op = 0; op < opcount; op++)
530
    {
531
      /* First classify the operand.  */
532
      if (REG_P (operands[op]))
533
        optype = REGOP;
534
      else if (CONSTANT_P (operands[op])
535
               || GET_CODE (operands[op]) == CONST_DOUBLE)
536
        optype = CNSTOP;
537
      else if (GET_CODE (XEXP (operands[op], 0)) == POST_INC)
538
        optype = POPOP;
539
      else if (GET_CODE (XEXP (operands[op], 0)) == PRE_DEC)
540
        optype = PUSHOP;
541
      else if (!reload_in_progress || offsettable_memref_p (operands[op]))
542
        optype = OFFSOP;
543
      else if (GET_CODE (operands[op]) == MEM)
544
        optype = MEMOP;
545
      else
546
        optype = RNDOP;
547
 
548
      /* Check for the cases that the operand constraints are not
549
         supposed to allow to happen. Return failure for such cases.  */
550
      if (optype == RNDOP)
551
        return false;
552
 
553
      if (action != NULL)
554
        action[op] = no_action;
555
 
556
      /* If the operand uses pre-decrement addressing but we
557
         want to get the parts high order first,
558
         decrement the former register explicitly
559
         and change the operand into ordinary indexing.  */
560
      if (optype == PUSHOP && order == big)
561
        {
562
          gcc_assert (action != NULL);
563
          action[op] = dec_before;
564
          operands[op] = gen_rtx_MEM (GET_MODE (operands[op]),
565
                                      XEXP (XEXP (operands[op], 0), 0));
566
          optype = OFFSOP;
567
        }
568
      /* If the operand uses post-increment mode but we want
569
         to get the parts low order first, change the operand
570
         into ordinary indexing and remember to increment
571
         the register explicitly when we're done.  */
572
      else if (optype == POPOP && order == little)
573
        {
574
          gcc_assert (action != NULL);
575
          action[op] = inc_after;
576
          operands[op] = gen_rtx_MEM (GET_MODE (operands[op]),
577
                                      XEXP (XEXP (operands[op], 0), 0));
578
          optype = OFFSOP;
579
        }
580
 
581
      if (GET_CODE (operands[op]) == CONST_DOUBLE)
582
        {
583
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[op]);
584
          REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
585
        }
586
 
587
      for (i = 0; i < words; i++)
588
        {
589
          if (order == big)
590
            w = i;
591
          else if (sameoff)
592
            w = words - 1;
593
          else
594
            w = words - 1 - i;
595
 
596
          /* Set the output operand to be word "w" of the input.  */
597
          if (optype == REGOP)
598
            exops[i][op] = gen_rtx_REG (HImode, REGNO (operands[op]) + w);
599
          else if (optype == OFFSOP)
600
            exops[i][op] = adjust_address (operands[op], HImode, w * 2);
601
          else if (optype == CNSTOP)
602
            {
603
              if (GET_CODE (operands[op]) == CONST_DOUBLE)
604
                {
605
                  sh = 16 - (w & 1) * 16;
606
                  exops[i][op] = gen_rtx_CONST_INT (HImode, (sval[w / 2] >> sh) & 0xffff);
607
                }
608
              else
609
                {
610
                  sh = ((words - 1 - w) * 16);
611
                  exops[i][op] = gen_rtx_CONST_INT (HImode, trunc_int_for_mode (INTVAL(operands[op]) >> sh, HImode));
612
                }
613
            }
614
          else
615
            exops[i][op] = operands[op];
616
        }
617
    }
618
  return true;
619
}
620
 
621
/* Output assembler code to perform a multiple-word move insn
622
   with operands OPERANDS.  This moves 2 or 4 words depending
623
   on the machine mode of the operands.  */
624
 
625
const char *
626
output_move_multiple (rtx *operands)
627
{
628
  rtx exops[4][2];
629
  pdp11_action action[2];
630
  int i, words;
631
 
632
  words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16;
633
 
634
  pdp11_expand_operands (operands, exops, 2, action, either);
635
 
636
  /* Check for explicit decrement before.  */
637
  if (action[0] == dec_before)
638
    {
639
      operands[0] = XEXP (operands[0], 0);
640
      output_asm_insn ("sub $4,%0", operands);
641
    }
642
  if (action[1] == dec_before)
643
    {
644
      operands[1] = XEXP (operands[1], 0);
645
      output_asm_insn ("sub $4,%1", operands);
646
    }
647
 
648
  /* Do the words.  */
649
  for (i = 0; i < words; i++)
650
    output_asm_insn (singlemove_string (exops[i]), exops[i]);
651
 
652
  /* Check for increment after.  */
653
  if (action[0] == inc_after)
654
    {
655
      operands[0] = XEXP (operands[0], 0);
656
      output_asm_insn ("add $4,%0", operands);
657
    }
658
  if (action[1] == inc_after)
659
    {
660
      operands[1] = XEXP (operands[1], 0);
661
      output_asm_insn ("add $4,%1", operands);
662
    }
663
 
664
  return "";
665
}
666
 
667
/* Output an ascii string.  */
668
void
669
output_ascii (FILE *file, const char *p, int size)
670
{
671
  int i;
672
 
673
  /* This used to output .byte "string", which doesn't work with the UNIX
674
     assembler and I think not with DEC ones either.  */
675
  fprintf (file, "\t.byte ");
676
 
677
  for (i = 0; i < size; i++)
678
    {
679
      register int c = p[i];
680
      if (c < 0)
681
        c += 256;
682
      fprintf (file, "%#o", c);
683
      if (i < size - 1)
684
        putc (',', file);
685
    }
686
  putc ('\n', file);
687
}
688
 
689
 
690
void
691
pdp11_asm_output_var (FILE *file, const char *name, int size,
692
                      int align, bool global)
693
{
694
  if (align > 8)
695
    fprintf (file, "\n\t.even\n");
696
  if (global)
697
    {
698
      fprintf (file, ".globl ");
699
      assemble_name (file, name);
700
    }
701
  fprintf (file, "\n");
702
  assemble_name (file, name);
703
  fprintf (file, ": .=.+ %#ho\n", (unsigned short)size);
704
}
705
 
706
static void
707
pdp11_asm_print_operand (FILE *file, rtx x, int code)
708
{
709
  REAL_VALUE_TYPE r;
710
  long sval[2];
711
 
712
  if (code == '#')
713
    fprintf (file, "#");
714
  else if (code == '@')
715
    {
716
      if (TARGET_UNIX_ASM)
717
        fprintf (file, "*");
718
      else
719
        fprintf (file, "@");
720
    }
721
  else if (GET_CODE (x) == REG)
722
    fprintf (file, "%s", reg_names[REGNO (x)]);
723
  else if (GET_CODE (x) == MEM)
724
    output_address (XEXP (x, 0));
725
  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != SImode)
726
    {
727
      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
728
      REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
729
      fprintf (file, "$%#lo", sval[0] >> 16);
730
    }
731
  else
732
    {
733
      putc ('$', file);
734
      output_addr_const_pdp11 (file, x);
735
    }
736
}
737
 
738
static bool
739
pdp11_asm_print_operand_punct_valid_p (unsigned char c)
740
{
741
  return (c == '#' || c == '@');
742
}
743
 
744
void
745
print_operand_address (FILE *file, register rtx addr)
746
{
747
  register rtx breg;
748
  rtx offset;
749
  int again = 0;
750
 
751
 retry:
752
 
753
  switch (GET_CODE (addr))
754
    {
755
    case MEM:
756
      if (TARGET_UNIX_ASM)
757
        fprintf (file, "*");
758
      else
759
        fprintf (file, "@");
760
      addr = XEXP (addr, 0);
761
      again = 1;
762
      goto retry;
763
 
764
    case REG:
765
      fprintf (file, "(%s)", reg_names[REGNO (addr)]);
766
      break;
767
 
768
    case PRE_MODIFY:
769
    case PRE_DEC:
770
      fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
771
      break;
772
 
773
    case POST_MODIFY:
774
    case POST_INC:
775
      fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
776
      break;
777
 
778
    case PLUS:
779
      breg = 0;
780
      offset = 0;
781
      if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
782
          || GET_CODE (XEXP (addr, 0)) == MEM)
783
        {
784
          offset = XEXP (addr, 0);
785
          addr = XEXP (addr, 1);
786
        }
787
      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
788
               || GET_CODE (XEXP (addr, 1)) == MEM)
789
        {
790
          offset = XEXP (addr, 1);
791
          addr = XEXP (addr, 0);
792
        }
793
      if (GET_CODE (addr) != PLUS)
794
        ;
795
      else if (GET_CODE (XEXP (addr, 0)) == REG)
796
        {
797
          breg = XEXP (addr, 0);
798
          addr = XEXP (addr, 1);
799
        }
800
      else if (GET_CODE (XEXP (addr, 1)) == REG)
801
        {
802
          breg = XEXP (addr, 1);
803
          addr = XEXP (addr, 0);
804
        }
805
      if (GET_CODE (addr) == REG)
806
        {
807
          gcc_assert (breg == 0);
808
          breg = addr;
809
          addr = 0;
810
        }
811
      if (offset != 0)
812
        {
813
          gcc_assert (addr == 0);
814
          addr = offset;
815
        }
816
      if (addr != 0)
817
        output_addr_const_pdp11 (file, addr);
818
      if (breg != 0)
819
        {
820
          gcc_assert (GET_CODE (breg) == REG);
821
          fprintf (file, "(%s)", reg_names[REGNO (breg)]);
822
        }
823
      break;
824
 
825
    default:
826
      if (!again && GET_CODE (addr) == CONST_INT)
827
        {
828
          /* Absolute (integer number) address.  */
829
          if (!TARGET_UNIX_ASM)
830
            fprintf (file, "@$");
831
        }
832
      output_addr_const_pdp11 (file, addr);
833
    }
834
}
835
 
836
/* Target hook to assemble integer objects.  We need to use the
837
   pdp-specific version of output_addr_const.  */
838
 
839
static bool
840
pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
841
{
842
  if (aligned_p)
843
    switch (size)
844
      {
845
      case 1:
846
        fprintf (asm_out_file, "\t.byte\t");
847
        output_addr_const_pdp11 (asm_out_file, GEN_INT (INTVAL (x) & 0xff));
848
;
849
        fprintf (asm_out_file, " /* char */\n");
850
        return true;
851
 
852
      case 2:
853
        fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
854
        output_addr_const_pdp11 (asm_out_file, x);
855
        fprintf (asm_out_file, " /* short */\n");
856
        return true;
857
      }
858
  return default_assemble_integer (x, size, aligned_p);
859
}
860
 
861
 
862
/* register move costs, indexed by regs */
863
 
864
static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
865
{
866
             /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
867
 
868
/* NO */     {  0,   0,   0,    0,    0,    0,   0},
869
/* MUL */    {  0,   2,   2,   22,   22,   22,  22},
870
/* GEN */    {  0,   2,   2,   22,   22,   22,  22},
871
/* LFPU */   {  0,  22,  22,    2,    2,    2,  22},
872
/* NLFPU */  {  0,  22,  22,    2,   10,   10,  22},
873
/* FPU */    {  0,  22,  22,    2,   10,   10,  22},
874
/* ALL */    {  0,  22,  22,   22,   22,   22,  22}
875
}  ;
876
 
877
 
878
/* -- note that some moves are tremendously expensive,
879
   because they require lots of tricks! do we have to
880
   charge the costs incurred by secondary reload class
881
   -- as we do here with 10 -- or not ? */
882
 
883
static int
884
pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
885
                          reg_class_t c1, reg_class_t c2)
886
{
887
    return move_costs[(int)c1][(int)c2];
888
}
889
 
890
static bool
891
pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
892
                 int opno ATTRIBUTE_UNUSED, int *total,
893
                 bool speed ATTRIBUTE_UNUSED)
894
{
895
  switch (code)
896
    {
897
    case CONST_INT:
898
      if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
899
        {
900
          *total = 0;
901
          return true;
902
        }
903
      /* FALLTHRU */
904
 
905
    case CONST:
906
    case LABEL_REF:
907
    case SYMBOL_REF:
908
      /* Twice as expensive as REG.  */
909
      *total = 2;
910
      return true;
911
 
912
    case CONST_DOUBLE:
913
      /* Twice (or 4 times) as expensive as 16 bit.  */
914
      *total = 4;
915
      return true;
916
 
917
    case MULT:
918
      /* ??? There is something wrong in MULT because MULT is not
919
         as cheap as total = 2 even if we can shift!  */
920
      /* If optimizing for size make mult etc cheap, but not 1, so when
921
         in doubt the faster insn is chosen.  */
922
      if (optimize_size)
923
        *total = COSTS_N_INSNS (2);
924
      else
925
        *total = COSTS_N_INSNS (11);
926
      return false;
927
 
928
    case DIV:
929
      if (optimize_size)
930
        *total = COSTS_N_INSNS (2);
931
      else
932
        *total = COSTS_N_INSNS (25);
933
      return false;
934
 
935
    case MOD:
936
      if (optimize_size)
937
        *total = COSTS_N_INSNS (2);
938
      else
939
        *total = COSTS_N_INSNS (26);
940
      return false;
941
 
942
    case ABS:
943
      /* Equivalent to length, so same for optimize_size.  */
944
      *total = COSTS_N_INSNS (3);
945
      return false;
946
 
947
    case ZERO_EXTEND:
948
      /* Only used for qi->hi.  */
949
      *total = COSTS_N_INSNS (1);
950
      return false;
951
 
952
    case SIGN_EXTEND:
953
      if (GET_MODE (x) == HImode)
954
        *total = COSTS_N_INSNS (1);
955
      else if (GET_MODE (x) == SImode)
956
        *total = COSTS_N_INSNS (6);
957
      else
958
        *total = COSTS_N_INSNS (2);
959
      return false;
960
 
961
    case ASHIFT:
962
    case LSHIFTRT:
963
    case ASHIFTRT:
964
      if (optimize_size)
965
        *total = COSTS_N_INSNS (1);
966
      else if (GET_MODE (x) ==  QImode)
967
        {
968
          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
969
            *total = COSTS_N_INSNS (8); /* worst case */
970
          else
971
            *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
972
        }
973
      else if (GET_MODE (x) == HImode)
974
        {
975
          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
976
            {
977
              if (abs (INTVAL (XEXP (x, 1))) == 1)
978
                *total = COSTS_N_INSNS (1);
979
              else
980
                *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
981
            }
982
          else
983
            *total = COSTS_N_INSNS (10); /* worst case */
984
        }
985
      else if (GET_MODE (x) == SImode)
986
        {
987
          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
988
            *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
989
          else /* worst case */
990
            *total = COSTS_N_INSNS (18);
991
        }
992
      return false;
993
 
994
    default:
995
      return false;
996
    }
997
}
998
 
999
const char *
1000
output_jump (enum rtx_code code, int inv, int length)
1001
{
1002
    static int x = 0;
1003
 
1004
    static char buf[1000];
1005
    const char *pos, *neg;
1006
 
1007
    if (cc_prev_status.flags & CC_NO_OVERFLOW)
1008
      {
1009
        switch (code)
1010
          {
1011
          case GTU: code = GT; break;
1012
          case LTU: code = LT; break;
1013
          case GEU: code = GE; break;
1014
          case LEU: code = LE; break;
1015
          default: ;
1016
          }
1017
      }
1018
    switch (code)
1019
      {
1020
      case EQ: pos = "beq", neg = "bne"; break;
1021
      case NE: pos = "bne", neg = "beq"; break;
1022
      case GT: pos = "bgt", neg = "ble"; break;
1023
      case GTU: pos = "bhi", neg = "blos"; break;
1024
      case LT: pos = "blt", neg = "bge"; break;
1025
      case LTU: pos = "blo", neg = "bhis"; break;
1026
      case GE: pos = "bge", neg = "blt"; break;
1027
      case GEU: pos = "bhis", neg = "blo"; break;
1028
      case LE: pos = "ble", neg = "bgt"; break;
1029
      case LEU: pos = "blos", neg = "bhi"; break;
1030
      default: gcc_unreachable ();
1031
      }
1032
 
1033
#if 0
1034
/* currently we don't need this, because the tstdf and cmpdf
1035
   copy the condition code immediately, and other float operations are not
1036
   yet recognized as changing the FCC - if so, then the length-cost of all
1037
   jump insns increases by one, because we have to potentially copy the
1038
   FCC! */
1039
    if (cc_status.flags & CC_IN_FPU)
1040
        output_asm_insn("cfcc", NULL);
1041
#endif
1042
 
1043
    switch (length)
1044
    {
1045
      case 2:
1046
 
1047
        sprintf(buf, "%s %%l1", inv ? neg : pos);
1048
 
1049
        return buf;
1050
 
1051
      case 6:
1052
 
1053
        sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
1054
 
1055
        x++;
1056
 
1057
        return buf;
1058
 
1059
      default:
1060
 
1061
        gcc_unreachable ();
1062
    }
1063
 
1064
}
1065
 
1066
void
1067
notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1068
{
1069
    if (GET_CODE (SET_DEST (exp)) == CC0)
1070
    {
1071
      cc_status.flags = 0;
1072
      cc_status.value1 = SET_DEST (exp);
1073
      cc_status.value2 = SET_SRC (exp);
1074
    }
1075
    else if (GET_CODE (SET_SRC (exp)) == CALL)
1076
    {
1077
      CC_STATUS_INIT;
1078
    }
1079
    else if (SET_DEST(exp) == pc_rtx)
1080
    {
1081
      /* jump */
1082
    }
1083
    else if (GET_MODE (SET_DEST(exp)) == HImode
1084
             || GET_MODE (SET_DEST(exp)) == QImode)
1085
    {
1086
      cc_status.flags = GET_CODE (SET_SRC(exp)) == MINUS ? 0 : CC_NO_OVERFLOW;
1087
      cc_status.value1 = SET_SRC (exp);
1088
      cc_status.value2 = SET_DEST (exp);
1089
 
1090
      if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1091
          && cc_status.value2
1092
          && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1093
        cc_status.value2 = 0;
1094
      if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1095
          && cc_status.value2
1096
          && GET_CODE (cc_status.value2) == MEM)
1097
        cc_status.value2 = 0;
1098
    }
1099
    else
1100
    {
1101
      CC_STATUS_INIT;
1102
    }
1103
}
1104
 
1105
 
1106
int
1107
simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1108
{
1109
    rtx addr;
1110
 
1111
    /* Eliminate non-memory operations */
1112
    if (GET_CODE (op) != MEM)
1113
        return FALSE;
1114
 
1115
#if 0
1116
    /* dword operations really put out 2 instructions, so eliminate them.  */
1117
    if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1118
        return FALSE;
1119
#endif
1120
 
1121
    /* Decode the address now.  */
1122
 
1123
  indirection:
1124
 
1125
    addr = XEXP (op, 0);
1126
 
1127
    switch (GET_CODE (addr))
1128
    {
1129
      case REG:
1130
        /* (R0) - no extra cost */
1131
        return 1;
1132
 
1133
      case PRE_DEC:
1134
      case POST_INC:
1135
        /* -(R0), (R0)+ - cheap! */
1136
        return 0;
1137
 
1138
      case MEM:
1139
        /* cheap - is encoded in addressing mode info!
1140
 
1141
           -- except for @(R0), which has to be @0(R0) !!! */
1142
 
1143
        if (GET_CODE (XEXP (addr, 0)) == REG)
1144
            return 0;
1145
 
1146
        op=addr;
1147
        goto indirection;
1148
 
1149
      case CONST_INT:
1150
      case LABEL_REF:
1151
      case CONST:
1152
      case SYMBOL_REF:
1153
        /* @#address - extra cost */
1154
        return 0;
1155
 
1156
      case PLUS:
1157
        /* X(R0) - extra cost */
1158
        return 0;
1159
 
1160
      default:
1161
        break;
1162
    }
1163
 
1164
    return FALSE;
1165
}
1166
 
1167
 
1168
/*
1169
 * output a block move:
1170
 *
1171
 * operands[0]  ... to
1172
 * operands[1]  ... from
1173
 * operands[2]  ... length
1174
 * operands[3]  ... alignment
1175
 * operands[4]  ... scratch register
1176
 */
1177
 
1178
 
1179
const char *
1180
output_block_move(rtx *operands)
1181
{
1182
    static int count = 0;
1183
    char buf[200];
1184
    int unroll;
1185
    int lastbyte = 0;
1186
 
1187
    /* Move of zero bytes is a NOP.  */
1188
    if (operands[2] == const0_rtx)
1189
      return "";
1190
 
1191
    /* Look for moves by small constant byte counts, those we'll
1192
       expand to straight line code.  */
1193
    if (CONSTANT_P (operands[2]))
1194
    {
1195
        if (INTVAL (operands[2]) < 16
1196
            && (!optimize_size || INTVAL (operands[2]) < 5)
1197
            && INTVAL (operands[3]) == 1)
1198
        {
1199
            register int i;
1200
 
1201
            for (i = 1; i <= INTVAL (operands[2]); i++)
1202
                output_asm_insn("movb (%1)+, (%0)+", operands);
1203
 
1204
            return "";
1205
        }
1206
        else if (INTVAL(operands[2]) < 32
1207
                 && (!optimize_size || INTVAL (operands[2]) < 9)
1208
                 && INTVAL (operands[3]) >= 2)
1209
        {
1210
            register int i;
1211
 
1212
            for (i = 1; i <= INTVAL (operands[2]) / 2; i++)
1213
                output_asm_insn ("mov (%1)+, (%0)+", operands);
1214
            if (INTVAL (operands[2]) & 1)
1215
              output_asm_insn ("movb (%1), (%0)", operands);
1216
 
1217
            return "";
1218
        }
1219
    }
1220
 
1221
    /* Ideally we'd look for moves that are multiples of 4 or 8
1222
       bytes and handle those by unrolling the move loop.  That
1223
       makes for a lot of code if done at run time, but it's ok
1224
       for constant counts.  Also, for variable counts we have
1225
       to worry about odd byte count with even aligned pointers.
1226
       On 11/40 and up we handle that case; on older machines
1227
       we don't and just use byte-wise moves all the time.  */
1228
 
1229
    if (CONSTANT_P (operands[2]) )
1230
    {
1231
      if (INTVAL (operands[3]) < 2)
1232
        unroll = 0;
1233
      else
1234
        {
1235
          lastbyte = INTVAL (operands[2]) & 1;
1236
 
1237
          if (optimize_size || INTVAL (operands[2]) & 2)
1238
            unroll = 1;
1239
          else if (INTVAL (operands[2]) & 4)
1240
            unroll = 2;
1241
          else
1242
            unroll = 3;
1243
        }
1244
 
1245
      /* Loop count is byte count scaled by unroll.  */
1246
      operands[2] = GEN_INT (INTVAL (operands[2]) >> unroll);
1247
      output_asm_insn ("mov %2, %4", operands);
1248
    }
1249
    else
1250
    {
1251
        /* Variable byte count; use the input register
1252
           as the scratch.  */
1253
        operands[4] = operands[2];
1254
 
1255
        /* Decide whether to move by words, and check
1256
           the byte count for zero.  */
1257
        if (TARGET_40_PLUS && INTVAL (operands[3]) > 1)
1258
          {
1259
            unroll = 1;
1260
            output_asm_insn ("asr %4", operands);
1261
          }
1262
        else
1263
          {
1264
            unroll = 0;
1265
            output_asm_insn ("tst %4", operands);
1266
          }
1267
        sprintf (buf, "beq movestrhi%d", count + 1);
1268
        output_asm_insn (buf, NULL);
1269
    }
1270
 
1271
    /* Output the loop label.  */
1272
    sprintf (buf, "\nmovestrhi%d:", count);
1273
    output_asm_insn (buf, NULL);
1274
 
1275
    /* Output the appropriate move instructions.  */
1276
    switch (unroll)
1277
    {
1278
      case 0:
1279
        output_asm_insn ("movb (%1)+, (%0)+", operands);
1280
        break;
1281
 
1282
      case 1:
1283
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1284
        break;
1285
 
1286
      case 2:
1287
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1288
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1289
        break;
1290
 
1291
      default:
1292
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1293
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1294
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1295
        output_asm_insn ("mov (%1)+, (%0)+", operands);
1296
        break;
1297
    }
1298
 
1299
    /* Output the decrement and test.  */
1300
    if (TARGET_40_PLUS)
1301
      {
1302
        sprintf (buf, "sob %%4, movestrhi%d", count);
1303
        output_asm_insn (buf, operands);
1304
      }
1305
    else
1306
      {
1307
        output_asm_insn ("dec %4", operands);
1308
        sprintf (buf, "bgt movestrhi%d", count);
1309
        output_asm_insn (buf, NULL);
1310
      }
1311
    count ++;
1312
 
1313
    /* If constant odd byte count, move the last byte.  */
1314
    if (lastbyte)
1315
      output_asm_insn ("movb (%1), (%0)", operands);
1316
    else if (!CONSTANT_P (operands[2]))
1317
      {
1318
        /* Output the destination label for the zero byte count check.  */
1319
        sprintf (buf, "\nmovestrhi%d:", count);
1320
        output_asm_insn (buf, NULL);
1321
        count++;
1322
 
1323
        /* If we did word moves, check for trailing last byte. */
1324
        if (unroll)
1325
          {
1326
            sprintf (buf, "bcc movestrhi%d", count);
1327
            output_asm_insn (buf, NULL);
1328
            output_asm_insn ("movb (%1), (%0)", operands);
1329
            sprintf (buf, "\nmovestrhi%d:", count);
1330
            output_asm_insn (buf, NULL);
1331
            count++;
1332
          }
1333
      }
1334
 
1335
    return "";
1336
}
1337
 
1338
/* This function checks whether a real value can be encoded as
1339
   a literal, i.e., addressing mode 27.  In that mode, real values
1340
   are one word values, so the remaining 48 bits have to be zero.  */
1341
int
1342
legitimate_const_double_p (rtx address)
1343
{
1344
  REAL_VALUE_TYPE r;
1345
  long sval[2];
1346
  REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1347
  REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1348
  if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1349
    return 1;
1350
  return 0;
1351
}
1352
 
1353
/* Implement CANNOT_CHANGE_MODE_CLASS.  */
1354
bool
1355
pdp11_cannot_change_mode_class (enum machine_mode from,
1356
                                enum machine_mode to,
1357
                                enum reg_class rclass)
1358
{
1359
  /* Also, FPU registers contain a whole float value and the parts of
1360
     it are not separately accessible.
1361
 
1362
     So we disallow all mode changes involving FPRs.  */
1363
  if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
1364
    return true;
1365
 
1366
  return reg_classes_intersect_p (FPU_REGS, rclass);
1367
}
1368
 
1369
/* TARGET_PREFERRED_RELOAD_CLASS
1370
 
1371
   Given an rtx X being reloaded into a reg required to be
1372
   in class CLASS, return the class of reg to actually use.
1373
   In general this is just CLASS; but on some machines
1374
   in some cases it is preferable to use a more restrictive class.
1375
 
1376
loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1377
 
1378
static reg_class_t
1379
pdp11_preferred_reload_class (rtx x, reg_class_t rclass)
1380
{
1381
  if (rclass == FPU_REGS)
1382
    return LOAD_FPU_REGS;
1383
  if (rclass == ALL_REGS)
1384
    {
1385
      if (FLOAT_MODE_P (GET_MODE (x)))
1386
        return LOAD_FPU_REGS;
1387
      else
1388
        return GENERAL_REGS;
1389
    }
1390
  return rclass;
1391
}
1392
 
1393
/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
1394
 
1395
   Given an rtx X being reloaded into a reg required to be
1396
   in class CLASS, return the class of reg to actually use.
1397
   In general this is just CLASS; but on some machines
1398
   in some cases it is preferable to use a more restrictive class.
1399
 
1400
loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1401
 
1402
static reg_class_t
1403
pdp11_preferred_output_reload_class (rtx x, reg_class_t rclass)
1404
{
1405
  if (rclass == FPU_REGS)
1406
    return LOAD_FPU_REGS;
1407
  if (rclass == ALL_REGS)
1408
    {
1409
      if (FLOAT_MODE_P (GET_MODE (x)))
1410
        return LOAD_FPU_REGS;
1411
      else
1412
        return GENERAL_REGS;
1413
    }
1414
  return rclass;
1415
}
1416
 
1417
 
1418
/* TARGET_SECONDARY_RELOAD.
1419
 
1420
   FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an
1421
   intermediate register (AC0-AC3: LOAD_FPU_REGS).  Everything else
1422
   can be loade/stored directly.  */
1423
static reg_class_t
1424
pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
1425
                        rtx x,
1426
                        reg_class_t reload_class,
1427
                        enum machine_mode reload_mode ATTRIBUTE_UNUSED,
1428
                        secondary_reload_info *sri ATTRIBUTE_UNUSED)
1429
{
1430
  if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG ||
1431
      REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS)
1432
    return NO_REGS;
1433
 
1434
  return LOAD_FPU_REGS;
1435
}
1436
 
1437
/* Target routine to check if register to register move requires memory.
1438
 
1439
   The answer is yes if we're going between general register and FPU
1440
   registers.  The mode doesn't matter in making this check.
1441
*/
1442
bool
1443
pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
1444
                               enum machine_mode mode ATTRIBUTE_UNUSED)
1445
{
1446
  int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS ||
1447
                   c1 == FPU_REGS);
1448
  int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS ||
1449
                 c2 == FPU_REGS);
1450
 
1451
  return (fromfloat != tofloat);
1452
}
1453
 
1454
/* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression
1455
   that is a valid memory address for an instruction.
1456
   The MODE argument is the machine mode for the MEM expression
1457
   that wants to use this address.
1458
 
1459
*/
1460
 
1461
static bool
1462
pdp11_legitimate_address_p (enum machine_mode mode,
1463
                            rtx operand, bool strict)
1464
{
1465
    rtx xfoob;
1466
 
1467
    /* accept @#address */
1468
    if (CONSTANT_ADDRESS_P (operand))
1469
      return true;
1470
 
1471
    switch (GET_CODE (operand))
1472
      {
1473
      case REG:
1474
        /* accept (R0) */
1475
        return !strict || REGNO_OK_FOR_BASE_P (REGNO (operand));
1476
 
1477
      case PLUS:
1478
        /* accept X(R0) */
1479
        return GET_CODE (XEXP (operand, 0)) == REG
1480
          && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))))
1481
          && CONSTANT_ADDRESS_P (XEXP (operand, 1));
1482
 
1483
      case PRE_DEC:
1484
        /* accept -(R0) */
1485
        return GET_CODE (XEXP (operand, 0)) == REG
1486
          && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))));
1487
 
1488
      case POST_INC:
1489
        /* accept (R0)+ */
1490
        return GET_CODE (XEXP (operand, 0)) == REG
1491
          && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))));
1492
 
1493
      case PRE_MODIFY:
1494
        /* accept -(SP) -- which uses PRE_MODIFY for byte mode */
1495
        return GET_CODE (XEXP (operand, 0)) == REG
1496
          && REGNO (XEXP (operand, 0)) == STACK_POINTER_REGNUM
1497
          && GET_CODE ((xfoob = XEXP (operand, 1))) == PLUS
1498
          && GET_CODE (XEXP (xfoob, 0)) == REG
1499
          && REGNO (XEXP (xfoob, 0)) == STACK_POINTER_REGNUM
1500
          && CONSTANT_P (XEXP (xfoob, 1))
1501
          && INTVAL (XEXP (xfoob,1)) == -2;
1502
 
1503
      case POST_MODIFY:
1504
        /* accept (SP)+ -- which uses POST_MODIFY for byte mode */
1505
        return GET_CODE (XEXP (operand, 0)) == REG
1506
          && REGNO (XEXP (operand, 0)) == STACK_POINTER_REGNUM
1507
          && GET_CODE ((xfoob = XEXP (operand, 1))) == PLUS
1508
          && GET_CODE (XEXP (xfoob, 0)) == REG
1509
          && REGNO (XEXP (xfoob, 0)) == STACK_POINTER_REGNUM
1510
          && CONSTANT_P (XEXP (xfoob, 1))
1511
          && INTVAL (XEXP (xfoob,1)) == 2;
1512
 
1513
      case MEM:
1514
        /* handle another level of indirection ! */
1515
        xfoob = XEXP (operand, 0);
1516
 
1517
        /* (MEM:xx (MEM:xx ())) is not valid for SI, DI and currently
1518
           also forbidden for float, because we have to handle this
1519
           in output_move_double and/or output_move_quad() - we could
1520
           do it, but currently it's not worth it!!!
1521
           now that DFmode cannot go into CPU register file,
1522
           maybe I should allow float ...
1523
           but then I have to handle memory-to-memory moves in movdf ??  */
1524
        if (GET_MODE_BITSIZE(mode) > 16)
1525
          return false;
1526
 
1527
        /* accept @address */
1528
        if (CONSTANT_ADDRESS_P (xfoob))
1529
          return true;
1530
 
1531
        switch (GET_CODE (xfoob))
1532
          {
1533
          case REG:
1534
            /* accept @(R0) - which is @0(R0) */
1535
            return !strict || REGNO_OK_FOR_BASE_P(REGNO (xfoob));
1536
 
1537
          case PLUS:
1538
            /* accept @X(R0) */
1539
            return GET_CODE (XEXP (xfoob, 0)) == REG
1540
              && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))))
1541
              && CONSTANT_ADDRESS_P (XEXP (xfoob, 1));
1542
 
1543
          case PRE_DEC:
1544
            /* accept @-(R0) */
1545
            return GET_CODE (XEXP (xfoob, 0)) == REG
1546
              && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))));
1547
 
1548
          case POST_INC:
1549
            /* accept @(R0)+ */
1550
            return GET_CODE (XEXP (xfoob, 0)) == REG
1551
              && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))));
1552
 
1553
          default:
1554
            /* anything else is invalid */
1555
            return false;
1556
          }
1557
 
1558
      default:
1559
        /* anything else is invalid */
1560
        return false;
1561
      }
1562
}
1563
 
1564
/* Return the class number of the smallest class containing
1565
   reg number REGNO.  */
1566
enum reg_class
1567
pdp11_regno_reg_class (int regno)
1568
{
1569
  if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM)
1570
    return GENERAL_REGS;
1571
  else if (regno > AC3_REGNUM)
1572
    return NO_LOAD_FPU_REGS;
1573
  else if (regno >= AC0_REGNUM)
1574
    return LOAD_FPU_REGS;
1575
  else if (regno & 1)
1576
    return MUL_REGS;
1577
  else
1578
    return GENERAL_REGS;
1579
}
1580
 
1581
 
1582
int
1583
pdp11_sp_frame_offset (void)
1584
{
1585
  int offset = 0, regno;
1586
  offset = get_frame_size();
1587
  for (regno = 0; regno <= PC_REGNUM; regno++)
1588
    if (pdp11_saved_regno (regno))
1589
      offset += 2;
1590
  for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++)
1591
    if (pdp11_saved_regno (regno))
1592
      offset += 8;
1593
 
1594
  return offset;
1595
}
1596
 
1597
/* Return the offset between two registers, one to be eliminated, and the other
1598
   its replacement, at the start of a routine.  */
1599
 
1600
int
1601
pdp11_initial_elimination_offset (int from, int to)
1602
{
1603
  int spoff;
1604
 
1605
  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
1606
    return 4;
1607
  else if (from == FRAME_POINTER_REGNUM
1608
           && to == HARD_FRAME_POINTER_REGNUM)
1609
    return 0;
1610
  else
1611
    {
1612
      gcc_assert (to == STACK_POINTER_REGNUM);
1613
 
1614
      /* Get the size of the register save area.  */
1615
      spoff = pdp11_sp_frame_offset ();
1616
      if (from == FRAME_POINTER_REGNUM)
1617
        return spoff;
1618
 
1619
      gcc_assert (from == ARG_POINTER_REGNUM);
1620
 
1621
      /* If there is a frame pointer, that is saved too.  */
1622
      if (frame_pointer_needed)
1623
        spoff += 2;
1624
 
1625
      /* Account for the saved PC in the function call.  */
1626
      return spoff + 2;
1627
    }
1628
}
1629
 
1630
/* A copy of output_addr_const modified for pdp11 expression syntax.
1631
   output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1632
   use, and for debugging output, which we don't support with this port either.
1633
   So this copy should get called whenever needed.
1634
*/
1635
void
1636
output_addr_const_pdp11 (FILE *file, rtx x)
1637
{
1638
  char buf[256];
1639
  int i;
1640
 
1641
 restart:
1642
  switch (GET_CODE (x))
1643
    {
1644
    case PC:
1645
      gcc_assert (flag_pic);
1646
      putc ('.', file);
1647
      break;
1648
 
1649
    case SYMBOL_REF:
1650
      assemble_name (file, XSTR (x, 0));
1651
      break;
1652
 
1653
    case LABEL_REF:
1654
      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1655
      assemble_name (file, buf);
1656
      break;
1657
 
1658
    case CODE_LABEL:
1659
      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1660
      assemble_name (file, buf);
1661
      break;
1662
 
1663
    case CONST_INT:
1664
      i = INTVAL (x);
1665
      if (i < 0)
1666
        {
1667
          i = -i;
1668
          fprintf (file, "-");
1669
        }
1670
      fprintf (file, "%#o", i & 0xffff);
1671
      break;
1672
 
1673
    case CONST:
1674
      /* This used to output parentheses around the expression,
1675
         but that does not work on the 386 (either ATT or BSD assembler).  */
1676
      output_addr_const_pdp11 (file, XEXP (x, 0));
1677
      break;
1678
 
1679
    case CONST_DOUBLE:
1680
      if (GET_MODE (x) == VOIDmode)
1681
        {
1682
          /* We can use %o if the number is one word and positive.  */
1683
          gcc_assert (!CONST_DOUBLE_HIGH (x));
1684
          fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1685
        }
1686
      else
1687
        /* We can't handle floating point constants;
1688
           PRINT_OPERAND must handle them.  */
1689
        output_operand_lossage ("floating constant misused");
1690
      break;
1691
 
1692
    case PLUS:
1693
      /* Some assemblers need integer constants to appear last (e.g. masm).  */
1694
      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1695
        {
1696
          output_addr_const_pdp11 (file, XEXP (x, 1));
1697
          if (INTVAL (XEXP (x, 0)) >= 0)
1698
            fprintf (file, "+");
1699
          output_addr_const_pdp11 (file, XEXP (x, 0));
1700
        }
1701
      else
1702
        {
1703
          output_addr_const_pdp11 (file, XEXP (x, 0));
1704
          if (INTVAL (XEXP (x, 1)) >= 0)
1705
            fprintf (file, "+");
1706
          output_addr_const_pdp11 (file, XEXP (x, 1));
1707
        }
1708
      break;
1709
 
1710
    case MINUS:
1711
      /* Avoid outputting things like x-x or x+5-x,
1712
         since some assemblers can't handle that.  */
1713
      x = simplify_subtraction (x);
1714
      if (GET_CODE (x) != MINUS)
1715
        goto restart;
1716
 
1717
      output_addr_const_pdp11 (file, XEXP (x, 0));
1718
      if (GET_CODE (XEXP (x, 1)) != CONST_INT
1719
          || INTVAL (XEXP (x, 1)) >= 0)
1720
        fprintf (file, "-");
1721
      output_addr_const_pdp11 (file, XEXP (x, 1));
1722
      break;
1723
 
1724
    case ZERO_EXTEND:
1725
    case SIGN_EXTEND:
1726
      output_addr_const_pdp11 (file, XEXP (x, 0));
1727
      break;
1728
 
1729
    default:
1730
      output_operand_lossage ("invalid expression as operand");
1731
    }
1732
}
1733
 
1734
/* Worker function for TARGET_RETURN_IN_MEMORY.  */
1735
 
1736
static bool
1737
pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1738
{
1739
  /* Integers 32 bits and under, and scalar floats (if FPU), are returned
1740
     in registers.  The rest go into memory.  */
1741
  return (TYPE_MODE (type) == DImode
1742
          || (FLOAT_MODE_P (TYPE_MODE (type)) && ! TARGET_AC0)
1743
          || TREE_CODE (type) == VECTOR_TYPE
1744
          || COMPLEX_MODE_P (TYPE_MODE (type)));
1745
}
1746
 
1747
/* Worker function for TARGET_FUNCTION_VALUE.
1748
 
1749
   On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! )  */
1750
 
1751
static rtx
1752
pdp11_function_value (const_tree valtype,
1753
                      const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1754
                      bool outgoing ATTRIBUTE_UNUSED)
1755
{
1756
  return gen_rtx_REG (TYPE_MODE (valtype),
1757
                      BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1758
}
1759
 
1760
/* Worker function for TARGET_LIBCALL_VALUE.  */
1761
 
1762
static rtx
1763
pdp11_libcall_value (enum machine_mode mode,
1764
                     const_rtx fun ATTRIBUTE_UNUSED)
1765
{
1766
  return  gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1767
}
1768
 
1769
/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1770
 
1771
   On the pdp, the first "output" reg is the only register thus used.
1772
 
1773
   maybe ac0 ? - as option someday!  */
1774
 
1775
static bool
1776
pdp11_function_value_regno_p (const unsigned int regno)
1777
{
1778
  return (regno == RETVAL_REGNUM) || (TARGET_AC0 && (regno == AC0_REGNUM));
1779
}
1780
 
1781
/* Worker function for TARGET_TRAMPOLINE_INIT.
1782
 
1783
   trampoline - how should i do it in separate i+d ?
1784
   have some allocate_trampoline magic???
1785
 
1786
   the following should work for shared I/D:
1787
 
1788
   MOV  #STATIC, $4     01270Y  0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1789
   JMP  @#FUNCTION      000137  0x0000 <- FUNCTION
1790
*/
1791
 
1792
static void
1793
pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1794
{
1795
  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1796
  rtx mem;
1797
 
1798
  gcc_assert (!TARGET_SPLIT);
1799
 
1800
  mem = adjust_address (m_tramp, HImode, 0);
1801
  emit_move_insn (mem, GEN_INT (012700+STATIC_CHAIN_REGNUM));
1802
  mem = adjust_address (m_tramp, HImode, 2);
1803
  emit_move_insn (mem, chain_value);
1804
  mem = adjust_address (m_tramp, HImode, 4);
1805
  emit_move_insn (mem, GEN_INT (000137));
1806
  emit_move_insn (mem, fnaddr);
1807
}
1808
 
1809
/* Worker function for TARGET_FUNCTION_ARG.
1810
 
1811
   Determine where to put an argument to a function.
1812
   Value is zero to push the argument on the stack,
1813
   or a hard register in which to store the argument.
1814
 
1815
   MODE is the argument's machine mode.
1816
   TYPE is the data type of the argument (as a tree).
1817
    This is null for libcalls where that information may
1818
    not be available.
1819
   CUM is a variable of type CUMULATIVE_ARGS which gives info about
1820
    the preceding args and about the function being called.
1821
   NAMED is nonzero if this argument is a named parameter
1822
    (otherwise it is an extra parameter matching an ellipsis).  */
1823
 
1824
static rtx
1825
pdp11_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
1826
                    enum machine_mode mode ATTRIBUTE_UNUSED,
1827
                    const_tree type ATTRIBUTE_UNUSED,
1828
                    bool named ATTRIBUTE_UNUSED)
1829
{
1830
  return NULL_RTX;
1831
}
1832
 
1833
/* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
1834
 
1835
   Update the data in CUM to advance over an argument of mode MODE and
1836
   data type TYPE.  (TYPE is null for libcalls where that information
1837
   may not be available.)  */
1838
 
1839
static void
1840
pdp11_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
1841
                            const_tree type, bool named ATTRIBUTE_UNUSED)
1842
{
1843
  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1844
 
1845
  *cum += (mode != BLKmode
1846
           ? GET_MODE_SIZE (mode)
1847
           : int_size_in_bytes (type));
1848
}
1849
 
1850
/* Make sure everything's fine if we *don't* have an FPU.
1851
   This assumes that putting a register in fixed_regs will keep the
1852
   compiler's mitts completely off it.  We don't bother to zero it out
1853
   of register classes.  Also fix incompatible register naming with
1854
   the UNIX assembler.  */
1855
 
1856
static void
1857
pdp11_conditional_register_usage (void)
1858
{
1859
  int i;
1860
  HARD_REG_SET x;
1861
  if (!TARGET_FPU)
1862
    {
1863
      COPY_HARD_REG_SET (x, reg_class_contents[(int)FPU_REGS]);
1864
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ )
1865
       if (TEST_HARD_REG_BIT (x, i))
1866
        fixed_regs[i] = call_used_regs[i] = 1;
1867
    }
1868
 
1869
  if (TARGET_AC0)
1870
      call_used_regs[AC0_REGNUM] = 1;
1871
  if (TARGET_UNIX_ASM)
1872
    {
1873
      /* Change names of FPU registers for the UNIX assembler.  */
1874
      reg_names[8] = "fr0";
1875
      reg_names[9] = "fr1";
1876
      reg_names[10] = "fr2";
1877
      reg_names[11] = "fr3";
1878
      reg_names[12] = "fr4";
1879
      reg_names[13] = "fr5";
1880
    }
1881
}
1882
 
1883
static section *
1884
pdp11_function_section (tree decl ATTRIBUTE_UNUSED,
1885
                        enum node_frequency freq ATTRIBUTE_UNUSED,
1886
                        bool startup ATTRIBUTE_UNUSED,
1887
                        bool exit ATTRIBUTE_UNUSED)
1888
{
1889
  return NULL;
1890
}
1891
 
1892
/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
1893
 
1894
static bool
1895
pdp11_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1896
{
1897
  return GET_CODE (x) != CONST_DOUBLE || legitimate_const_double_p (x);
1898
}
1899
 
1900
struct gcc_target targetm = TARGET_INITIALIZER;

powered by: WebSVN 2.1.0

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