OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc2/] [gcc/] [config/] [iq2000/] [iq2000.c] - Blame information for rev 437

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

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

powered by: WebSVN 2.1.0

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