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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [config/] [iq2000/] [iq2000.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Subroutines used for code generation on Vitesse IQ2000 processors
2
   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GCC is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING.  If not, write to
18
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.  */
20
 
21
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include <signal.h>
25
#include "tm.h"
26
#include "tree.h"
27
#include "rtl.h"
28
#include "regs.h"
29
#include "hard-reg-set.h"
30
#include "real.h"
31
#include "insn-config.h"
32
#include "conditions.h"
33
#include "output.h"
34
#include "insn-attr.h"
35
#include "flags.h"
36
#include "function.h"
37
#include "expr.h"
38
#include "optabs.h"
39
#include "libfuncs.h"
40
#include "recog.h"
41
#include "toplev.h"
42
#include "reload.h"
43
#include "ggc.h"
44
#include "tm_p.h"
45
#include "debug.h"
46
#include "target.h"
47
#include "target-def.h"
48
#include "langhooks.h"
49
 
50
/* Enumeration for all of the relational tests, so that we can build
51
   arrays indexed by the test type, and not worry about the order
52
   of EQ, NE, etc.  */
53
 
54
enum internal_test
55
  {
56
    ITEST_EQ,
57
    ITEST_NE,
58
    ITEST_GT,
59
    ITEST_GE,
60
    ITEST_LT,
61
    ITEST_LE,
62
    ITEST_GTU,
63
    ITEST_GEU,
64
    ITEST_LTU,
65
    ITEST_LEU,
66
    ITEST_MAX
67
  };
68
 
69
struct constant;
70
 
71
 
72
/* Structure to be filled in by compute_frame_size with register
73
   save masks, and offsets for the current function.  */
74
 
75
struct iq2000_frame_info
76
{
77
  long total_size;              /* # bytes that the entire frame takes up.  */
78
  long var_size;                /* # bytes that variables take up.  */
79
  long args_size;               /* # bytes that outgoing arguments take up.  */
80
  long extra_size;              /* # bytes of extra gunk.  */
81
  int  gp_reg_size;             /* # bytes needed to store gp regs.  */
82
  int  fp_reg_size;             /* # bytes needed to store fp regs.  */
83
  long mask;                    /* Mask of saved gp registers.  */
84
  long gp_save_offset;          /* Offset from vfp to store gp registers.  */
85
  long fp_save_offset;          /* Offset from vfp to store fp registers.  */
86
  long gp_sp_offset;            /* Offset from new sp to store gp registers.  */
87
  long fp_sp_offset;            /* Offset from new sp to store fp registers.  */
88
  int  initialized;             /* != 0 if frame size already calculated.  */
89
  int  num_gp;                  /* Number of gp registers saved.  */
90
} iq2000_frame_info;
91
 
92
struct machine_function GTY(())
93
{
94
  /* Current frame information, calculated by compute_frame_size.  */
95
  long total_size;              /* # bytes that the entire frame takes up.  */
96
  long var_size;                /* # bytes that variables take up.  */
97
  long args_size;               /* # bytes that outgoing arguments take up.  */
98
  long extra_size;              /* # bytes of extra gunk.  */
99
  int  gp_reg_size;             /* # bytes needed to store gp regs.  */
100
  int  fp_reg_size;             /* # bytes needed to store fp regs.  */
101
  long mask;                    /* Mask of saved gp registers.  */
102
  long gp_save_offset;          /* Offset from vfp to store gp registers.  */
103
  long fp_save_offset;          /* Offset from vfp to store fp registers.  */
104
  long gp_sp_offset;            /* Offset from new sp to store gp registers.  */
105
  long fp_sp_offset;            /* Offset from new sp to store fp registers.  */
106
  int  initialized;             /* != 0 if frame size already calculated.  */
107
  int  num_gp;                  /* Number of gp registers saved.  */
108
};
109
 
110
/* Global variables for machine-dependent things.  */
111
 
112
/* List of all IQ2000 punctuation characters used by print_operand.  */
113
char iq2000_print_operand_punct[256];
114
 
115
/* The target cpu for optimization and scheduling.  */
116
enum processor_type iq2000_tune;
117
 
118
/* Which instruction set architecture to use.  */
119
int iq2000_isa;
120
 
121
/* Cached operands, and operator to compare for use in set/branch/trap
122
   on condition codes.  */
123
rtx branch_cmp[2];
124
 
125
/* What type of branch to use.  */
126
enum cmp_type branch_type;
127
 
128
/* Local variables.  */
129
 
130
/* The next branch instruction is a branch likely, not branch normal.  */
131
static int iq2000_branch_likely;
132
 
133
/* Count of delay slots and how many are filled.  */
134
static int dslots_load_total;
135
static int dslots_load_filled;
136
static int dslots_jump_total;
137
 
138
/* # of nops needed by previous insn.  */
139
static int dslots_number_nops;
140
 
141
/* Number of 1/2/3 word references to data items (i.e., not jal's).  */
142
static int num_refs[3];
143
 
144
/* Registers to check for load delay.  */
145
static rtx iq2000_load_reg;
146
static rtx iq2000_load_reg2;
147
static rtx iq2000_load_reg3;
148
static rtx iq2000_load_reg4;
149
 
150
/* Mode used for saving/restoring general purpose registers.  */
151
static enum machine_mode gpr_mode;
152
 
153
 
154
/* Initialize the GCC target structure.  */
155
static struct machine_function* iq2000_init_machine_status (void);
156
static bool iq2000_handle_option      (size_t, const char *, int);
157
static void iq2000_select_rtx_section (enum machine_mode, rtx, unsigned HOST_WIDE_INT);
158
static void iq2000_init_builtins      (void);
159
static rtx  iq2000_expand_builtin     (tree, rtx, rtx, enum machine_mode, int);
160
static bool iq2000_return_in_memory   (tree, tree);
161
static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
162
                                           enum machine_mode, tree, int *,
163
                                           int);
164
static bool iq2000_rtx_costs          (rtx, int, int, int *);
165
static int  iq2000_address_cost       (rtx);
166
static void iq2000_select_section     (tree, int, unsigned HOST_WIDE_INT);
167
static bool iq2000_return_in_memory   (tree, tree);
168
static bool iq2000_pass_by_reference  (CUMULATIVE_ARGS *, enum machine_mode,
169
                                       tree, bool);
170
static int  iq2000_arg_partial_bytes  (CUMULATIVE_ARGS *, enum machine_mode,
171
                                       tree, bool);
172
 
173
#undef  TARGET_INIT_BUILTINS
174
#define TARGET_INIT_BUILTINS            iq2000_init_builtins
175
#undef  TARGET_EXPAND_BUILTIN
176
#define TARGET_EXPAND_BUILTIN           iq2000_expand_builtin
177
#undef  TARGET_ASM_SELECT_RTX_SECTION
178
#define TARGET_ASM_SELECT_RTX_SECTION   iq2000_select_rtx_section
179
#undef  TARGET_HANDLE_OPTION
180
#define TARGET_HANDLE_OPTION            iq2000_handle_option
181
#undef  TARGET_RTX_COSTS
182
#define TARGET_RTX_COSTS                iq2000_rtx_costs
183
#undef  TARGET_ADDRESS_COST
184
#define TARGET_ADDRESS_COST             iq2000_address_cost
185
#undef  TARGET_ASM_SELECT_SECTION
186
#define TARGET_ASM_SELECT_SECTION       iq2000_select_section
187
 
188
#undef  TARGET_PROMOTE_FUNCTION_ARGS
189
#define TARGET_PROMOTE_FUNCTION_ARGS    hook_bool_tree_true
190
#undef  TARGET_PROMOTE_FUNCTION_RETURN
191
#define TARGET_PROMOTE_FUNCTION_RETURN  hook_bool_tree_true
192
#undef  TARGET_PROMOTE_PROTOTYPES
193
#define TARGET_PROMOTE_PROTOTYPES       hook_bool_tree_true
194
 
195
#undef  TARGET_RETURN_IN_MEMORY
196
#define TARGET_RETURN_IN_MEMORY         iq2000_return_in_memory
197
#undef  TARGET_PASS_BY_REFERENCE
198
#define TARGET_PASS_BY_REFERENCE        iq2000_pass_by_reference
199
#undef  TARGET_CALLEE_COPIES
200
#define TARGET_CALLEE_COPIES            hook_callee_copies_named
201
#undef  TARGET_ARG_PARTIAL_BYTES
202
#define TARGET_ARG_PARTIAL_BYTES        iq2000_arg_partial_bytes
203
 
204
#undef  TARGET_SETUP_INCOMING_VARARGS
205
#define TARGET_SETUP_INCOMING_VARARGS   iq2000_setup_incoming_varargs
206
#undef  TARGET_STRICT_ARGUMENT_NAMING
207
#define TARGET_STRICT_ARGUMENT_NAMING   hook_bool_CUMULATIVE_ARGS_true
208
 
209
struct gcc_target targetm = TARGET_INITIALIZER;
210
 
211
/* Return nonzero if we split the address into high and low parts.  */
212
 
213
int
214
iq2000_check_split (rtx address, enum machine_mode mode)
215
{
216
  /* This is the same check used in simple_memory_operand.
217
     We use it here because LO_SUM is not offsettable.  */
218
  if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD)
219
    return 0;
220
 
221
  if ((GET_CODE (address) == SYMBOL_REF)
222
      || (GET_CODE (address) == CONST
223
          && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF)
224
      || GET_CODE (address) == LABEL_REF)
225
    return 1;
226
 
227
  return 0;
228
}
229
 
230
/* Return nonzero if REG is valid for MODE.  */
231
 
232
int
233
iq2000_reg_mode_ok_for_base_p (rtx reg,
234
                               enum machine_mode mode ATTRIBUTE_UNUSED,
235
                               int strict)
236
{
237
  return (strict
238
          ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
239
          : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));
240
}
241
 
242
/* Return a nonzero value if XINSN is a legitimate address for a
243
   memory operand of the indicated MODE.  STRICT is nonzero if this
244
   function is called during reload.  */
245
 
246
int
247
iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
248
{
249
  if (TARGET_DEBUG_A_MODE)
250
    {
251
      GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
252
                  strict ? "" : "not ");
253
      GO_DEBUG_RTX (xinsn);
254
    }
255
 
256
  /* Check for constant before stripping off SUBREG, so that we don't
257
     accept (subreg (const_int)) which will fail to reload.  */
258
  if (CONSTANT_ADDRESS_P (xinsn)
259
      && ! (iq2000_check_split (xinsn, mode))
260
      && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn)))
261
    return 1;
262
 
263
  while (GET_CODE (xinsn) == SUBREG)
264
    xinsn = SUBREG_REG (xinsn);
265
 
266
  if (GET_CODE (xinsn) == REG
267
      && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict))
268
    return 1;
269
 
270
  if (GET_CODE (xinsn) == LO_SUM)
271
    {
272
      rtx xlow0 = XEXP (xinsn, 0);
273
      rtx xlow1 = XEXP (xinsn, 1);
274
 
275
      while (GET_CODE (xlow0) == SUBREG)
276
        xlow0 = SUBREG_REG (xlow0);
277
      if (GET_CODE (xlow0) == REG
278
          && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)
279
          && iq2000_check_split (xlow1, mode))
280
        return 1;
281
    }
282
 
283
  if (GET_CODE (xinsn) == PLUS)
284
    {
285
      rtx xplus0 = XEXP (xinsn, 0);
286
      rtx xplus1 = XEXP (xinsn, 1);
287
      enum rtx_code code0;
288
      enum rtx_code code1;
289
 
290
      while (GET_CODE (xplus0) == SUBREG)
291
        xplus0 = SUBREG_REG (xplus0);
292
      code0 = GET_CODE (xplus0);
293
 
294
      while (GET_CODE (xplus1) == SUBREG)
295
        xplus1 = SUBREG_REG (xplus1);
296
      code1 = GET_CODE (xplus1);
297
 
298
      if (code0 == REG
299
          && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))
300
        {
301
          if (code1 == CONST_INT && SMALL_INT (xplus1)
302
              && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */)
303
            return 1;
304
        }
305
    }
306
 
307
  if (TARGET_DEBUG_A_MODE)
308
    GO_PRINTF ("Not a legitimate address\n");
309
 
310
  /* The address was not legitimate.  */
311
  return 0;
312
}
313
 
314
/* Returns an operand string for the given instruction's delay slot,
315
   after updating filled delay slot statistics.
316
 
317
   We assume that operands[0] is the target register that is set.
318
 
319
   In order to check the next insn, most of this functionality is moved
320
   to FINAL_PRESCAN_INSN, and we just set the global variables that
321
   it needs.  */
322
 
323
const char *
324
iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],
325
                        rtx cur_insn)
326
{
327
  rtx set_reg;
328
  enum machine_mode mode;
329
  rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
330
  int num_nops;
331
 
332
  if (type == DELAY_LOAD || type == DELAY_FCMP)
333
    num_nops = 1;
334
 
335
  else
336
    num_nops = 0;
337
 
338
  /* Make sure that we don't put nop's after labels.  */
339
  next_insn = NEXT_INSN (cur_insn);
340
  while (next_insn != 0
341
         && (GET_CODE (next_insn) == NOTE
342
             || GET_CODE (next_insn) == CODE_LABEL))
343
    next_insn = NEXT_INSN (next_insn);
344
 
345
  dslots_load_total += num_nops;
346
  if (TARGET_DEBUG_C_MODE
347
      || type == DELAY_NONE
348
      || operands == 0
349
      || cur_insn == 0
350
      || next_insn == 0
351
      || GET_CODE (next_insn) == CODE_LABEL
352
      || (set_reg = operands[0]) == 0)
353
    {
354
      dslots_number_nops = 0;
355
      iq2000_load_reg  = 0;
356
      iq2000_load_reg2 = 0;
357
      iq2000_load_reg3 = 0;
358
      iq2000_load_reg4 = 0;
359
 
360
      return ret;
361
    }
362
 
363
  set_reg = operands[0];
364
  if (set_reg == 0)
365
    return ret;
366
 
367
  while (GET_CODE (set_reg) == SUBREG)
368
    set_reg = SUBREG_REG (set_reg);
369
 
370
  mode = GET_MODE (set_reg);
371
  dslots_number_nops = num_nops;
372
  iq2000_load_reg = set_reg;
373
  if (GET_MODE_SIZE (mode)
374
      > (unsigned) (UNITS_PER_WORD))
375
    iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);
376
  else
377
    iq2000_load_reg2 = 0;
378
 
379
  return ret;
380
}
381
 
382
/* Determine whether a memory reference takes one (based off of the GP
383
   pointer), two (normal), or three (label + reg) instructions, and bump the
384
   appropriate counter for -mstats.  */
385
 
386
static void
387
iq2000_count_memory_refs (rtx op, int num)
388
{
389
  int additional = 0;
390
  int n_words = 0;
391
  rtx addr, plus0, plus1;
392
  enum rtx_code code0, code1;
393
  int looping;
394
 
395
  if (TARGET_DEBUG_B_MODE)
396
    {
397
      fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");
398
      debug_rtx (op);
399
    }
400
 
401
  /* Skip MEM if passed, otherwise handle movsi of address.  */
402
  addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);
403
 
404
  /* Loop, going through the address RTL.  */
405
  do
