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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [config/] [iq2000/] [iq2000.c] - Blame information for rev 455

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

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

powered by: WebSVN 2.1.0

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