406
    {
407
      looping = FALSE;
408
      switch (GET_CODE (addr))
409
        {
410
        case REG:
411
        case CONST_INT:
412
        case LO_SUM:
413
          break;
414
 
415
        case PLUS:
416
          plus0 = XEXP (addr, 0);
417
          plus1 = XEXP (addr, 1);
418
          code0 = GET_CODE (plus0);
419
          code1 = GET_CODE (plus1);
420
 
421
          if (code0 == REG)
422
            {
423
              additional++;
424
              addr = plus1;
425
              looping = 1;
426
              continue;
427
            }
428
 
429
          if (code0 == CONST_INT)
430
            {
431
              addr = plus1;
432
              looping = 1;
433
              continue;
434
            }
435
 
436
          if (code1 == REG)
437
            {
438
              additional++;
439
              addr = plus0;
440
              looping = 1;
441
              continue;
442
            }
443
 
444
          if (code1 == CONST_INT)
445
            {
446
              addr = plus0;
447
              looping = 1;
448
              continue;
449
            }
450
 
451
          if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)
452
            {
453
              addr = plus0;
454
              looping = 1;
455
              continue;
456
            }
457
 
458
          if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)
459
            {
460
              addr = plus1;
461
              looping = 1;
462
              continue;
463
            }
464
 
465
          break;
466
 
467
        case LABEL_REF:
468
          n_words = 2;          /* Always 2 words.  */
469
          break;
470
 
471
        case CONST:
472
          addr = XEXP (addr, 0);
473
          looping = 1;
474
          continue;
475
 
476
        case SYMBOL_REF:
477
          n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;
478
          break;
479
 
480
        default:
481
          break;
482
        }
483
    }
484
  while (looping);
485
 
486
  if (n_words == 0)
487
    return;
488
 
489
  n_words += additional;
490
  if (n_words > 3)
491
    n_words = 3;
492
 
493
  num_refs[n_words-1] += num;
494
}
495
 
496
/* Abort after printing out a specific insn.  */
497
 
498
static void
499
abort_with_insn (rtx insn, const char * reason)
500
{
501
  error (reason);
502
  debug_rtx (insn);
503
  fancy_abort (__FILE__, __LINE__, __FUNCTION__);
504
}
505
 
506
/* Return the appropriate instructions to move one operand to another.  */
507
 
508
const char *
509
iq2000_move_1word (rtx operands[], rtx insn, int unsignedp)
510
{
511
  const char *ret = 0;
512
  rtx op0 = operands[0];
513
  rtx op1 = operands[1];
514
  enum rtx_code code0 = GET_CODE (op0);
515
  enum rtx_code code1 = GET_CODE (op1);
516
  enum machine_mode mode = GET_MODE (op0);
517
  int subreg_offset0 = 0;
518
  int subreg_offset1 = 0;
519
  enum delay_type delay = DELAY_NONE;
520
 
521
  while (code0 == SUBREG)
522
    {
523
      subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
524
                                             GET_MODE (SUBREG_REG (op0)),
525
                                             SUBREG_BYTE (op0),
526
                                             GET_MODE (op0));
527
      op0 = SUBREG_REG (op0);
528
      code0 = GET_CODE (op0);
529
    }
530
 
531
  while (code1 == SUBREG)
532
    {
533
      subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
534
                                             GET_MODE (SUBREG_REG (op1)),
535
                                             SUBREG_BYTE (op1),
536
                                             GET_MODE (op1));
537
      op1 = SUBREG_REG (op1);
538
      code1 = GET_CODE (op1);
539
    }
540
 
541
  /* For our purposes, a condition code mode is the same as SImode.  */
542
  if (mode == CCmode)
543
    mode = SImode;
544
 
545
  if (code0 == REG)
546
    {
547
      int regno0 = REGNO (op0) + subreg_offset0;
548
 
549
      if (code1 == REG)
550
        {
551
          int regno1 = REGNO (op1) + subreg_offset1;
552
 
553
          /* Do not do anything for assigning a register to itself */
554
          if (regno0 == regno1)
555
            ret = "";
556
 
557
          else if (GP_REG_P (regno0))
558
            {
559
              if (GP_REG_P (regno1))
560
                ret = "or\t%0,%%0,%1";
561
            }
562
 
563
        }
564
 
565
      else if (code1 == MEM)
566
        {
567
          delay = DELAY_LOAD;
568
 
569
          if (TARGET_STATS)
570
            iq2000_count_memory_refs (op1, 1);
571
 
572
          if (GP_REG_P (regno0))
573
            {
574
              /* For loads, use the mode of the memory item, instead of the
575
                 target, so zero/sign extend can use this code as well.  */
576
              switch (GET_MODE (op1))
577
                {
578
                default:
579
                  break;
580
                case SFmode:
581
                  ret = "lw\t%0,%1";
582
                  break;
583
                case SImode:
584
                case CCmode:
585
                  ret = "lw\t%0,%1";
586
                  break;
587
                case HImode:
588
                  ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";
589
                  break;
590
                case QImode:
591
                  ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";
592
                  break;
593
                }
594
            }
595
        }
596
 
597
      else if (code1 == CONST_INT
598
               || (code1 == CONST_DOUBLE
599
                   && GET_MODE (op1) == VOIDmode))
600
        {
601
          if (code1 == CONST_DOUBLE)
602
            {
603
              /* This can happen when storing constants into long long
604
                 bitfields.  Just store the least significant word of
605
                 the value.  */
606
              operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
607
            }
608
 
609
          if (INTVAL (op1) == 0)
610
            {
611
              if (GP_REG_P (regno0))
612
                ret = "or\t%0,%%0,%z1";
613
            }
614
         else if (GP_REG_P (regno0))
615
            {
616
              if (SMALL_INT_UNSIGNED (op1))
617
                ret = "ori\t%0,%%0,%x1\t\t\t# %1";
618
              else if (SMALL_INT (op1))
619
                ret = "addiu\t%0,%%0,%1\t\t\t# %1";
620
              else
621
                ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
622
            }
623
        }
624
 
625
      else if (code1 == CONST_DOUBLE && mode == SFmode)
626
        {
627
          if (op1 == CONST0_RTX (SFmode))
628
            {
629
              if (GP_REG_P (regno0))
630
                ret = "or\t%0,%%0,%.";
631
            }
632
 
633
          else
634
            {
635
              delay = DELAY_LOAD;
636
              ret = "li.s\t%0,%1";
637
            }
638
        }
639
 
640
      else if (code1 == LABEL_REF)
641
        {
642
          if (TARGET_STATS)
643
            iq2000_count_memory_refs (op1, 1);
644
 
645
          ret = "la\t%0,%a1";
646
        }
647
 
648
      else if (code1 == SYMBOL_REF || code1 == CONST)
649
        {
650
          if (TARGET_STATS)
651
            iq2000_count_memory_refs (op1, 1);
652
 
653
          ret = "la\t%0,%a1";
654
        }
655
 
656
      else if (code1 == PLUS)
657
        {
658
          rtx add_op0 = XEXP (op1, 0);
659
          rtx add_op1 = XEXP (op1, 1);
660
 
661
          if (GET_CODE (XEXP (op1, 1)) == REG
662
              && GET_CODE (XEXP (op1, 0)) == CONST_INT)
663
            add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0);
664
 
665
          operands[2] = add_op0;
666
          operands[3] = add_op1;
667
          ret = "add%:\t%0,%2,%3";
668
        }
669
 
670
      else if (code1 == HIGH)
671
        {
672
          operands[1] = XEXP (op1, 0);
673
          ret = "lui\t%0,%%hi(%1)";
674
        }
675
    }
676
 
677
  else if (code0 == MEM)
678
    {
679
      if (TARGET_STATS)
680
        iq2000_count_memory_refs (op0, 1);
681
 
682
      if (code1 == REG)
683
        {
684
          int regno1 = REGNO (op1) + subreg_offset1;
685
 
686
          if (GP_REG_P (regno1))
687
            {
688
              switch (mode)
689
                {
690
                case SFmode: ret = "sw\t%1,%0"; break;
691
                case SImode: ret = "sw\t%1,%0"; break;
692
                case HImode: ret = "sh\t%1,%0"; break;
693
                case QImode: ret = "sb\t%1,%0"; break;
694
                default: break;
695
                }
696
            }
697
        }
698
 
699
      else if (code1 == CONST_INT && INTVAL (op1) == 0)
700
        {
701
          switch (mode)
702
            {
703
            case SFmode: ret = "sw\t%z1,%0"; break;
704
            case SImode: ret = "sw\t%z1,%0"; break;
705
            case HImode: ret = "sh\t%z1,%0"; break;
706
            case QImode: ret = "sb\t%z1,%0"; break;
707
            default: break;
708
            }
709
        }
710
 
711
      else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))
712
        {
713
          switch (mode)
714
            {
715
            case SFmode: ret = "sw\t%.,%0"; break;
716
            case SImode: ret = "sw\t%.,%0"; break;
717
            case HImode: ret = "sh\t%.,%0"; break;
718
            case QImode: ret = "sb\t%.,%0"; break;
719
            default: break;
720
            }
721
        }
722
    }
723
 
724
  if (ret == 0)
725
    {
726
      abort_with_insn (insn, "Bad move");
727
      return 0;
728
    }
729
 
730
  if (delay != DELAY_NONE)
731
    return iq2000_fill_delay_slot (ret, delay, operands, insn);
732
 
733
  return ret;
734
}
735
 
736
/* Provide the costs of an addressing mode that contains ADDR.  */
737
 
738
static int
739
iq2000_address_cost (rtx addr)
740
{
741
  switch (GET_CODE (addr))
742
    {
743
    case LO_SUM:
744
      return 1;
745
 
746
    case LABEL_REF:
747
      return 2;
748
 
749
    case CONST:
750
      {
751
        rtx offset = const0_rtx;
752
 
753
        addr = eliminate_constant_term (XEXP (addr, 0), & offset);
754
        if (GET_CODE (addr) == LABEL_REF)
755
          return 2;
756
 
757
        if (GET_CODE (addr) != SYMBOL_REF)
758
          return 4;
759
 
760
        if (! SMALL_INT (offset))
761
          return 2;
762
      }
763
 
764
      /* Fall through.  */
765
 
766
    case SYMBOL_REF:
767
      return SYMBOL_REF_FLAG (addr) ? 1 : 2;
768
 
769
    case PLUS:
770
      {
771
        rtx plus0 = XEXP (addr, 0);
772
        rtx plus1 = XEXP (addr, 1);
773
 
774
        if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
775
          plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);
776
 
777
        if (GET_CODE (plus0) != REG)
778
          break;
779
 
780
        switch (GET_CODE (plus1))
781
          {
782
          case CONST_INT:
783
            return SMALL_INT (plus1) ? 1 : 2;
784
 
785
          case CONST:
786
          case SYMBOL_REF:
787
          case LABEL_REF:
788
          case HIGH:
789
          case LO_SUM:
790
            return iq2000_address_cost (plus1) + 1;
791
 
792
          default:
793
            break;
794
          }
795
      }
796
 
797
    default:
798
      break;
799
    }
800
 
801
  return 4;
802
}
803
 
804
/* Make normal rtx_code into something we can index from an array.  */
805
 
806
static enum internal_test
807
map_test_to_internal_test (enum rtx_code test_code)
808
{
809
  enum internal_test test = ITEST_MAX;
810
 
811
  switch (test_code)
812
    {
813
    case EQ:  test = ITEST_EQ;  break;
814
    case NE:  test = ITEST_NE;  break;
815
    case GT:  test = ITEST_GT;  break;
816
    case GE:  test = ITEST_GE;  break;
817
    case LT:  test = ITEST_LT;  break;
818
    case LE:  test = ITEST_LE;  break;
819
    case GTU: test = ITEST_GTU; break;
820
    case GEU: test = ITEST_GEU; break;
821
    case LTU: test = ITEST_LTU; break;
822
    case LEU: test = ITEST_LEU; break;
823
    default:                    break;
824
    }
825
 
826
  return test;
827
}
828
 
829
/* Generate the code to do a TEST_CODE comparison on two integer values CMP0
830
   and CMP1.  P_INVERT is NULL or ptr if branch needs to reverse its test.
831
   The return value RESULT is:
832
   (reg:SI xx)          The pseudo register the comparison is in
833
 
834
 
835
rtx
836
gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
837
                    int *p_invert)
838
{
839
  struct cmp_info
840
  {
841
    enum rtx_code test_code;    /* Code to use in instruction (LT vs. LTU).  */
842
    int const_low;              /* Low bound of constant we can accept.  */
843
    int const_high;             /* High bound of constant we can accept.  */
844
    int const_add;              /* Constant to add (convert LE -> LT).  */
845
    int reverse_regs;           /* Reverse registers in test.  */
846
    int invert_const;           /* != 0 if invert value if cmp1 is constant.  */
847
    int invert_reg;             /* != 0 if invert value if cmp1 is register.  */
848
    int unsignedp;              /* != 0 for unsigned comparisons.  */
849
  };
850
 
851
  static struct cmp_info info[ (int)ITEST_MAX ] =
852
  {
853
    { XOR,       0,  65535,  0,    0,  0,    0, 0 },  /* EQ  */
854
    { XOR,       0,  65535,  0,    0,  1,   1, 0 }, /* NE  */
855
    { LT,   -32769,  32766,  1,  1,  1,  0, 0 },  /* GT  */
856
    { LT,   -32768,  32767,  0,   0,  1,   1, 0 }, /* GE  */
857
    { LT,   -32768,  32767,  0,   0,  0,    0, 0 },  /* LT  */
858
    { LT,   -32769,  32766,  1,  1,  0,   1, 0 }, /* LE  */
859
    { LTU,  -32769,  32766,  1,  1,  1,  0, 1 }, /* GTU */
860
    { LTU,  -32768,  32767,  0,   0,  1,   1, 1 },        /* GEU */
861
    { LTU,  -32768,  32767,  0,   0,  0,    0, 1 }, /* LTU */
862
    { LTU,  -32769,  32766,  1,  1,  0,   1, 1 },        /* LEU */
863
  };
864
 
865
  enum internal_test test;
866
  enum machine_mode mode;
867
  struct cmp_info *p_info;
868
  int branch_p;
869
  int eqne_p;
870
  int invert;
871
  rtx reg;
872
  rtx reg2;
873
 
874
  test = map_test_to_internal_test (test_code);
875
  gcc_assert (test != ITEST_MAX);
876
 
877
  p_info = &info[(int) test];
878
  eqne_p = (p_info->test_code == XOR);
879
 
880
  mode = GET_MODE (cmp0);
881
  if (mode == VOIDmode)
882
    mode = GET_MODE (cmp1);
883
 
884
  /* Eliminate simple branches.  */
885
  branch_p = (result == 0);
886
  if (branch_p)
887
    {
888
      if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
889
        {
890
          /* Comparisons against zero are simple branches.  */
891
          if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
892
            return 0;
893
 
894
          /* Test for beq/bne.  */
895
          if (eqne_p)
896
            return 0;
897
        }
898
 
899
      /* Allocate a pseudo to calculate the value in.  */
900
      result = gen_reg_rtx (mode);
901
    }
902
 
903
  /* Make sure we can handle any constants given to us.  */
904
  if (GET_CODE (cmp0) == CONST_INT)
905
    cmp0 = force_reg (mode, cmp0);
906
 
907
  if (GET_CODE (cmp1) == CONST_INT)
908
    {
909
      HOST_WIDE_INT value = INTVAL (cmp1);
910
 
911
      if (value < p_info->const_low
912
          || value > p_info->const_high)
913
        cmp1 = force_reg (mode, cmp1);
914
    }
915
 
916
  /* See if we need to invert the result.  */
917
  invert = (GET_CODE (cmp1) == CONST_INT
918
            ? p_info->invert_const : p_info->invert_reg);
919
 
920
  if (p_invert != (int *)0)
921
    {
922
      *p_invert = invert;
923
      invert = 0;
924
    }
925
 
926
  /* Comparison to constants, may involve adding 1 to change a LT into LE.
927
     Comparison between two registers, may involve switching operands.  */
928
  if (GET_CODE (cmp1) == CONST_INT)
929
    {
930
      if (p_info->const_add != 0)
931
        {
932
          HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
933
 
934
          /* If modification of cmp1 caused overflow,
935
             we would get the wrong answer if we follow the usual path;
936
             thus, x > 0xffffffffU would turn into x > 0U.  */
937
          if ((p_info->unsignedp
938
               ? (unsigned HOST_WIDE_INT) new >
939
               (unsigned HOST_WIDE_INT) INTVAL (cmp1)
940
               : new > INTVAL (cmp1))
941
              != (p_info->const_add > 0))
942
            {
943
              /* This test is always true, but if INVERT is true then
944
                 the result of the test needs to be inverted so 0 should
945
                 be returned instead.  */
946
              emit_move_insn (result, invert ? const0_rtx : const_true_rtx);
947
              return result;
948
            }
949
          else
950
            cmp1 = GEN_INT (new);
951
        }
952
    }
953
 
954
  else if (p_info->reverse_regs)
955
    {
956
      rtx temp = cmp0;
957
      cmp0 = cmp1;
958
      cmp1 = temp;
959
    }
960
 
961
  if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
962
    reg = cmp0;
963
  else
964
    {
965
      reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
966
      convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);
967
    }
968
 
969
  if (test == ITEST_NE)
970
    {
971
      convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);
972
      if (p_invert != NULL)
973
        *p_invert = 0;
974
      invert = 0;
975
    }
976
 
977
  else if (test == ITEST_EQ)
978
    {
979
      reg2 = invert ? gen_reg_rtx (mode) : result;
980
      convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0);
981
      reg = reg2;
982
    }
983
 
984
  if (invert)
985
    {
986
      rtx one;
987
 
988
      one = const1_rtx;
989
      convert_move (result, gen_rtx_XOR (mode, reg, one), 0);
990
    }
991
 
992
  return result;
993
}
994
 
995
/* Emit the common code for doing conditional branches.
996
   operand[0] is the label to jump to.
997
   The comparison operands are saved away by cmp{si,di,sf,df}.  */
998
 
999
void
1000
gen_conditional_branch (rtx operands[], enum rtx_code test_code)
1001
{
1002
  enum cmp_type type = branch_type;
1003
  rtx cmp0 = branch_cmp[0];
1004
  rtx cmp1 = branch_cmp[1];
1005
  enum machine_mode mode;
1006
  rtx reg;
1007
  int invert;
1008
  rtx label1, label2;
1009
 
1010
  switch (type)
1011
    {
1012
    case CMP_SI:
1013
    case CMP_DI:
1014
      mode = type == CMP_SI ? SImode : DImode;
1015
      invert = 0;
1016
      reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
1017
 
1018
      if (reg)
1019
        {
1020
          cmp0 = reg;
1021
          cmp1 = const0_rtx;
1022
          test_code = NE;
1023
        }
1024
      else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
1025
        /* We don't want to build a comparison against a nonzero
1026
           constant.  */
1027
        cmp1 = force_reg (mode, cmp1);
1028
 
1029
      break;
1030
 
1031
    case CMP_SF:
1032
    case CMP_DF:
1033
      reg = gen_reg_rtx (CCmode);
1034
 
1035
      /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0.  */
1036
      emit_insn (gen_rtx_SET (VOIDmode, reg,
1037
                              gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
1038
                                              CCmode, cmp0, cmp1)));
1039
 
1040
      test_code = test_code == NE ? EQ : NE;
1041
      mode = CCmode;
1042
      cmp0 = reg;
1043
      cmp1 = const0_rtx;
1044
      invert = 0;
1045
      break;
1046
 
1047
    default:
1048
      abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
1049
                       "bad test");
1050
    }
1051
 
1052
  /* Generate the branch.  */
1053
  label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
1054
  label2 = pc_rtx;
1055
 
1056
  if (invert)
1057
    {
1058
      label2 = label1;
1059
      label1 = pc_rtx;
1060
    }
1061
 
1062
  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1063
                               gen_rtx_IF_THEN_ELSE (VOIDmode,
1064
                                                     gen_rtx_fmt_ee (test_code,
1065
                                                                     mode,
1066
                                                                     cmp0, cmp1),
1067
                                                     label1, label2)));
1068
}
1069
 
1070
/* Initialize CUM for a function FNTYPE.  */
1071
 
1072
void
1073
init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1074
                      rtx libname ATTRIBUTE_UNUSED)
1075
{
1076
  static CUMULATIVE_ARGS zero_cum;
1077
  tree param;
1078
  tree next_param;
1079
 
1080
  if (TARGET_DEBUG_D_MODE)
1081
    {
1082
      fprintf (stderr,
1083
               "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);
1084
 
1085
      if (!fntype)
1086
        fputc ('\n', stderr);
1087
 
1088
      else
1089
        {
1090
          tree ret_type = TREE_TYPE (fntype);
1091
 
1092
          fprintf (stderr, ", fntype code = %s, ret code = %s\n",
1093
                   tree_code_name[(int)TREE_CODE (fntype)],
1094
                   tree_code_name[(int)TREE_CODE (ret_type)]);
1095
        }
1096
    }
1097
 
1098
  *cum = zero_cum;
1099
 
1100
  /* Determine if this function has variable arguments.  This is
1101
     indicated by the last argument being 'void_type_mode' if there
1102
     are no variable arguments.  The standard IQ2000 calling sequence
1103
     passes all arguments in the general purpose registers in this case.  */
1104
 
1105
  for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
1106
       param != 0; param = next_param)
1107
    {
1108
      next_param = TREE_CHAIN (param);
1109
      if (next_param == 0 && TREE_VALUE (param) != void_type_node)
1110
        cum->gp_reg_found = 1;
1111
    }
1112
}
1113
 
1114
/* Advance the argument of type TYPE and mode MODE to the next argument
1115
   position in CUM.  */
1116
 
1117
void
1118
function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1119
                      int named)
1120
{
1121
  if (TARGET_DEBUG_D_MODE)
1122
    {
1123
      fprintf (stderr,
1124
               "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1125
               cum->gp_reg_found, cum->arg_number, cum->arg_words,
1126
               GET_MODE_NAME (mode));
1127
      fprintf (stderr, "%p", (void *) type);
1128
      fprintf (stderr, ", %d )\n\n", named);
1129
    }
1130
 
1131
  cum->arg_number++;
1132
  switch (mode)
1133
    {
1134
    case VOIDmode:
1135
      break;
1136
 
1137
    default:
1138
      gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1139
                  || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1140
 
1141
      cum->gp_reg_found = 1;
1142
      cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1143
                         / UNITS_PER_WORD);
1144
      break;
1145
 
1146
    case BLKmode:
1147
      cum->gp_reg_found = 1;
1148
      cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1149
                         / UNITS_PER_WORD);
1150
      break;
1151
 
1152
    case SFmode:
1153
      cum->arg_words ++;
1154
      if (! cum->gp_reg_found && cum->arg_number <= 2)
1155
        cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1156
      break;
1157
 
1158
    case DFmode:
1159
      cum->arg_words += 2;
1160
      if (! cum->gp_reg_found && cum->arg_number <= 2)
1161
        cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1162
      break;
1163
 
1164
    case DImode:
1165
      cum->gp_reg_found = 1;
1166
      cum->arg_words += 2;
1167
      break;
1168
 
1169
    case QImode:
1170
    case HImode:
1171
    case SImode:
1172
      cum->gp_reg_found = 1;
1173
      cum->arg_words ++;
1174
      break;
1175
    }
1176
}
1177
 
1178
/* Return an RTL expression containing the register for the given mode MODE
1179
   and type TYPE in CUM, or 0 if the argument is to be passed on the stack.  */
1180
 
1181
struct rtx_def *
1182
function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1183
              int named)
1184
{
1185
  rtx ret;
1186
  int regbase = -1;
1187
  int bias = 0;
1188
  unsigned int *arg_words = &cum->arg_words;
1189
  int struct_p = (type != 0
1190
                  && (TREE_CODE (type) == RECORD_TYPE
1191
                      || TREE_CODE (type) == UNION_TYPE
1192
                      || TREE_CODE (type) == QUAL_UNION_TYPE));
1193
 
1194
  if (TARGET_DEBUG_D_MODE)
1195
    {
1196
      fprintf (stderr,
1197
               "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1198
               cum->gp_reg_found, cum->arg_number, cum->arg_words,
1199
               GET_MODE_NAME (mode));
1200
      fprintf (stderr, "%p", (void *) type);
1201
      fprintf (stderr, ", %d ) = ", named);
1202
    }
1203
 
1204
 
1205
  cum->last_arg_fp = 0;
1206
  switch (mode)
1207
    {
1208
    case SFmode:
1209
      regbase = GP_ARG_FIRST;
1210
      break;
1211
 
1212
    case DFmode:
1213
      cum->arg_words += cum->arg_words & 1;
1214
 
1215
      regbase = GP_ARG_FIRST;
1216
      break;
1217
 
1218
    default:
1219
      gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1220
                  || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1221
 
1222
      /* Drops through.  */
1223
    case BLKmode:
1224
      if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
1225
        cum->arg_words += (cum->arg_words & 1);
1226
      regbase = GP_ARG_FIRST;
1227
      break;
1228
 
1229
    case VOIDmode:
1230
    case QImode:
1231
    case HImode:
1232
    case SImode:
1233
      regbase = GP_ARG_FIRST;
1234
      break;
1235
 
1236
    case DImode:
1237
      cum->arg_words += (cum->arg_words & 1);
1238
      regbase = GP_ARG_FIRST;
1239
    }
1240
 
1241
  if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
1242
    {
1243
      if (TARGET_DEBUG_D_MODE)
1244
        fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");
1245
 
1246
      ret = 0;
1247
    }
1248
  else
1249
    {
1250
      gcc_assert (regbase != -1);
1251
 
1252
      if (! type || TREE_CODE (type) != RECORD_TYPE
1253
          || ! named  || ! TYPE_SIZE_UNIT (type)
1254
          || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1255
        ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1256
      else
1257
        {
1258
          tree field;
1259
 
1260
          for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
1261
            if (TREE_CODE (field) == FIELD_DECL
1262
                && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1263
                && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
1264
                && host_integerp (bit_position (field), 0)
1265
                && int_bit_position (field) % BITS_PER_WORD == 0)
1266
              break;
1267
 
1268
          /* If the whole struct fits a DFmode register,
1269
             we don't need the PARALLEL.  */
1270
          if (! field || mode == DFmode)
1271
            ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1272
          else
1273
            {
1274
              unsigned int chunks;
1275
              HOST_WIDE_INT bitpos;
1276
              unsigned int regno;
1277
              unsigned int i;
1278
 
1279
              /* ??? If this is a packed structure, then the last hunk won't
1280
                 be 64 bits.  */
1281
              chunks
1282
                = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
1283
              if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS)
1284
                chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias;
1285
 
1286
              /* Assign_parms checks the mode of ENTRY_PARM, so we must
1287
                 use the actual mode here.  */
1288
              ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks));
1289
 
1290
              bitpos = 0;
1291
              regno = regbase + *arg_words + bias;
1292
              field = TYPE_FIELDS (type);
1293
              for (i = 0; i < chunks; i++)
1294
                {
1295
                  rtx reg;
1296
 
1297
                  for (; field; field = TREE_CHAIN (field))
1298
                    if (TREE_CODE (field) == FIELD_DECL
1299
                        && int_bit_position (field) >= bitpos)
1300
                      break;
1301
 
1302
                  if (field
1303
                      && int_bit_position (field) == bitpos
1304
                      && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1305
                      && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
1306
                    reg = gen_rtx_REG (DFmode, regno++);
1307
                  else
1308
                    reg = gen_rtx_REG (word_mode, regno);
1309
 
1310
                  XVECEXP (ret, 0, i)
1311
                    = gen_rtx_EXPR_LIST (VOIDmode, reg,
1312
                                         GEN_INT (bitpos / BITS_PER_UNIT));
1313
 
1314
                  bitpos += 64;
1315
                  regno++;
1316
                }
1317
            }
1318
        }
1319
 
1320
      if (TARGET_DEBUG_D_MODE)
1321
        fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias],
1322
                 struct_p ? ", [struct]" : "");
1323
    }
1324
 
1325
  /* We will be called with a mode of VOIDmode after the last argument
1326
     has been seen.  Whatever we return will be passed to the call
1327
     insn.  If we need any shifts for small structures, return them in
1328
     a PARALLEL.  */
1329
  if (mode == VOIDmode)
1330
    {
1331
      if (cum->num_adjusts > 0)
1332
        ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
1333
                       gen_rtvec_v (cum->num_adjusts, cum->adjust));
1334
    }
1335
 
1336
  return ret;
1337
}
1338
 
1339
static int
1340
iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1341
                          tree type ATTRIBUTE_UNUSED,
1342
                          bool named ATTRIBUTE_UNUSED)
1343
{
1344
  if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
1345
    {
1346
      if (TARGET_DEBUG_D_MODE)
1347
        fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
1348
      return UNITS_PER_WORD;
1349
    }
1350
 
1351
  return 0;
1352
}
1353
 
1354
/* Implement va_start.  */
1355
 
1356
void
1357
iq2000_va_start (tree valist, rtx nextarg)
1358
{
1359
  int int_arg_words;
1360
  /* Find out how many non-float named formals.  */
1361
  int gpr_save_area_size;
1362
  /* Note UNITS_PER_WORD is 4 bytes.  */
1363
  int_arg_words = current_function_args_info.arg_words;
1364
 
1365
  if (int_arg_words < 8 )
1366
    /* Adjust for the prologue's economy measure.  */
1367
    gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
1368
  else
1369
    gpr_save_area_size = 0;
1370
 
1371
  /* Everything is in the GPR save area, or in the overflow
1372
     area which is contiguous with it.  */
1373
  nextarg = plus_constant (nextarg, - gpr_save_area_size);
1374
  std_expand_builtin_va_start (valist, nextarg);
1375
}
1376
 
1377
/* Allocate a chunk of memory for per-function machine-dependent data.  */
1378
 
1379
static struct machine_function *
1380
iq2000_init_machine_status (void)
1381
{
1382
  struct machine_function *f;
1383
 
1384
  f = ggc_alloc_cleared (sizeof (struct machine_function));
1385
 
1386
  return f;
1387
}
1388
 
1389
/* Implement TARGET_HANDLE_OPTION.  */
1390
 
1391
static bool
1392
iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
1393
{
1394
  switch (code)
1395
    {
1396
    case OPT_mcpu_:
1397
      if (strcmp (arg, "iq10") == 0)
1398
        iq2000_tune = PROCESSOR_IQ10;
1399
      else if (strcmp (arg, "iq2000") == 0)
1400
        iq2000_tune = PROCESSOR_IQ2000;
1401
      else
1402
        return false;
1403
      return true;
1404
 
1405
    case OPT_march_:
1406
      /* This option has no effect at the moment.  */
1407
      return (strcmp (arg, "default") == 0
1408
              || strcmp (arg, "DEFAULT") == 0
1409
              || strcmp (arg, "iq2000") == 0);
1410
 
1411
    default:
1412
      return true;
1413
    }
1414
}
1415
 
1416
/* Detect any conflicts in the switches.  */
1417
 
1418
void
1419
override_options (void)
1420
{
1421
  target_flags &= ~MASK_GPOPT;
1422
 
1423
  iq2000_isa = IQ2000_ISA_DEFAULT;
1424
 
1425
  /* Identify the processor type.  */
1426
 
1427
  iq2000_print_operand_punct['?'] = 1;
1428
  iq2000_print_operand_punct['#'] = 1;
1429
  iq2000_print_operand_punct['&'] = 1;
1430
  iq2000_print_operand_punct['!'] = 1;
1431
  iq2000_print_operand_punct['*'] = 1;
1432
  iq2000_print_operand_punct['@'] = 1;
1433
  iq2000_print_operand_punct['.'] = 1;
1434
  iq2000_print_operand_punct['('] = 1;
1435
  iq2000_print_operand_punct[')'] = 1;
1436
  iq2000_print_operand_punct['['] = 1;
1437
  iq2000_print_operand_punct[']'] = 1;
1438
  iq2000_print_operand_punct['<'] = 1;
1439
  iq2000_print_operand_punct['>'] = 1;
1440
  iq2000_print_operand_punct['{'] = 1;
1441
  iq2000_print_operand_punct['}'] = 1;
1442
  iq2000_print_operand_punct['^'] = 1;
1443
  iq2000_print_operand_punct['$'] = 1;
1444
  iq2000_print_operand_punct['+'] = 1;
1445
  iq2000_print_operand_punct['~'] = 1;
1446
 
1447
  /* Save GPR registers in word_mode sized hunks.  word_mode hasn't been
1448
     initialized yet, so we can't use that here.  */
1449
  gpr_mode = SImode;
1450
 
1451
  /* Function to allocate machine-dependent function status.  */
1452
  init_machine_status = iq2000_init_machine_status;
1453
}
1454
 
1455
/* The arg pointer (which is eliminated) points to the virtual frame pointer,
1456
   while the frame pointer (which may be eliminated) points to the stack
1457
   pointer after the initial adjustments.  */
1458
 
1459
HOST_WIDE_INT
1460
iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset)
1461
{
1462
  rtx offset2 = const0_rtx;
1463
  rtx reg = eliminate_constant_term (addr, & offset2);
1464
 
1465
  if (offset == 0)
1466
    offset = INTVAL (offset2);
1467
 
1468
  if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
1469
      || reg == hard_frame_pointer_rtx)
1470
    {
1471
      HOST_WIDE_INT frame_size = (!cfun->machine->initialized)
1472
                                  ? compute_frame_size (get_frame_size ())
1473
                                  : cfun->machine->total_size;
1474
 
1475
      offset = offset - frame_size;
1476
    }
1477
 
1478
  return offset;
1479
}
1480
 
1481
/* If defined, a C statement to be executed just prior to the output of
1482
   assembler code for INSN, to modify the extracted operands so they will be
1483
   output differently.
1484
 
1485
   Here the argument OPVEC is the vector containing the operands extracted
1486
   from INSN, and NOPERANDS is the number of elements of the vector which
1487
   contain meaningful data for this insn.  The contents of this vector are
1488
   what will be used to convert the insn template into assembler code, so you
1489
   can change the assembler output by changing the contents of the vector.
1490
 
1491
   We use it to check if the current insn needs a nop in front of it because
1492
   of load delays, and also to update the delay slot statistics.  */
1493
 
1494
void
1495
final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED,
1496
                    int noperands ATTRIBUTE_UNUSED)
1497
{
1498
  if (dslots_number_nops > 0)
1499
    {
1500
      rtx pattern = PATTERN (insn);
1501
      int length = get_attr_length (insn);
1502
 
1503
      /* Do we need to emit a NOP?  */
1504
      if (length == 0
1505
          || (iq2000_load_reg != 0 && reg_mentioned_p (iq2000_load_reg,  pattern))
1506
          || (iq2000_load_reg2 != 0 && reg_mentioned_p (iq2000_load_reg2, pattern))
1507
          || (iq2000_load_reg3 != 0 && reg_mentioned_p (iq2000_load_reg3, pattern))
1508
          || (iq2000_load_reg4 != 0
1509
              && reg_mentioned_p (iq2000_load_reg4, pattern)))
1510
        fputs ("\tnop\n", asm_out_file);
1511
 
1512
      else
1513
        dslots_load_filled ++;
1514
 
1515
      while (--dslots_number_nops > 0)
1516
        fputs ("\tnop\n", asm_out_file);
1517
 
1518
      iq2000_load_reg = 0;
1519
      iq2000_load_reg2 = 0;
1520
      iq2000_load_reg3 = 0;
1521
      iq2000_load_reg4 = 0;
1522
    }
1523
 
1524
  if (   (GET_CODE (insn) == JUMP_INSN
1525
       || GET_CODE (insn) == CALL_INSN
1526
       || (GET_CODE (PATTERN (insn)) == RETURN))
1527
           && NEXT_INSN (PREV_INSN (insn)) == insn)
1528
    {
1529
      rtx nop_insn = emit_insn_after (gen_nop (), insn);
1530
 
1531
      INSN_ADDRESSES_NEW (nop_insn, -1);
1532
    }
1533
 
1534
  if (TARGET_STATS
1535
      && (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN))
1536
    dslots_jump_total ++;
1537
}
1538
 
1539
/* Return the bytes needed to compute the frame pointer from the current
1540
   stack pointer where SIZE is the # of var. bytes allocated.
1541
 
1542
   IQ2000 stack frames look like:
1543
 
1544
             Before call                        After call
1545
        +-----------------------+       +-----------------------+
1546
   high |                       |       |                       |
1547
   mem. |                       |       |                       |
1548
        |  caller's temps.      |       |  caller's temps.      |
1549
        |                       |       |                       |
1550
        +-----------------------+       +-----------------------+
1551
        |                       |       |                       |
1552
        |  arguments on stack.  |       |  arguments on stack.  |
1553
        |                       |       |                       |
1554
        +-----------------------+       +-----------------------+
1555
        |  4 words to save      |       |  4 words to save      |
1556
        |  arguments passed     |       |  arguments passed     |
1557
        |  in registers, even   |       |  in registers, even   |
1558
    SP->|  if not passed.       |  VFP->|  if not passed.       |
1559
        +-----------------------+       +-----------------------+
1560
                                        |                       |
1561
                                        |  fp register save     |
1562
                                        |                       |
1563
                                        +-----------------------+
1564
                                        |                       |
1565
                                        |  gp register save     |
1566
                                        |                       |
1567
                                        +-----------------------+
1568
                                        |                       |
1569
                                        |  local variables      |
1570
                                        |                       |
1571
                                        +-----------------------+
1572
                                        |                       |
1573
                                        |  alloca allocations   |
1574
                                        |                       |
1575
                                        +-----------------------+
1576
                                        |                       |
1577
                                        |  GP save for V.4 abi  |
1578
                                        |                       |
1579
                                        +-----------------------+
1580
                                        |                       |
1581
                                        |  arguments on stack   |
1582
                                        |                       |
1583
                                        +-----------------------+
1584
                                        |  4 words to save      |
1585
                                        |  arguments passed     |
1586
                                        |  in registers, even   |
1587
   low                              SP->|  if not passed.       |
1588
   memory                               +-----------------------+  */
1589
 
1590
HOST_WIDE_INT
1591
compute_frame_size (HOST_WIDE_INT size)
1592
{
1593
  int regno;
1594
  HOST_WIDE_INT total_size;     /* # bytes that the entire frame takes up.  */
1595
  HOST_WIDE_INT var_size;       /* # bytes that variables take up.  */
1596
  HOST_WIDE_INT args_size;      /* # bytes that outgoing arguments take up.  */
1597
  HOST_WIDE_INT extra_size;     /* # extra bytes.  */
1598
  HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding.  */
1599
  HOST_WIDE_INT gp_reg_size;    /* # bytes needed to store gp regs.  */
1600
  HOST_WIDE_INT fp_reg_size;    /* # bytes needed to store fp regs.  */
1601
  long mask;                    /* mask of saved gp registers.  */
1602
  int  fp_inc;                  /* 1 or 2 depending on the size of fp regs.  */
1603
  long fp_bits;                 /* bitmask to use for each fp register.  */
1604
 
1605
  gp_reg_size = 0;
1606
  fp_reg_size = 0;
1607
  mask = 0;
1608
  extra_size = IQ2000_STACK_ALIGN ((0));
1609
  var_size = IQ2000_STACK_ALIGN (size);
1610
  args_size = IQ2000_STACK_ALIGN (current_function_outgoing_args_size);
1611
 
1612
  /* If a function dynamically allocates the stack and
1613
     has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space.  */
1614
  if (args_size == 0 && current_function_calls_alloca)
1615
    args_size = 4 * UNITS_PER_WORD;
1616
 
1617
  total_size = var_size + args_size + extra_size;
1618
 
1619
  /* Calculate space needed for gp registers.  */
1620
  for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1621
    {
1622
      if (MUST_SAVE_REGISTER (regno))
1623
        {
1624
          gp_reg_size += GET_MODE_SIZE (gpr_mode);
1625
          mask |= 1L << (regno - GP_REG_FIRST);
1626
        }
1627
    }
1628
 
1629
  /* We need to restore these for the handler.  */
1630
  if (current_function_calls_eh_return)
1631
    {
1632
      unsigned int i;
1633
 
1634
      for (i = 0; ; ++i)
1635
        {
1636
          regno = EH_RETURN_DATA_REGNO (i);
1637
          if (regno == (int) INVALID_REGNUM)
1638
            break;
1639
          gp_reg_size += GET_MODE_SIZE (gpr_mode);
1640
          mask |= 1L << (regno - GP_REG_FIRST);
1641
        }
1642
    }
1643
 
1644
  fp_inc = 2;
1645
  fp_bits = 3;
1646
  gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size);
1647
  total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size);
1648
 
1649
  /* The gp reg is caller saved, so there is no need for leaf routines
1650
     (total_size == extra_size) to save the gp reg.  */
1651
  if (total_size == extra_size
1652
      && ! profile_flag)
1653
    total_size = extra_size = 0;
1654
 
1655
  total_size += IQ2000_STACK_ALIGN (current_function_pretend_args_size);
1656
 
1657
  /* Save other computed information.  */
1658
  cfun->machine->total_size = total_size;
1659
  cfun->machine->var_size = var_size;
1660
  cfun->machine->args_size = args_size;
1661
  cfun->machine->extra_size = extra_size;
1662
  cfun->machine->gp_reg_size = gp_reg_size;
1663
  cfun->machine->fp_reg_size = fp_reg_size;
1664
  cfun->machine->mask = mask;
1665
  cfun->machine->initialized = reload_completed;
1666
  cfun->machine->num_gp = gp_reg_size / UNITS_PER_WORD;
1667
 
1668
  if (mask)
1669
    {
1670
      unsigned long offset;
1671
 
1672
      offset = (args_size + extra_size + var_size
1673
                + gp_reg_size - GET_MODE_SIZE (gpr_mode));
1674
 
1675
      cfun->machine->gp_sp_offset = offset;
1676
      cfun->machine->gp_save_offset = offset - total_size;
1677
    }
1678
  else
1679
    {
1680
      cfun->machine->gp_sp_offset = 0;
1681
      cfun->machine->gp_save_offset = 0;
1682
    }
1683
 
1684
  cfun->machine->fp_sp_offset = 0;
1685
  cfun->machine->fp_save_offset = 0;
1686
 
1687
  /* Ok, we're done.  */
1688
  return total_size;
1689
}
1690
 
1691
/* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
1692
   pointer, argument pointer, or return address pointer.  TO is either
1693
   the stack pointer or hard frame pointer.  */
1694
 
1695
int
1696
iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
1697
{
1698
  int offset;
1699
 
1700
  compute_frame_size (get_frame_size ());
1701
  if ((from) == FRAME_POINTER_REGNUM)
1702
    (offset) = 0;
1703
  else if ((from) == ARG_POINTER_REGNUM)
1704
    (offset) = (cfun->machine->total_size);
1705
  else if ((from) == RETURN_ADDRESS_POINTER_REGNUM)
1706
    {
1707
      if (leaf_function_p ())
1708
        (offset) = 0;
1709
      else (offset) = cfun->machine->gp_sp_offset
1710
             + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
1711
                * (BYTES_BIG_ENDIAN != 0));
1712
    }
1713
 
1714
  return offset;
1715
}
1716
 
1717
/* Common code to emit the insns (or to write the instructions to a file)
1718
   to save/restore registers.
1719
   Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg)
1720
   is not modified within save_restore_insns.  */
1721
 
1722
#define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
1723
 
1724
/* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM
1725
   and return an rtl expression for the register.  Write the assembly
1726
   instructions directly to FILE if it is not null, otherwise emit them as
1727
   rtl.
1728
 
1729
   This function is a subroutine of save_restore_insns.  It is used when
1730
   OFFSET is too large to add in a single instruction.  */
1731
 
1732
static rtx
1733
iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset)
1734
{
1735
  rtx reg = gen_rtx_REG (Pmode, IQ2000_TEMP2_REGNUM);
1736
  rtx offset_rtx = GEN_INT (offset);
1737
 
1738
  emit_move_insn (reg, offset_rtx);
1739
  emit_insn (gen_addsi3 (reg, reg, stack_pointer_rtx));
1740
  return reg;
1741
}
1742
 
1743
/* Make INSN frame related and note that it performs the frame-related
1744
   operation DWARF_PATTERN.  */
1745
 
1746
static void
1747
iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern)
1748
{
1749
  RTX_FRAME_RELATED_P (insn) = 1;
1750
  REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1751
                                      dwarf_pattern,
1752
                                      REG_NOTES (insn));
1753
}
1754
 
1755
/* Emit a move instruction that stores REG in MEM.  Make the instruction
1756
   frame related and note that it stores REG at (SP + OFFSET).  */
1757
 
1758
static void
1759
iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset)
1760
{
1761
  rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
1762
  rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
1763
 
1764
  iq2000_annotate_frame_insn (emit_move_insn (mem, reg),
1765
                            gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
1766
}
1767
 
1768
/* Emit instructions to save/restore registers, as determined by STORE_P.  */
1769
 
1770
static void
1771
save_restore_insns (int store_p)
1772
{
1773
  long mask = cfun->machine->mask;
1774
  int regno;
1775
  rtx base_reg_rtx;
1776
  HOST_WIDE_INT base_offset;
1777
  HOST_WIDE_INT gp_offset;
1778
  HOST_WIDE_INT end_offset;
1779
 
1780
  gcc_assert (!frame_pointer_needed
1781
              || BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST));
1782
 
1783
  if (mask == 0)
1784
    {
1785
      base_reg_rtx = 0, base_offset  = 0;
1786
      return;
1787
    }
1788
 
1789
  /* Save registers starting from high to low.  The debuggers prefer at least
1790
     the return register be stored at func+4, and also it allows us not to
1791
     need a nop in the epilog if at least one register is reloaded in
1792
     addition to return address.  */
1793
 
1794
  /* Save GP registers if needed.  */
1795
  /* Pick which pointer to use as a base register.  For small frames, just
1796
     use the stack pointer.  Otherwise, use a temporary register.  Save 2
1797
     cycles if the save area is near the end of a large frame, by reusing
1798
     the constant created in the prologue/epilogue to adjust the stack
1799
     frame.  */
1800
 
1801
  gp_offset = cfun->machine->gp_sp_offset;
1802
  end_offset
1803
    = gp_offset - (cfun->machine->gp_reg_size
1804
                   - GET_MODE_SIZE (gpr_mode));
1805
 
1806
  if (gp_offset < 0 || end_offset < 0)
1807
    internal_error
1808
      ("gp_offset (%ld) or end_offset (%ld) is less than zero",
1809
       (long) gp_offset, (long) end_offset);
1810
 
1811
  else if (gp_offset < 32768)
1812
    base_reg_rtx = stack_pointer_rtx, base_offset  = 0;
1813
  else
1814
    {
1815
      int regno;
1816
      int reg_save_count = 0;
1817
 
1818
      for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
1819
        if (BITSET_P (mask, regno - GP_REG_FIRST)) reg_save_count += 1;
1820
      base_offset = gp_offset - ((reg_save_count - 1) * 4);
1821
      base_reg_rtx = iq2000_add_large_offset_to_sp (base_offset);
1822
    }
1823
 
1824
  for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
1825
    {
1826
      if (BITSET_P (mask, regno - GP_REG_FIRST))
1827
        {
1828
          rtx reg_rtx;
1829
          rtx mem_rtx
1830
            = gen_rtx_MEM (gpr_mode,
1831
                       gen_rtx_PLUS (Pmode, base_reg_rtx,
1832
                                GEN_INT (gp_offset - base_offset)));
1833
 
1834
          reg_rtx = gen_rtx_REG (gpr_mode, regno);
1835
 
1836
          if (store_p)
1837
            iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
1838
          else
1839
            {
1840
              emit_move_insn (reg_rtx, mem_rtx);
1841
            }
1842
          gp_offset -= GET_MODE_SIZE (gpr_mode);
1843
        }
1844
    }
1845
}
1846
 
1847
/* Expand the prologue into a bunch of separate insns.  */
1848
 
1849
void
1850
iq2000_expand_prologue (void)
1851
{
1852
  int regno;
1853
  HOST_WIDE_INT tsize;
1854
  int last_arg_is_vararg_marker = 0;
1855
  tree fndecl = current_function_decl;
1856
  tree fntype = TREE_TYPE (fndecl);
1857
  tree fnargs = DECL_ARGUMENTS (fndecl);
1858
  rtx next_arg_reg;
1859
  int i;
1860
  tree next_arg;
1861
  tree cur_arg;
1862
  CUMULATIVE_ARGS args_so_far;
1863
  int store_args_on_stack = (iq2000_can_use_return_insn ());
1864
 
1865
  /* If struct value address is treated as the first argument.  */
1866
  if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
1867
      && ! current_function_returns_pcc_struct
1868
      && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
1869
    {
1870
      tree type = build_pointer_type (fntype);
1871
      tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
1872
 
1873
      DECL_ARG_TYPE (function_result_decl) = type;
1874
      TREE_CHAIN (function_result_decl) = fnargs;
1875
      fnargs = function_result_decl;
1876
    }
1877
 
1878
  /* For arguments passed in registers, find the register number
1879
     of the first argument in the variable part of the argument list,
1880
     otherwise GP_ARG_LAST+1.  Note also if the last argument is
1881
     the varargs special argument, and treat it as part of the
1882
     variable arguments.
1883
 
1884
     This is only needed if store_args_on_stack is true.  */
1885
  INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
1886
  regno = GP_ARG_FIRST;
1887
 
1888
  for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
1889
    {
1890
      tree passed_type = DECL_ARG_TYPE (cur_arg);
1891
      enum machine_mode passed_mode = TYPE_MODE (passed_type);
1892
      rtx entry_parm;
1893
 
1894
      if (TREE_ADDRESSABLE (passed_type))
1895
        {
1896
          passed_type = build_pointer_type (passed_type);
1897
          passed_mode = Pmode;
1898
        }
1899
 
1900
      entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1);
1901
 
1902
      FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1);
1903
      next_arg = TREE_CHAIN (cur_arg);
1904
 
1905
      if (entry_parm && store_args_on_stack)
1906
        {
1907
          if (next_arg == 0
1908
              && DECL_NAME (cur_arg)
1909
              && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
1910
                                "__builtin_va_alist"))
1911
                  || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
1912
                                   "va_alist"))))
1913
            {
1914
              last_arg_is_vararg_marker = 1;
1915
              break;
1916
            }
1917
          else
1918
            {
1919
              int words;
1920
 
1921
              gcc_assert (GET_CODE (entry_parm) == REG);
1922
 
1923
              /* Passed in a register, so will get homed automatically.  */
1924
              if (GET_MODE (entry_parm) == BLKmode)
1925
                words = (int_size_in_bytes (passed_type) + 3) / 4;
1926
              else
1927
                words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
1928
 
1929
              regno = REGNO (entry_parm) + words - 1;
1930
            }
1931
        }
1932
      else
1933
        {
1934
          regno = GP_ARG_LAST+1;
1935
          break;
1936
        }
1937
    }
1938
 
1939
  /* In order to pass small structures by value in registers we need to
1940
     shift the value into the high part of the register.
1941
     Function_arg has encoded a PARALLEL rtx, holding a vector of
1942
     adjustments to be made as the next_arg_reg variable, so we split up the
1943
     insns, and emit them separately.  */
1944
  next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
1945
  if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
1946
    {
1947
      rtvec adjust = XVEC (next_arg_reg, 0);
1948
      int num = GET_NUM_ELEM (adjust);
1949
 
1950
      for (i = 0; i < num; i++)
1951
        {
1952
          rtx insn, pattern;
1953
 
1954
          pattern = RTVEC_ELT (adjust, i);
1955
          if (GET_CODE (pattern) != SET
1956
              || GET_CODE (SET_SRC (pattern)) != ASHIFT)
1957
            abort_with_insn (pattern, "Insn is not a shift");
1958
          PUT_CODE (SET_SRC (pattern), ASHIFTRT);
1959
 
1960
          insn = emit_insn (pattern);
1961
 
1962
          /* Global life information isn't valid at this point, so we
1963
             can't check whether these shifts are actually used.  Mark
1964
             them MAYBE_DEAD so that flow2 will remove them, and not
1965
             complain about dead code in the prologue.  */
1966
          REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
1967
                                               REG_NOTES (insn));
1968
        }
1969
    }
1970
 
1971
  tsize = compute_frame_size (get_frame_size ());
1972
 
1973
  /* If this function is a varargs function, store any registers that
1974
     would normally hold arguments ($4 - $7) on the stack.  */
1975
  if (store_args_on_stack
1976
      && ((TYPE_ARG_TYPES (fntype) != 0
1977
           && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1978
               != void_type_node))
1979
          || last_arg_is_vararg_marker))
1980
    {
1981
      int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD;
1982
      rtx ptr = stack_pointer_rtx;
1983
 
1984
      for (; regno <= GP_ARG_LAST; regno++)
1985
        {
1986
          if (offset != 0)
1987
            ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
1988
          emit_move_insn (gen_rtx_MEM (gpr_mode, ptr),
1989
                          gen_rtx_REG (gpr_mode, regno));
1990
 
1991
          offset += GET_MODE_SIZE (gpr_mode);
1992
        }
1993
    }
1994
 
1995
  if (tsize > 0)
1996
    {
1997
      rtx tsize_rtx = GEN_INT (tsize);
1998
      rtx adjustment_rtx, insn, dwarf_pattern;
1999
 
2000
      if (tsize > 32767)
2001
        {
2002
          adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
2003
          emit_move_insn (adjustment_rtx, tsize_rtx);
2004
        }
2005
      else
2006
        adjustment_rtx = tsize_rtx;
2007
 
2008
      insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2009
                                    adjustment_rtx));
2010
 
2011
      dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx,
2012
                                   plus_constant (stack_pointer_rtx, -tsize));
2013
 
2014
      iq2000_annotate_frame_insn (insn, dwarf_pattern);
2015
 
2016
      save_restore_insns (1);
2017
 
2018
      if (frame_pointer_needed)
2019
        {
2020
          rtx insn = 0;
2021
 
2022
          insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2023
                                       stack_pointer_rtx));
2024
 
2025
          if (insn)
2026
            RTX_FRAME_RELATED_P (insn) = 1;
2027
        }
2028
    }
2029
 
2030
  emit_insn (gen_blockage ());
2031
}
2032
 
2033
/* Expand the epilogue into a bunch of separate insns.  */
2034
 
2035
void
2036
iq2000_expand_epilogue (void)
2037
{
2038
  HOST_WIDE_INT tsize = cfun->machine->total_size;
2039
  rtx tsize_rtx = GEN_INT (tsize);
2040
  rtx tmp_rtx = (rtx)0;
2041
 
2042
  if (iq2000_can_use_return_insn ())
2043
    {
2044
      emit_jump_insn (gen_return ());
2045
      return;
2046
    }
2047
 
2048
  if (tsize > 32767)
2049
    {
2050
      tmp_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
2051
      emit_move_insn (tmp_rtx, tsize_rtx);
2052
      tsize_rtx = tmp_rtx;
2053
    }
2054
 
2055
  if (tsize > 0)
2056
    {
2057
      if (frame_pointer_needed)
2058
        {
2059
          emit_insn (gen_blockage ());
2060
 
2061
          emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2062
        }
2063
 
2064
      save_restore_insns (0);
2065
 
2066
      if (current_function_calls_eh_return)
2067
        {
2068
          rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
2069
          emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
2070
          tsize_rtx = eh_ofs;
2071
        }
2072
 
2073
      emit_insn (gen_blockage ());
2074
 
2075
      if (tsize != 0 || current_function_calls_eh_return)
2076
        {
2077
          emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2078
                                 tsize_rtx));
2079
        }
2080
    }
2081
 
2082
  if (current_function_calls_eh_return)
2083
    {
2084
      /* Perform the additional bump for __throw.  */
2085
      emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
2086
                      stack_pointer_rtx);
2087
      emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode,
2088
                                                  HARD_FRAME_POINTER_REGNUM)));
2089
      emit_jump_insn (gen_eh_return_internal ());
2090
    }
2091
  else
2092
      emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2093
                                                  GP_REG_FIRST + 31)));
2094
}
2095
 
2096
void
2097
iq2000_expand_eh_return (rtx address)
2098
{
2099
  HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset;
2100
  rtx scratch;
2101
 
2102
  scratch = plus_constant (stack_pointer_rtx, gp_offset);
2103
  emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address);
2104
}
2105
 
2106
/* Return nonzero if this function is known to have a null epilogue.
2107
   This allows the optimizer to omit jumps to jumps if no stack
2108
   was created.  */
2109
 
2110
int
2111
iq2000_can_use_return_insn (void)
2112
{
2113
  if (! reload_completed)
2114
    return 0;
2115
 
2116
  if (regs_ever_live[31] || profile_flag)
2117
    return 0;
2118
 
2119
  if (cfun->machine->initialized)
2120
    return cfun->machine->total_size == 0;
2121
 
2122
  return compute_frame_size (get_frame_size ()) == 0;
2123
}
2124
 
2125
/* Returns nonzero if X contains a SYMBOL_REF.  */
2126
 
2127
static int
2128
symbolic_expression_p (rtx x)
2129
{
2130
  if (GET_CODE (x) == SYMBOL_REF)
2131
    return 1;
2132
 
2133
  if (GET_CODE (x) == CONST)
2134
    return symbolic_expression_p (XEXP (x, 0));
2135
 
2136
  if (UNARY_P (x))
2137
    return symbolic_expression_p (XEXP (x, 0));
2138
 
2139
  if (ARITHMETIC_P (x))
2140
    return (symbolic_expression_p (XEXP (x, 0))
2141
            || symbolic_expression_p (XEXP (x, 1)));
2142
 
2143
  return 0;
2144
}
2145
 
2146
/* Choose the section to use for the constant rtx expression X that has
2147
   mode MODE.  */
2148
 
2149
static void
2150
iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED,
2151
                           unsigned HOST_WIDE_INT align)
2152
{
2153
  /* For embedded applications, always put constants in read-only data,
2154
     in order to reduce RAM usage.  */
2155
      /* For embedded applications, always put constants in read-only data,
2156
         in order to reduce RAM usage.  */
2157
  mergeable_constant_section (mode, align, 0);
2158
}
2159
 
2160
/* Choose the section to use for DECL.  RELOC is true if its value contains
2161
   any relocatable expression.
2162
 
2163
   Some of the logic used here needs to be replicated in
2164
   ENCODE_SECTION_INFO in iq2000.h so that references to these symbols
2165
   are done correctly.  */
2166
 
2167
static void
2168
iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
2169
                       unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
2170
{
2171
  if (TARGET_EMBEDDED_DATA)
2172
    {
2173
      /* For embedded applications, always put an object in read-only data
2174
         if possible, in order to reduce RAM usage.  */
2175
      if ((TREE_CODE (decl) == VAR_DECL
2176
           && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
2177
           && DECL_INITIAL (decl)
2178
           && (DECL_INITIAL (decl) == error_mark_node
2179
               || TREE_CONSTANT (DECL_INITIAL (decl))))
2180
          /* Deal with calls from output_constant_def_contents.  */
2181
          || TREE_CODE (decl) != VAR_DECL)
2182
        readonly_data_section ();
2183
      else
2184
        data_section ();
2185
    }
2186
  else
2187
    {
2188
      /* For hosted applications, always put an object in small data if
2189
         possible, as this gives the best performance.  */
2190
      if ((TREE_CODE (decl) == VAR_DECL
2191
           && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
2192
           && DECL_INITIAL (decl)
2193
           && (DECL_INITIAL (decl) == error_mark_node
2194
               || TREE_CONSTANT (DECL_INITIAL (decl))))
2195
          /* Deal with calls from output_constant_def_contents.  */
2196
          || TREE_CODE (decl) != VAR_DECL)
2197
        readonly_data_section ();
2198
      else
2199
        data_section ();
2200
    }
2201
}
2202
/* Return register to use for a function return value with VALTYPE for function
2203
   FUNC.  */
2204
 
2205
rtx
2206
iq2000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
2207
{
2208
  int reg = GP_RETURN;
2209
  enum machine_mode mode = TYPE_MODE (valtype);
2210
  int unsignedp = TYPE_UNSIGNED (valtype);
2211
 
2212
  /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
2213
     we must promote the mode just as PROMOTE_MODE does.  */
2214
  mode = promote_mode (valtype, mode, &unsignedp, 1);
2215
 
2216
  return gen_rtx_REG (mode, reg);
2217
}
2218
 
2219
/* Return true when an argument must be passed by reference.  */
2220
 
2221
static bool
2222
iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
2223
                          tree type, bool named ATTRIBUTE_UNUSED)
2224
{
2225
  int size;
2226
 
2227
  /* We must pass by reference if we would be both passing in registers
2228
     and the stack.  This is because any subsequent partial arg would be
2229
     handled incorrectly in this case.  */
2230
  if (cum && targetm.calls.must_pass_in_stack (mode, type))
2231
     {
2232
       /* Don't pass the actual CUM to FUNCTION_ARG, because we would
2233
          get double copies of any offsets generated for small structs
2234
          passed in registers.  */
2235
       CUMULATIVE_ARGS temp;
2236
 
2237
       temp = *cum;
2238
       if (FUNCTION_ARG (temp, mode, type, named) != 0)
2239
         return 1;
2240
     }
2241
 
2242
  if (type == NULL_TREE || mode == DImode || mode == DFmode)
2243
    return 0;
2244
 
2245
  size = int_size_in_bytes (type);
2246
  return size == -1 || size > UNITS_PER_WORD;
2247
}
2248
 
2249
/* Return the length of INSN.  LENGTH is the initial length computed by
2250
   attributes in the machine-description file.  */
2251
 
2252
int
2253
iq2000_adjust_insn_length (rtx insn, int length)
2254
{
2255
  /* A unconditional jump has an unfilled delay slot if it is not part
2256
     of a sequence.  A conditional jump normally has a delay slot.  */
2257
  if (simplejump_p (insn)
2258
      || (   (GET_CODE (insn) == JUMP_INSN
2259
           || GET_CODE (insn) == CALL_INSN)))
2260
    length += 4;
2261
 
2262
  return length;
2263
}
2264
 
2265
/* Output assembly instructions to perform a conditional branch.
2266
 
2267
   INSN is the branch instruction.  OPERANDS[0] is the condition.
2268
   OPERANDS[1] is the target of the branch.  OPERANDS[2] is the target
2269
   of the first operand to the condition.  If TWO_OPERANDS_P is
2270
   nonzero the comparison takes two operands; OPERANDS[3] will be the
2271
   second operand.
2272
 
2273
   If INVERTED_P is nonzero we are to branch if the condition does
2274
   not hold.  If FLOAT_P is nonzero this is a floating-point comparison.
2275
 
2276
   LENGTH is the length (in bytes) of the sequence we are to generate.
2277
   That tells us whether to generate a simple conditional branch, or a
2278
   reversed conditional branch around a `jr' instruction.  */
2279
 
2280
char *
2281
iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p,
2282
                                  int float_p, int inverted_p, int length)
2283
{
2284
  static char buffer[200];
2285
  /* The kind of comparison we are doing.  */
2286
  enum rtx_code code = GET_CODE (operands[0]);
2287
  /* Nonzero if the opcode for the comparison needs a `z' indicating
2288
     that it is a comparison against zero.  */
2289
  int need_z_p;
2290
  /* A string to use in the assembly output to represent the first
2291
     operand.  */
2292
  const char *op1 = "%z2";
2293
  /* A string to use in the assembly output to represent the second
2294
     operand.  Use the hard-wired zero register if there's no second
2295
     operand.  */
2296
  const char *op2 = (two_operands_p ? ",%z3" : ",%.");
2297
  /* The operand-printing string for the comparison.  */
2298
  const char *comp = (float_p ? "%F0" : "%C0");
2299
  /* The operand-printing string for the inverted comparison.  */
2300
  const char *inverted_comp = (float_p ? "%W0" : "%N0");
2301
 
2302
  /* Likely variants of each branch instruction annul the instruction
2303
     in the delay slot if the branch is not taken.  */
2304
  iq2000_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
2305
 
2306
  if (!two_operands_p)
2307
    {
2308
      /* To compute whether than A > B, for example, we normally
2309
         subtract B from A and then look at the sign bit.  But, if we
2310
         are doing an unsigned comparison, and B is zero, we don't
2311
         have to do the subtraction.  Instead, we can just check to
2312
         see if A is nonzero.  Thus, we change the CODE here to
2313
         reflect the simpler comparison operation.  */
2314
      switch (code)
2315
        {
2316
        case GTU:
2317
          code = NE;
2318
          break;
2319
 
2320
        case LEU:
2321
          code = EQ;
2322
          break;
2323
 
2324
        case GEU:
2325
          /* A condition which will always be true.  */
2326
          code = EQ;
2327
          op1 = "%.";
2328
          break;
2329
 
2330
        case LTU:
2331
          /* A condition which will always be false.  */
2332
          code = NE;
2333
          op1 = "%.";
2334
          break;
2335
 
2336
        default:
2337
          /* Not a special case.  */
2338
          break;
2339
        }
2340
    }
2341
 
2342
  /* Relative comparisons are always done against zero.  But
2343
     equality comparisons are done between two operands, and therefore
2344
     do not require a `z' in the assembly language output.  */
2345
  need_z_p = (!float_p && code != EQ && code != NE);
2346
  /* For comparisons against zero, the zero is not provided
2347
     explicitly.  */
2348
  if (need_z_p)
2349
    op2 = "";
2350
 
2351
  /* Begin by terminating the buffer.  That way we can always use
2352
     strcat to add to it.  */
2353
  buffer[0] = '\0';
2354
 
2355
  switch (length)
2356
    {
2357
    case 4:
2358
    case 8:
2359
      /* Just a simple conditional branch.  */
2360
      if (float_p)
2361
        sprintf (buffer, "b%s%%?\t%%Z2%%1",
2362
                 inverted_p ? inverted_comp : comp);
2363
      else
2364
        sprintf (buffer, "b%s%s%%?\t%s%s,%%1",
2365
                 inverted_p ? inverted_comp : comp,
2366
                 need_z_p ? "z" : "",
2367
                 op1,
2368
                 op2);
2369
      return buffer;
2370
 
2371
    case 12:
2372
    case 16:
2373
      {
2374
        /* Generate a reversed conditional branch around ` j'
2375
           instruction:
2376
 
2377
                .set noreorder
2378
                .set nomacro
2379
                bc    l
2380
                nop
2381
                j     target
2382
                .set macro
2383
                .set reorder
2384
             l:
2385
 
2386
           Because we have to jump four bytes *past* the following
2387
           instruction if this branch was annulled, we can't just use
2388
           a label, as in the picture above; there's no way to put the
2389
           label after the next instruction, as the assembler does not
2390
           accept `.L+4' as the target of a branch.  (We can't just
2391
           wait until the next instruction is output; it might be a
2392
           macro and take up more than four bytes.  Once again, we see
2393
           why we want to eliminate macros.)
2394
 
2395
           If the branch is annulled, we jump four more bytes that we
2396
           would otherwise; that way we skip the annulled instruction
2397
           in the delay slot.  */
2398
 
2399
        const char *target
2400
          = ((iq2000_branch_likely || length == 16) ? ".+16" : ".+12");
2401
        char *c;
2402
 
2403
        c = strchr (buffer, '\0');
2404
        /* Generate the reversed comparison.  This takes four
2405
           bytes.  */
2406
        if (float_p)
2407
          sprintf (c, "b%s\t%%Z2%s",
2408
                   inverted_p ? comp : inverted_comp,
2409
                   target);
2410
        else
2411
          sprintf (c, "b%s%s\t%s%s,%s",
2412
                   inverted_p ? comp : inverted_comp,
2413
                   need_z_p ? "z" : "",
2414
                   op1,
2415
                   op2,
2416
                   target);
2417
        strcat (c, "\n\tnop\n\tj\t%1");
2418
        if (length == 16)
2419
          /* The delay slot was unfilled.  Since we're inside
2420
             .noreorder, the assembler will not fill in the NOP for
2421
             us, so we must do it ourselves.  */
2422
          strcat (buffer, "\n\tnop");
2423
        return buffer;
2424
      }
2425
 
2426
    default:
2427
      gcc_unreachable ();
2428
    }
2429
 
2430
  /* NOTREACHED */
2431
  return 0;
2432
}
2433
 
2434
#define def_builtin(NAME, TYPE, CODE)                                   \
2435
  lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,     \
2436
                               NULL, NULL_TREE)
2437
 
2438
static void
2439
iq2000_init_builtins (void)
2440
{
2441
  tree endlink = void_list_node;
2442
  tree void_ftype, void_ftype_int, void_ftype_int_int;
2443
  tree void_ftype_int_int_int;
2444
  tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int;
2445
  tree int_ftype_int_int_int_int;
2446
 
2447
  /* func () */
2448
  void_ftype
2449
    = build_function_type (void_type_node,
2450
                           tree_cons (NULL_TREE, void_type_node, endlink));
2451
 
2452
  /* func (int) */
2453
  void_ftype_int
2454
    = build_function_type (void_type_node,
2455
                           tree_cons (NULL_TREE, integer_type_node, endlink));
2456
 
2457
  /* void func (int, int) */
2458
  void_ftype_int_int
2459
    = build_function_type (void_type_node,
2460
                           tree_cons (NULL_TREE, integer_type_node,
2461
                                      tree_cons (NULL_TREE, integer_type_node,
2462
                                                 endlink)));
2463
 
2464
  /* int func (int) */
2465
  int_ftype_int
2466
    = build_function_type (integer_type_node,
2467
                           tree_cons (NULL_TREE, integer_type_node, endlink));
2468
 
2469
  /* int func (int, int) */
2470
  int_ftype_int_int
2471
    = build_function_type (integer_type_node,
2472
                           tree_cons (NULL_TREE, integer_type_node,
2473
                                      tree_cons (NULL_TREE, integer_type_node,
2474
                                                 endlink)));
2475
 
2476
  /* void func (int, int, int) */
2477
void_ftype_int_int_int
2478
    = build_function_type
2479
    (void_type_node,
2480
     tree_cons (NULL_TREE, integer_type_node,
2481
                tree_cons (NULL_TREE, integer_type_node,
2482
                           tree_cons (NULL_TREE,
2483
                                      integer_type_node,
2484
                                      endlink))));
2485
 
2486
  /* int func (int, int, int, int) */
2487
  int_ftype_int_int_int_int
2488
    = build_function_type
2489
    (integer_type_node,
2490
     tree_cons (NULL_TREE, integer_type_node,
2491
                tree_cons (NULL_TREE, integer_type_node,
2492
                           tree_cons (NULL_TREE,
2493
                                      integer_type_node,
2494
                                      tree_cons (NULL_TREE,
2495
                                                 integer_type_node,
2496
                                                 endlink)))));
2497
 
2498
  /* int func (int, int, int) */
2499
  int_ftype_int_int_int
2500
    = build_function_type
2501
    (integer_type_node,
2502
     tree_cons (NULL_TREE, integer_type_node,
2503
                tree_cons (NULL_TREE, integer_type_node,
2504
                           tree_cons (NULL_TREE,
2505
                                      integer_type_node,
2506
                                      endlink))));
2507
 
2508
  /* int func (int, int, int, int) */
2509
  int_ftype_int_int_int_int
2510
    = build_function_type
2511
    (integer_type_node,
2512
     tree_cons (NULL_TREE, integer_type_node,
2513
                tree_cons (NULL_TREE, integer_type_node,
2514
                           tree_cons (NULL_TREE,
2515
                                      integer_type_node,
2516
                                      tree_cons (NULL_TREE,
2517
                                                 integer_type_node,
2518
                                                 endlink)))));
2519
 
2520
  def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16);
2521
  def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM);
2522
  def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR);
2523
  def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL);
2524
  def_builtin ("__builtin_cfc0", int_ftype_int, IQ2000_BUILTIN_CFC0);
2525
  def_builtin ("__builtin_cfc1", int_ftype_int, IQ2000_BUILTIN_CFC1);
2526
  def_builtin ("__builtin_cfc2", int_ftype_int, IQ2000_BUILTIN_CFC2);
2527
  def_builtin ("__builtin_cfc3", int_ftype_int, IQ2000_BUILTIN_CFC3);
2528
  def_builtin ("__builtin_ctc0", void_ftype_int_int, IQ2000_BUILTIN_CTC0);
2529
  def_builtin ("__builtin_ctc1", void_ftype_int_int, IQ2000_BUILTIN_CTC1);
2530
  def_builtin ("__builtin_ctc2", void_ftype_int_int, IQ2000_BUILTIN_CTC2);
2531
  def_builtin ("__builtin_ctc3", void_ftype_int_int, IQ2000_BUILTIN_CTC3);
2532
  def_builtin ("__builtin_mfc0", int_ftype_int, IQ2000_BUILTIN_MFC0);
2533
  def_builtin ("__builtin_mfc1", int_ftype_int, IQ2000_BUILTIN_MFC1);
2534
  def_builtin ("__builtin_mfc2", int_ftype_int, IQ2000_BUILTIN_MFC2);
2535
  def_builtin ("__builtin_mfc3", int_ftype_int, IQ2000_BUILTIN_MFC3);
2536
  def_builtin ("__builtin_mtc0", void_ftype_int_int, IQ2000_BUILTIN_MTC0);
2537
  def_builtin ("__builtin_mtc1", void_ftype_int_int, IQ2000_BUILTIN_MTC1);
2538
  def_builtin ("__builtin_mtc2", void_ftype_int_int, IQ2000_BUILTIN_MTC2);
2539
  def_builtin ("__builtin_mtc3", void_ftype_int_int, IQ2000_BUILTIN_MTC3);
2540
  def_builtin ("__builtin_lur", void_ftype_int_int, IQ2000_BUILTIN_LUR);
2541
  def_builtin ("__builtin_rb", void_ftype_int_int, IQ2000_BUILTIN_RB);
2542
  def_builtin ("__builtin_rx", void_ftype_int_int, IQ2000_BUILTIN_RX);
2543
  def_builtin ("__builtin_srrd", void_ftype_int, IQ2000_BUILTIN_SRRD);
2544
  def_builtin ("__builtin_srwr", void_ftype_int_int, IQ2000_BUILTIN_SRWR);
2545
  def_builtin ("__builtin_wb", void_ftype_int_int, IQ2000_BUILTIN_WB);
2546
  def_builtin ("__builtin_wx", void_ftype_int_int, IQ2000_BUILTIN_WX);
2547
  def_builtin ("__builtin_luc32l", void_ftype_int_int, IQ2000_BUILTIN_LUC32L);
2548
  def_builtin ("__builtin_luc64", void_ftype_int_int, IQ2000_BUILTIN_LUC64);
2549
  def_builtin ("__builtin_luc64l", void_ftype_int_int, IQ2000_BUILTIN_LUC64L);
2550
  def_builtin ("__builtin_luk", void_ftype_int_int, IQ2000_BUILTIN_LUK);
2551
  def_builtin ("__builtin_lulck", void_ftype_int, IQ2000_BUILTIN_LULCK);
2552
  def_builtin ("__builtin_lum32", void_ftype_int_int, IQ2000_BUILTIN_LUM32);
2553
  def_builtin ("__builtin_lum32l", void_ftype_int_int, IQ2000_BUILTIN_LUM32L);
2554
  def_builtin ("__builtin_lum64", void_ftype_int_int, IQ2000_BUILTIN_LUM64);
2555
  def_builtin ("__builtin_lum64l", void_ftype_int_int, IQ2000_BUILTIN_LUM64L);
2556
  def_builtin ("__builtin_lurl", void_ftype_int_int, IQ2000_BUILTIN_LURL);
2557
  def_builtin ("__builtin_mrgb", int_ftype_int_int_int, IQ2000_BUILTIN_MRGB);
2558
  def_builtin ("__builtin_srrdl", void_ftype_int, IQ2000_BUILTIN_SRRDL);
2559
  def_builtin ("__builtin_srulck", void_ftype_int, IQ2000_BUILTIN_SRULCK);
2560
  def_builtin ("__builtin_srwru", void_ftype_int_int, IQ2000_BUILTIN_SRWRU);
2561
  def_builtin ("__builtin_trapqfl", void_ftype, IQ2000_BUILTIN_TRAPQFL);
2562
  def_builtin ("__builtin_trapqne", void_ftype, IQ2000_BUILTIN_TRAPQNE);
2563
  def_builtin ("__builtin_traprel", void_ftype_int, IQ2000_BUILTIN_TRAPREL);
2564
  def_builtin ("__builtin_wbu", void_ftype_int_int_int, IQ2000_BUILTIN_WBU);
2565
  def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL);
2566
}
2567
 
2568
/* Builtin for ICODE having ARGCOUNT args in ARGLIST where each arg
2569
   has an rtx CODE.  */
2570
 
2571
static rtx
2572
expand_one_builtin (enum insn_code icode, rtx target, tree arglist,
2573
                    enum rtx_code *code, int argcount)
2574
{
2575
  rtx pat;
2576
  tree arg [5];
2577
  rtx op [5];
2578
  enum machine_mode mode [5];
2579
  int i;
2580
 
2581
  mode[0] = insn_data[icode].operand[0].mode;
2582
  for (i = 0; i < argcount; i++)
2583
    {
2584
      arg[i] = TREE_VALUE (arglist);
2585
      arglist = TREE_CHAIN (arglist);
2586
      op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0);
2587
      mode[i] = insn_data[icode].operand[i].mode;
2588
      if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT)
2589
        error ("argument %qd is not a constant", i + 1);
2590
      if (code[i] == REG
2591
          && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i]))
2592
        op[i] = copy_to_mode_reg (mode[i], op[i]);
2593
    }
2594
 
2595
  if (insn_data[icode].operand[0].constraint[0] == '=')
2596
    {
2597
      if (target == 0
2598
          || GET_MODE (target) != mode[0]
2599
          || ! (*insn_data[icode].operand[0].predicate) (target, mode[0]))
2600
        target = gen_reg_rtx (mode[0]);
2601
    }
2602
  else
2603
    target = 0;
2604
 
2605
  switch (argcount)
2606
    {
2607
    case 0:
2608
        pat = GEN_FCN (icode) (target);
2609
    case 1:
2610
      if (target)
2611
        pat = GEN_FCN (icode) (target, op[0]);
2612
      else
2613
        pat = GEN_FCN (icode) (op[0]);
2614
      break;
2615
    case 2:
2616
      if (target)
2617
        pat = GEN_FCN (icode) (target, op[0], op[1]);
2618
      else
2619
        pat = GEN_FCN (icode) (op[0], op[1]);
2620
      break;
2621
    case 3:
2622
      if (target)
2623
        pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
2624
      else
2625
        pat = GEN_FCN (icode) (op[0], op[1], op[2]);
2626
      break;
2627
    case 4:
2628
      if (target)
2629
        pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
2630
      else
2631
        pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
2632
      break;
2633
    default:
2634
      gcc_unreachable ();
2635
    }
2636
 
2637
  if (! pat)
2638
    return 0;
2639
  emit_insn (pat);
2640
  return target;
2641
}
2642
 
2643
/* Expand an expression EXP that calls a built-in function,
2644
   with result going to TARGET if that's convenient
2645
   (and in mode MODE if that's convenient).
2646
   SUBTARGET may be used as the target for computing one of EXP's operands.
2647
   IGNORE is nonzero if the value is to be ignored.  */
2648
 
2649
static rtx
2650
iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2651
                       enum machine_mode mode ATTRIBUTE_UNUSED,
2652
                       int ignore ATTRIBUTE_UNUSED)
2653
{
2654
  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2655
  tree arglist = TREE_OPERAND (exp, 1);
2656
  int fcode = DECL_FUNCTION_CODE (fndecl);
2657
  enum rtx_code code [5];
2658
 
2659
  code[0] = REG;
2660
  code[1] = REG;
2661
  code[2] = REG;
2662
  code[3] = REG;
2663
  code[4] = REG;
2664
  switch (fcode)
2665
    {
2666
    default:
2667
      break;
2668
 
2669
    case IQ2000_BUILTIN_ADO16:
2670
      return expand_one_builtin (CODE_FOR_ado16, target, arglist, code, 2);
2671
 
2672
    case IQ2000_BUILTIN_RAM:
2673
      code[1] = CONST_INT;
2674
      code[2] = CONST_INT;
2675
      code[3] = CONST_INT;
2676
      return expand_one_builtin (CODE_FOR_ram, target, arglist, code, 4);
2677
 
2678
    case IQ2000_BUILTIN_CHKHDR:
2679
      return expand_one_builtin (CODE_FOR_chkhdr, target, arglist, code, 2);
2680
 
2681
    case IQ2000_BUILTIN_PKRL:
2682
      return expand_one_builtin (CODE_FOR_pkrl, target, arglist, code, 2);
2683
 
2684
    case IQ2000_BUILTIN_CFC0:
2685
      code[0] = CONST_INT;
2686
      return expand_one_builtin (CODE_FOR_cfc0, target, arglist, code, 1);
2687
 
2688
    case IQ2000_BUILTIN_CFC1:
2689
      code[0] = CONST_INT;
2690
      return expand_one_builtin (CODE_FOR_cfc1, target, arglist, code, 1);
2691
 
2692
    case IQ2000_BUILTIN_CFC2:
2693
      code[0] = CONST_INT;
2694
      return expand_one_builtin (CODE_FOR_cfc2, target, arglist, code, 1);
2695
 
2696
    case IQ2000_BUILTIN_CFC3:
2697
      code[0] = CONST_INT;
2698
      return expand_one_builtin (CODE_FOR_cfc3, target, arglist, code, 1);
2699
 
2700
    case IQ2000_BUILTIN_CTC0:
2701
      code[1] = CONST_INT;
2702
      return expand_one_builtin (CODE_FOR_ctc0, target, arglist, code, 2);
2703
 
2704
    case IQ2000_BUILTIN_CTC1:
2705
      code[1] = CONST_INT;
2706
      return expand_one_builtin (CODE_FOR_ctc1, target, arglist, code, 2);
2707
 
2708
    case IQ2000_BUILTIN_CTC2:
2709
      code[1] = CONST_INT;
2710
      return expand_one_builtin (CODE_FOR_ctc2, target, arglist, code, 2);
2711
 
2712
    case IQ2000_BUILTIN_CTC3:
2713
      code[1] = CONST_INT;
2714
      return expand_one_builtin (CODE_FOR_ctc3, target, arglist, code, 2);
2715
 
2716
    case IQ2000_BUILTIN_MFC0:
2717
      code[0] = CONST_INT;
2718
      return expand_one_builtin (CODE_FOR_mfc0, target, arglist, code, 1);
2719
 
2720
    case IQ2000_BUILTIN_MFC1:
2721
      code[0] = CONST_INT;
2722
      return expand_one_builtin (CODE_FOR_mfc1, target, arglist, code, 1);
2723
 
2724
    case IQ2000_BUILTIN_MFC2:
2725
      code[0] = CONST_INT;
2726
      return expand_one_builtin (CODE_FOR_mfc2, target, arglist, code, 1);
2727
 
2728
    case IQ2000_BUILTIN_MFC3:
2729
      code[0] = CONST_INT;
2730
      return expand_one_builtin (CODE_FOR_mfc3, target, arglist, code, 1);
2731
 
2732
    case IQ2000_BUILTIN_MTC0:
2733
      code[1] = CONST_INT;
2734
      return expand_one_builtin (CODE_FOR_mtc0, target, arglist, code, 2);
2735
 
2736
    case IQ2000_BUILTIN_MTC1:
2737
      code[1] = CONST_INT;
2738
      return expand_one_builtin (CODE_FOR_mtc1, target, arglist, code, 2);
2739
 
2740
    case IQ2000_BUILTIN_MTC2:
2741
      code[1] = CONST_INT;
2742
      return expand_one_builtin (CODE_FOR_mtc2, target, arglist, code, 2);
2743
 
2744
    case IQ2000_BUILTIN_MTC3:
2745
      code[1] = CONST_INT;
2746
      return expand_one_builtin (CODE_FOR_mtc3, target, arglist, code, 2);
2747
 
2748
    case IQ2000_BUILTIN_LUR:
2749
      return expand_one_builtin (CODE_FOR_lur, target, arglist, code, 2);
2750
 
2751
    case IQ2000_BUILTIN_RB:
2752
      return expand_one_builtin (CODE_FOR_rb, target, arglist, code, 2);
2753
 
2754
    case IQ2000_BUILTIN_RX:
2755
      return expand_one_builtin (CODE_FOR_rx, target, arglist, code, 2);
2756
 
2757
    case IQ2000_BUILTIN_SRRD:
2758
      return expand_one_builtin (CODE_FOR_srrd, target, arglist, code, 1);
2759
 
2760
    case IQ2000_BUILTIN_SRWR:
2761
      return expand_one_builtin (CODE_FOR_srwr, target, arglist, code, 2);
2762
 
2763
    case IQ2000_BUILTIN_WB:
2764
      return expand_one_builtin (CODE_FOR_wb, target, arglist, code, 2);
2765
 
2766
    case IQ2000_BUILTIN_WX:
2767
      return expand_one_builtin (CODE_FOR_wx, target, arglist, code, 2);
2768
 
2769
    case IQ2000_BUILTIN_LUC32L:
2770
      return expand_one_builtin (CODE_FOR_luc32l, target, arglist, code, 2);
2771
 
2772
    case IQ2000_BUILTIN_LUC64:
2773
      return expand_one_builtin (CODE_FOR_luc64, target, arglist, code, 2);
2774
 
2775
    case IQ2000_BUILTIN_LUC64L:
2776
      return expand_one_builtin (CODE_FOR_luc64l, target, arglist, code, 2);
2777
 
2778
    case IQ2000_BUILTIN_LUK:
2779
      return expand_one_builtin (CODE_FOR_luk, target, arglist, code, 2);
2780
 
2781
    case IQ2000_BUILTIN_LULCK:
2782
      return expand_one_builtin (CODE_FOR_lulck, target, arglist, code, 1);
2783
 
2784
    case IQ2000_BUILTIN_LUM32:
2785
      return expand_one_builtin (CODE_FOR_lum32, target, arglist, code, 2);
2786
 
2787
    case IQ2000_BUILTIN_LUM32L:
2788
      return expand_one_builtin (CODE_FOR_lum32l, target, arglist, code, 2);
2789
 
2790
    case IQ2000_BUILTIN_LUM64:
2791
      return expand_one_builtin (CODE_FOR_lum64, target, arglist, code, 2);
2792
 
2793
    case IQ2000_BUILTIN_LUM64L:
2794
      return expand_one_builtin (CODE_FOR_lum64l, target, arglist, code, 2);
2795
 
2796
    case IQ2000_BUILTIN_LURL:
2797
      return expand_one_builtin (CODE_FOR_lurl, target, arglist, code, 2);
2798
 
2799
    case IQ2000_BUILTIN_MRGB:
2800
      code[2] = CONST_INT;
2801
      return expand_one_builtin (CODE_FOR_mrgb, target, arglist, code, 3);
2802
 
2803
    case IQ2000_BUILTIN_SRRDL:
2804
      return expand_one_builtin (CODE_FOR_srrdl, target, arglist, code, 1);
2805
 
2806
    case IQ2000_BUILTIN_SRULCK:
2807
      return expand_one_builtin (CODE_FOR_srulck, target, arglist, code, 1);
2808
 
2809
    case IQ2000_BUILTIN_SRWRU:
2810
      return expand_one_builtin (CODE_FOR_srwru, target, arglist, code, 2);
2811
 
2812
    case IQ2000_BUILTIN_TRAPQFL:
2813
      return expand_one_builtin (CODE_FOR_trapqfl, target, arglist, code, 0);
2814
 
2815
    case IQ2000_BUILTIN_TRAPQNE:
2816
      return expand_one_builtin (CODE_FOR_trapqne, target, arglist, code, 0);
2817
 
2818
    case IQ2000_BUILTIN_TRAPREL:
2819
      return expand_one_builtin (CODE_FOR_traprel, target, arglist, code, 1);
2820
 
2821
    case IQ2000_BUILTIN_WBU:
2822
      return expand_one_builtin (CODE_FOR_wbu, target, arglist, code, 3);
2823
 
2824
    case IQ2000_BUILTIN_SYSCALL:
2825
      return expand_one_builtin (CODE_FOR_syscall, target, arglist, code, 0);
2826
    }
2827
 
2828
  return NULL_RTX;
2829
}
2830
 
2831
/* Worker function for TARGET_RETURN_IN_MEMORY.  */
2832
 
2833
static bool
2834
iq2000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
2835
{
2836
  return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
2837
          || (int_size_in_bytes (type) == -1));
2838
}
2839
 
2840
/* Worker function for TARGET_SETUP_INCOMING_VARARGS.  */
2841
 
2842
static void
2843
iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
2844
                               enum machine_mode mode ATTRIBUTE_UNUSED,
2845
                               tree type ATTRIBUTE_UNUSED, int * pretend_size,
2846
                               int no_rtl)
2847
{
2848
  unsigned int iq2000_off = ! cum->last_arg_fp;
2849
  unsigned int iq2000_fp_off = cum->last_arg_fp;
2850
 
2851
  if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
2852
    {
2853
      int iq2000_save_gp_regs
2854
        = MAX_ARGS_IN_REGISTERS - cum->arg_words - iq2000_off;
2855
      int iq2000_save_fp_regs
2856
        = (MAX_ARGS_IN_REGISTERS - cum->fp_arg_words - iq2000_fp_off);
2857
 
2858
      if (iq2000_save_gp_regs < 0)
2859
        iq2000_save_gp_regs = 0;
2860
      if (iq2000_save_fp_regs < 0)
2861
        iq2000_save_fp_regs = 0;
2862
 
2863
      *pretend_size = ((iq2000_save_gp_regs * UNITS_PER_WORD)
2864
                      + (iq2000_save_fp_regs * UNITS_PER_FPREG));
2865
 
2866
      if (! (no_rtl))
2867
        {
2868
          if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
2869
            {
2870
              rtx ptr, mem;
2871
              ptr = plus_constant (virtual_incoming_args_rtx,
2872
                                   - (iq2000_save_gp_regs
2873
                                      * UNITS_PER_WORD));
2874
              mem = gen_rtx_MEM (BLKmode, ptr);
2875
              move_block_from_reg
2876
                (cum->arg_words + GP_ARG_FIRST + iq2000_off,
2877
                 mem,
2878
                 iq2000_save_gp_regs);
2879
            }
2880
        }
2881
    }
2882
}
2883
 
2884
/* A C compound statement to output to stdio stream STREAM the
2885
   assembler syntax for an instruction operand that is a memory
2886
   reference whose address is ADDR.  ADDR is an RTL expression.  */
2887
 
2888
void
2889
print_operand_address (FILE * file, rtx addr)
2890
{
2891
  if (!addr)
2892
    error ("PRINT_OPERAND_ADDRESS, null pointer");
2893
 
2894
  else
2895
    switch (GET_CODE (addr))
2896
      {
2897
      case REG:
2898
        if (REGNO (addr) == ARG_POINTER_REGNUM)
2899
          abort_with_insn (addr, "Arg pointer not eliminated.");
2900
 
2901
        fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
2902
        break;
2903
 
2904
      case LO_SUM:
2905
        {
2906
          rtx arg0 = XEXP (addr, 0);
2907
          rtx arg1 = XEXP (addr, 1);
2908
 
2909
          if (GET_CODE (arg0) != REG)
2910
            abort_with_insn (addr,
2911
                             "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
2912
 
2913
          fprintf (file, "%%lo(");
2914
          print_operand_address (file, arg1);
2915
          fprintf (file, ")(%s)", reg_names [REGNO (arg0)]);
2916
        }
2917
        break;
2918
 
2919
      case PLUS:
2920
        {
2921
          rtx reg = 0;
2922
          rtx offset = 0;
2923
          rtx arg0 = XEXP (addr, 0);
2924
          rtx arg1 = XEXP (addr, 1);
2925
 
2926
          if (GET_CODE (arg0) == REG)
2927
            {
2928
              reg = arg0;
2929
              offset = arg1;
2930
              if (GET_CODE (offset) == REG)
2931
                abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs");
2932
            }
2933
 
2934
          else if (GET_CODE (arg1) == REG)
2935
              reg = arg1, offset = arg0;
2936
          else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
2937
            {
2938
              output_addr_const (file, addr);
2939
              break;
2940
            }
2941
          else
2942
            abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs");
2943
 
2944
          if (! CONSTANT_P (offset))
2945
            abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2");
2946
 
2947
          if (REGNO (reg) == ARG_POINTER_REGNUM)
2948
            abort_with_insn (addr, "Arg pointer not eliminated.");
2949
 
2950
          output_addr_const (file, offset);
2951
          fprintf (file, "(%s)", reg_names [REGNO (reg)]);
2952
        }
2953
        break;
2954
 
2955
      case LABEL_REF:
2956
      case SYMBOL_REF:
2957
      case CONST_INT:
2958
      case CONST:
2959
        output_addr_const (file, addr);
2960
        if (GET_CODE (addr) == CONST_INT)
2961
          fprintf (file, "(%s)", reg_names [0]);
2962
        break;
2963
 
2964
      default:
2965
        abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #1");
2966
        break;
2967
    }
2968
}
2969
 
2970
/* A C compound statement to output to stdio stream FILE the
2971
   assembler syntax for an instruction operand OP.
2972
 
2973
   LETTER is a value that can be used to specify one of several ways
2974
   of printing the operand.  It is used when identical operands
2975
   must be printed differently depending on the context.  LETTER
2976
   comes from the `%' specification that was used to request
2977
   printing of the operand.  If the specification was just `%DIGIT'
2978
   then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
2979
   is the ASCII code for LTR.
2980
 
2981
   If OP is a register, this macro should print the register's name.
2982
   The names can be found in an array `reg_names' whose type is
2983
   `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
2984
 
2985
   When the machine description has a specification `%PUNCT' (a `%'
2986
   followed by a punctuation character), this macro is called with
2987
   a null pointer for X and the punctuation character for LETTER.
2988
 
2989
   The IQ2000 specific codes are:
2990
 
2991
   'X'  X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x",
2992
   'x'  X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x",
2993
   'd'  output integer constant in decimal,
2994
   'z'  if the operand is 0, use $0 instead of normal operand.
2995
   'D'  print second part of double-word register or memory operand.
2996
   'L'  print low-order register of double-word register operand.
2997
   'M'  print high-order register of double-word register operand.
2998
   'C'  print part of opcode for a branch condition.
2999
   'F'  print part of opcode for a floating-point branch condition.
3000
   'N'  print part of opcode for a branch condition, inverted.
3001
   'W'  print part of opcode for a floating-point branch condition, inverted.
3002
   'A'  Print part of opcode for a bit test condition.
3003
   'P'  Print label for a bit test.
3004
   'p'  Print log for a bit test.
3005
   'B'  print 'z' for EQ, 'n' for NE
3006
   'b'  print 'n' for EQ, 'z' for NE
3007
   'T'  print 'f' for EQ, 't' for NE
3008
   't'  print 't' for EQ, 'f' for NE
3009
   'Z'  print register and a comma, but print nothing for $fcc0
3010
   '?'  Print 'l' if we are to use a branch likely instead of normal branch.
3011
   '@'  Print the name of the assembler temporary register (at or $1).
3012
   '.'  Print the name of the register with a hard-wired zero (zero or $0).
3013
   '$'  Print the name of the stack pointer register (sp or $29).
3014
   '+'  Print the name of the gp register (gp or $28).  */
3015
 
3016
void
3017
print_operand (FILE *file, rtx op, int letter)
3018
{
3019
  enum rtx_code code;
3020
 
3021
  if (PRINT_OPERAND_PUNCT_VALID_P (letter))
3022
    {
3023
      switch (letter)
3024
        {
3025
        case '?':
3026
          if (iq2000_branch_likely)
3027
            putc ('l', file);
3028
          break;
3029
 
3030
        case '@':
3031
          fputs (reg_names [GP_REG_FIRST + 1], file);
3032
          break;
3033
 
3034
        case '.':
3035
          fputs (reg_names [GP_REG_FIRST + 0], file);
3036
          break;
3037
 
3038
        case '$':
3039
          fputs (reg_names[STACK_POINTER_REGNUM], file);
3040
          break;
3041
 
3042
        case '+':
3043
          fputs (reg_names[GP_REG_FIRST + 28], file);
3044
          break;
3045
 
3046
        default:
3047
          error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
3048
          break;
3049
        }
3050
 
3051
      return;
3052
    }
3053
 
3054
  if (! op)
3055
    {
3056
      error ("PRINT_OPERAND null pointer");
3057
      return;
3058
    }
3059
 
3060
  code = GET_CODE (op);
3061
 
3062
  if (code == SIGN_EXTEND)
3063
    op = XEXP (op, 0), code = GET_CODE (op);
3064
 
3065
  if (letter == 'C')
3066
    switch (code)
3067
      {
3068
      case EQ:  fputs ("eq",  file); break;
3069
      case NE:  fputs ("ne",  file); break;
3070
      case GT:  fputs ("gt",  file); break;
3071
      case GE:  fputs ("ge",  file); break;
3072
      case LT:  fputs ("lt",  file); break;
3073
      case LE:  fputs ("le",  file); break;
3074
      case GTU: fputs ("ne", file); break;
3075
      case GEU: fputs ("geu", file); break;
3076
      case LTU: fputs ("ltu", file); break;
3077
      case LEU: fputs ("eq", file); break;
3078
      default:
3079
        abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%C");
3080
      }
3081
 
3082
  else if (letter == 'N')
3083
    switch (code)
3084
      {
3085
      case EQ:  fputs ("ne",  file); break;
3086
      case NE:  fputs ("eq",  file); break;
3087
      case GT:  fputs ("le",  file); break;
3088
      case GE:  fputs ("lt",  file); break;
3089
      case LT:  fputs ("ge",  file); break;
3090
      case LE:  fputs ("gt",  file); break;
3091
      case GTU: fputs ("leu", file); break;
3092
      case GEU: fputs ("ltu", file); break;
3093
      case LTU: fputs ("geu", file); break;
3094
      case LEU: fputs ("gtu", file); break;
3095
      default:
3096
        abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%N");
3097
      }
3098
 
3099
  else if (letter == 'F')
3100
    switch (code)
3101
      {
3102
      case EQ: fputs ("c1f", file); break;
3103
      case NE: fputs ("c1t", file); break;
3104
      default:
3105
        abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%F");
3106
      }
3107
 
3108
  else if (letter == 'W')
3109
    switch (code)
3110
      {
3111
      case EQ: fputs ("c1t", file); break;
3112
      case NE: fputs ("c1f", file); break;
3113
      default:
3114
        abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W");
3115
      }
3116
 
3117
  else if (letter == 'A')
3118
    fputs (code == LABEL_REF ? "i" : "in", file);
3119
 
3120
  else if (letter == 'P')
3121
    {
3122
      if (code == LABEL_REF)
3123
        output_addr_const (file, op);
3124
      else if (code != PC)
3125
        output_operand_lossage ("invalid %%P operand");
3126
    }
3127
 
3128
  else if (letter == 'p')
3129
    {
3130
      int value;
3131
      if (code != CONST_INT
3132
          || (value = exact_log2 (INTVAL (op))) < 0)
3133
        output_operand_lossage ("invalid %%p value");
3134
      fprintf (file, "%d", value);
3135
    }
3136
 
3137
  else if (letter == 'Z')
3138
    {
3139
      gcc_unreachable ();
3140
    }
3141
 
3142
  else if (code == REG || code == SUBREG)
3143
    {
3144
      int regnum;
3145
 
3146
      if (code == REG)
3147
        regnum = REGNO (op);
3148
      else
3149
        regnum = true_regnum (op);
3150
 
3151
      if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
3152
          || (letter == 'L' && WORDS_BIG_ENDIAN)
3153
          || letter == 'D')
3154
        regnum++;
3155
 
3156
      fprintf (file, "%s", reg_names[regnum]);
3157
    }
3158
 
3159
  else if (code == MEM)
3160
    {
3161
      if (letter == 'D')
3162
        output_address (plus_constant (XEXP (op, 0), 4));
3163
      else
3164
        output_address (XEXP (op, 0));
3165
    }
3166
 
3167
  else if (code == CONST_DOUBLE
3168
           && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
3169
    {
3170
      char s[60];
3171
 
3172
      real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
3173
      fputs (s, file);
3174
    }
3175
 
3176
  else if (letter == 'x' && GET_CODE (op) == CONST_INT)
3177
    fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
3178
 
3179
  else if (letter == 'X' && GET_CODE(op) == CONST_INT)
3180
    fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & (INTVAL (op) >> 16));
3181
 
3182
  else if (letter == 'd' && GET_CODE(op) == CONST_INT)
3183
    fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
3184
 
3185
  else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
3186
    fputs (reg_names[GP_REG_FIRST], file);
3187
 
3188
  else if (letter == 'd' || letter == 'x' || letter == 'X')
3189
    output_operand_lossage ("invalid use of %%d, %%x, or %%X");
3190
 
3191
  else if (letter == 'B')
3192
    fputs (code == EQ ? "z" : "n", file);
3193
  else if (letter == 'b')
3194
    fputs (code == EQ ? "n" : "z", file);
3195
  else if (letter == 'T')
3196
    fputs (code == EQ ? "f" : "t", file);
3197
  else if (letter == 't')
3198
    fputs (code == EQ ? "t" : "f", file);
3199
 
3200
  else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
3201
    {
3202
      print_operand (file, XEXP (op, 0), letter);
3203
    }
3204
 
3205
  else
3206
    output_addr_const (file, op);
3207
}
3208
 
3209
static bool
3210
iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total)
3211
{
3212
  enum machine_mode mode = GET_MODE (x);
3213
 
3214
  switch (code)
3215
    {
3216
    case MEM:
3217
      {
3218
        int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
3219
 
3220
        if (simple_memory_operand (x, mode))
3221
          return COSTS_N_INSNS (num_words);
3222
 
3223
        * total = COSTS_N_INSNS (2 * num_words);
3224
        break;
3225
      }
3226
 
3227
    case FFS:
3228
      * total = COSTS_N_INSNS (6);
3229
      break;
3230
 
3231
    case AND:
3232
    case IOR:
3233
    case XOR:
3234
    case NOT:
3235
      * total = COSTS_N_INSNS (mode == DImode ? 2 : 1);
3236
      break;
3237
 
3238
    case ASHIFT:
3239
    case ASHIFTRT:
3240
    case LSHIFTRT:
3241
      if (mode == DImode)
3242
        * total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12);
3243
      else
3244
        * total = COSTS_N_INSNS (1);
3245
    break;
3246
 
3247
    case ABS:
3248
      if (mode == SFmode || mode == DFmode)
3249
        * total = COSTS_N_INSNS (1);
3250
      else
3251
        * total = COSTS_N_INSNS (4);
3252
      break;
3253
 
3254
    case PLUS:
3255
    case MINUS:
3256
      if (mode == SFmode || mode == DFmode)
3257
        * total = COSTS_N_INSNS (6);
3258
      else if (mode == DImode)
3259
        * total = COSTS_N_INSNS (4);
3260
      else
3261
        * total = COSTS_N_INSNS (1);
3262
      break;
3263
 
3264
    case NEG:
3265
      * total = (mode == DImode) ? 4 : 1;
3266
      break;
3267
 
3268
    case MULT:
3269
      if (mode == SFmode)
3270
        * total = COSTS_N_INSNS (7);
3271
      else if (mode == DFmode)
3272
        * total = COSTS_N_INSNS (8);
3273
      else
3274
        * total = COSTS_N_INSNS (10);
3275
      break;
3276
 
3277
    case DIV:
3278
    case MOD:
3279
      if (mode == SFmode)
3280
        * total = COSTS_N_INSNS (23);
3281
      else if (mode == DFmode)
3282
        * total = COSTS_N_INSNS (36);
3283
      else
3284
        * total = COSTS_N_INSNS (69);
3285
      break;
3286
 
3287
    case UDIV:
3288
    case UMOD:
3289
      * total = COSTS_N_INSNS (69);
3290
      break;
3291
 
3292
    case SIGN_EXTEND:
3293
      * total = COSTS_N_INSNS (2);
3294
      break;
3295
 
3296
    case ZERO_EXTEND:
3297
      * total = COSTS_N_INSNS (1);
3298
      break;
3299
 
3300
    case CONST_INT:
3301
      * total = 0;
3302
      break;
3303
 
3304
    case LABEL_REF:
3305
      * total = COSTS_N_INSNS (2);
3306
      break;
3307
 
3308
    case CONST:
3309
      {
3310
        rtx offset = const0_rtx;
3311
        rtx symref = eliminate_constant_term (XEXP (x, 0), & offset);
3312
 
3313
        if (GET_CODE (symref) == LABEL_REF)
3314
          * total = COSTS_N_INSNS (2);
3315
        else if (GET_CODE (symref) != SYMBOL_REF)
3316
          * total = COSTS_N_INSNS (4);
3317
        /* Let's be paranoid....  */
3318
        else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
3319
          * total = COSTS_N_INSNS (2);
3320
        else
3321
          * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
3322
        break;
3323
      }
3324
 
3325
    case SYMBOL_REF:
3326
      * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
3327
      break;
3328
 
3329
    case CONST_DOUBLE:
3330
      {
3331
        rtx high, low;
3332
 
3333
        split_double (x, & high, & low);
3334
 
3335
        * total = COSTS_N_INSNS (  (high == CONST0_RTX (GET_MODE (high))
3336
                                  || low == CONST0_RTX (GET_MODE (low)))
3337
                                   ? 2 : 4);
3338
        break;
3339
      }
3340
 
3341
    default:
3342
      return false;
3343
    }
3344
  return true;
3345
}
3346
 
3347
#include "gt-iq2000.h"

powered by: WebSVN 2.1.0

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