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

Subversion Repositories scarts

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Subroutines for insn-output.c for the SCARTS32 micro controller
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
3
   Contributed by Wolfgang Puffitsch <hausen@gmx.at>
4
                  Martin Walter <mwalter@opencores.org>
5
 
6
   This file is part of the SCARTS32 port of GCC
7
 
8
   GNU CC is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 2, or (at your option)
11
   any later version.
12
 
13
   GNU CC is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GNU CC; see the file COPYING.  If not, write to
20
   the Free Software Foundation, 59 Temple Place - Suite 330,
21
   Boston, MA 02111-1307, USA.  */
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
#include "rtl.h"
28
#include "regs.h"
29
#include "hard-reg-set.h"
30
#include "real.h"
31
#include "insn-config.h"
32
#include "conditions.h"
33
#include "insn-attr.h"
34
#include "flags.h"
35
#include "reload.h"
36
#include "tree.h"
37
#include "output.h"
38
#include "expr.h"
39
#include "toplev.h"
40
#include "obstack.h"
41
#include "function.h"
42
#include "recog.h"
43
#include "tm_p.h"
44
#include "target.h"
45
#include "target-def.h"
46
#include "debug.h"
47
#include "integrate.h"
48
 
49
static int    scarts32_naked_function_p (tree);
50
static int    interrupt_function_p (tree);
51
static int    signal_function_p (tree);
52
static int    scarts32_regs_to_save (HARD_REG_SET *);
53
static int    scarts32_num_arg_regs (enum machine_mode, tree);
54
static int    out_adj_stack_ptr (FILE *, int);
55
static tree   scarts32_handle_progmem_attribute (tree *, tree, tree, int, bool *);
56
static tree   scarts32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
57
const struct attribute_spec scarts32_attribute_table[];
58
static void   scarts32_asm_file_start (void);
59
static void   scarts32_asm_file_end (void);
60
static void   scarts32_output_function_prologue (FILE *, HOST_WIDE_INT);
61
static void   scarts32_output_function_epilogue (FILE *, HOST_WIDE_INT);
62
static void   scarts32_unique_section (tree, int);
63
static unsigned int scarts32_section_type_flags (tree, const char *, int);
64
 
65
static bool   scarts32_rtx_costs (rtx, int, int, int *);
66
static void   scarts32_asm_named_section(const char *name, unsigned int flags, tree decl);
67
 
68
static int    ptrreg_to_addr(int);
69
static rtx    next_cc_user(rtx);
70
 
71
/* Allocate registers from r1 to r4 for parameters for function calls */
72
#define FIRST_CUM_REG ARG0_REGNO
73
 
74
/* SCARTS32 register names {"r0", "r1", ..., "r15"} */
75
static const char *const scarts32_regnames[] = REGISTER_NAMES;
76
 
77
/* This holds the last insn address.  */
78
static int last_insn_address = 0;
79
 
80
/* Commands count in the compiled file */
81
static int commands_in_file;
82
 
83
/* Commands in the functions prologues in the compiled file */
84
static int commands_in_prologues;
85
 
86
/* Commands in the functions epilogues in the compiled file */
87
static int commands_in_epilogues;
88
 
89
/* Prologue/Epilogue size in words */
90
static int prologue_size;
91
static int epilogue_size;
92
 
93
/* Preprocessor macros to define depending on MCU type.  */
94
const char *scarts32_base_arch_macro;
95
const char *scarts32_extra_arch_macro;
96
 
97
/* Assembler only.  */
98
int scarts32_asm_only_p = 0;
99
 
100
struct base_arch_s {
101
  const char *const macro;
102
};
103
 
104
static const struct base_arch_s scarts32_arch_types[] = {
105
  { NULL },  /* unknown device specified */
106
  { "__SCARTS32_ARCH__=1" }
107
};
108
 
109
struct mcu_type_s {
110
  const char *const name;
111
  int arch;  /* index in scarts32_arch_types[] */
112
  /* Must lie outside user's namespace.  NULL == no macro.  */
113
  const char *const macro;
114
};
115
 
116
/* List of all known SCARTS32 MCU types.
117
   These are all equivalent and are here for completeness only */
118
static const struct mcu_type_s scarts32_mcu_types[] = {
119
  { "scarts32",     1, "__SCARTS32_scarts32__" },
120
  { NULL,        0, NULL }
121
};
122
 
123
int scarts32_case_values_threshold = (1 << 16);
124
 
125
/* Initialize the GCC target structure.  */
126
#undef TARGET_ASM_BYTE_OP
127
#define TARGET_ASM_BYTE_OP "\t.byte\t"
128
#undef TARGET_ASM_ALIGNED_HI_OP
129
#define TARGET_ASM_ALIGNED_HI_OP "\t.short\t"
130
#undef TARGET_ASM_ALIGNED_SI_OP
131
#define TARGET_ASM_ALIGNED_SI_OP "\t.int\t"
132
#undef TARGET_ASM_UNALIGNED_HI_OP
133
#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
134
#undef TARGET_ASM_UNALIGNED_SI_OP
135
#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
136
 
137
#undef TARGET_ASM_FILE_START
138
#define TARGET_ASM_FILE_START scarts32_asm_file_start
139
#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
140
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
141
#undef TARGET_ASM_FILE_END
142
#define TARGET_ASM_FILE_END scarts32_asm_file_end
143
 
144
#undef TARGET_ASM_FUNCTION_PROLOGUE
145
#define TARGET_ASM_FUNCTION_PROLOGUE scarts32_output_function_prologue
146
#undef TARGET_ASM_FUNCTION_EPILOGUE
147
#define TARGET_ASM_FUNCTION_EPILOGUE scarts32_output_function_epilogue
148
#undef TARGET_ATTRIBUTE_TABLE
149
#define TARGET_ATTRIBUTE_TABLE scarts32_attribute_table
150
#undef TARGET_ASM_UNIQUE_SECTION
151
#define TARGET_ASM_UNIQUE_SECTION scarts32_unique_section
152
#undef TARGET_SECTION_TYPE_FLAGS
153
#define TARGET_SECTION_TYPE_FLAGS scarts32_section_type_flags
154
 
155
#undef TARGET_RTX_COSTS
156
#define TARGET_RTX_COSTS scarts32_rtx_costs
157
 
158
#undef TARGET_ASM_NAMED_SECTION
159
#define TARGET_ASM_NAMED_SECTION scarts32_asm_named_section
160
 
161
struct gcc_target targetm = TARGET_INITIALIZER;
162
 
163
void
164
scarts32_override_options (void)
165
{
166
  const struct mcu_type_s *t;
167
  const struct base_arch_s *base;
168
 
169
  for (t = scarts32_mcu_types; t->name; t++)
170
    if (strcmp (t->name, scarts32_mcu_name) == 0)
171
      break;
172
 
173
  if (!t->name)
174
    {
175
      fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
176
               scarts32_mcu_name);
177
      for (t = scarts32_mcu_types; t->name; t++)
178
        fprintf (stderr,"   %s\n", t->name);
179
    }
180
 
181
  base = &scarts32_arch_types[t->arch];
182
  scarts32_base_arch_macro = base->macro;
183
  scarts32_extra_arch_macro = t->macro;
184
}
185
 
186
void
187
scarts32_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
188
{
189
}
190
 
191
/*  return register class from register number */
192
 
193
static const int reg_class_tab[]={
194
  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
195
  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
196
  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
197
  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
198
  POINTER_REGS, POINTER_REGS, POINTER_REGS, POINTER_REGS,
199
  NO_REGS
200
};
201
 
202
/* Return register class for register R */
203
 
204
enum reg_class
205
scarts32_regno_reg_class (int r)
206
{
207
  if (r >= 0 && r < FIRST_PSEUDO_REGISTER )
208
    return reg_class_tab[r];
209
  return ALL_REGS;
210
}
211
 
212
 
213
/* A C expression which defines the machine-dependent operand
214
   constraint letters for register classes.  If C is such a
215
   letter, the value should be the register class corresponding to
216
   it.  Otherwise, the value should be `NO_REGS'.  The register
217
   letter `r', corresponding to class `GENERAL_REGS', will not be
218
   passed to this macro; you do not need to handle it.  */
219
 
220
enum reg_class
221
scarts32_reg_class_from_letter  (int c)
222
{
223
  switch (c)
224
    {
225
    case 'q' : return POINTER_REGS;
226
    default: break;
227
    }
228
  return NO_REGS;
229
}
230
 
231
/* Define machine-dependent operand constraint letters (`I', `J', `K',
232
   ... `P') that specify particular ranges of integer values. */
233
int
234
scarts32_const_ok_for_letter(HOST_WIDE_INT value, char c)
235
{
236
  switch (c)
237
    {
238
    case 'I': /* one bit cleared */
239
      if (exact_log2 (~value) != -1)
240
        {
241
          return 1;
242
        }
243
      break;
244
    case 'J': /* one bit set */
245
      if (exact_log2 (value) != -1)
246
        {
247
          return 1;
248
        }
249
      break;
250
    case 'K': /* value for compare immediate */
251
      if ((value >= -0x40) && (value <= 0x3f))
252
        {
253
          return 1;
254
        }
255
      break;
256
    case 'L': /* loadable */
257
      if ((value >= -0x80) && (value <= 0x7f))
258
        {
259
          return 1;
260
        }
261
      break;
262
    case 'M': /* 16-bit value */
263
      if ((value >= -0x8000) && (value <= 0x7fff))
264
        {
265
          return 1;
266
        }
267
      break;
268
    case 'N': /* value for bittests */
269
      if ((value >= 0) && (value <= 31))
270
        {
271
          return 1;
272
        }
273
      break;
274
    case 'O': /* value for add immediate */
275
      if ((value >= -0x20) && (value <= 0x1f))
276
        {
277
          return 1;
278
        }
279
      break;
280
    case 'P': /* value for shifts */
281
      if ((value >= 0) && (value <= 15))
282
        {
283
          return 1;
284
        }
285
      break;
286
    }
287
  return 0;
288
}
289
 
290
/* Return nonzero if FUNC is a naked function.  */
291
 
292
static int
293
scarts32_naked_function_p (tree func)
294
{
295
  tree a;
296
 
297
  if (TREE_CODE (func) != FUNCTION_DECL)
298
    abort ();
299
 
300
  a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
301
  return a != NULL_TREE;
302
}
303
 
304
/* Return nonzero if FUNC is an interrupt function as specified
305
   by the "interrupt" attribute.  */
306
 
307
static int
308
interrupt_function_p (tree func)
309
{
310
  tree a;
311
 
312
  if (TREE_CODE (func) != FUNCTION_DECL)
313
    return 0;
314
 
315
  a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
316
  return a != NULL_TREE;
317
}
318
 
319
/* Return nonzero if FUNC is a signal function as specified
320
   by the "signal" attribute.  */
321
 
322
static int
323
signal_function_p (tree func)
324
{
325
  tree a;
326
 
327
  if (TREE_CODE (func) != FUNCTION_DECL)
328
    return 0;
329
 
330
  a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
331
  return a != NULL_TREE;
332
}
333
 
334
/* Return the number of hard registers to push/pop in the prologue/epilogue
335
   of the current function, and optionally store these registers in SET.  */
336
 
337
static int
338
scarts32_regs_to_save (HARD_REG_SET *set)
339
{
340
  int reg, count;
341
  int int_or_sig_p = (interrupt_function_p (current_function_decl)
342
                      || signal_function_p (current_function_decl));
343
  int leaf_func_p = leaf_function_p ();
344
 
345
  if (set)
346
    CLEAR_HARD_REG_SET (*set);
347
  count = 0;
348
 
349
  /* No need to save any registers if the function never returns.  */
350
  if (TREE_THIS_VOLATILE (current_function_decl))
351
    return 0;
352
 
353
  for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
354
    {
355
      /* Push frame pointer if necessary. */
356
      if (frame_pointer_needed && (reg == FRAME_POINTER_REGNUM))
357
        {
358
          if (set)
359
            SET_HARD_REG_BIT (*set, reg);
360
          count++;
361
        }
362
 
363
      /* Do not push/pop __tmp_reg__ as well as
364
         any global register variables.  */
365
      if (fixed_regs[reg])
366
        continue;
367
 
368
      /* Push "normal" registers. */
369
      if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
370
          || (regs_ever_live[reg] && (int_or_sig_p || !call_used_regs[reg])))
371
        {
372
          if (set)
373
            SET_HARD_REG_BIT (*set, reg);
374
          count++;
375
        }
376
    }
377
  return count;
378
}
379
 
380
/* Compute offset between arg_pointer, frame_pointer and
381
   stack_pointer.  */
382
int
383
initial_elimination_offset (int from, int to)
384
{
385
  int retval = 0;
386
 
387
  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
388
    {
389
      retval = get_frame_size();
390
    }
391
  else if (from == ARG_POINTER_REGNUM)
392
    {
393
      retval = (UNITS_PER_WORD * scarts32_regs_to_save(NULL));
394
      if (to == STACK_POINTER_REGNUM)
395
        {
396
          retval += get_frame_size();
397
        }
398
    }
399
  else
400
    abort();
401
 
402
  return retval;
403
}
404
 
405
/* Return 1 if the function epilogue is just a single "ret".  */
406
int
407
scarts32_simple_epilogue (void)
408
{
409
  return (! frame_pointer_needed
410
          && get_frame_size () == 0
411
          && scarts32_regs_to_save (NULL) == 0
412
          && ! interrupt_function_p (current_function_decl)
413
          && ! signal_function_p (current_function_decl)
414
          && ! scarts32_naked_function_p (current_function_decl)
415
          && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
416
          && ! TREE_THIS_VOLATILE (current_function_decl));
417
}
418
 
419
 
420
/* Return 1 if frame pointer for current function required.  */
421
int
422
frame_pointer_required_p (void)
423
{
424
  return (current_function_calls_alloca
425
          || current_function_args_size > 0
426
          || scarts32_regs_to_save(NULL) > 0
427
          || get_frame_size () > 0);
428
}
429
 
430
 
431
/* Output to FILE the asm instructions to adjust the frame pointer by
432
   ADJ (r26 -= ADJ;) which can be positive (prologue) or negative
433
   (epilogue).  Returns the number of instructions generated.  */
434
static int
435
out_adj_stack_ptr (FILE *file, int adj)
436
{
437
  int size = 0;
438
 
439
  adj = -adj;
440
 
441
  if (adj != 0)
442
    {
443
      if (adj <= 15 && adj >= -16)
444
        {
445
          fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr(STACK_POINTER_REGNUM));
446
          fprintf (file, "\tldw r13, r7\n");
447
          fprintf (file, "\taddi r13, %d\n", adj);
448
          fprintf (file, "\tstw r13, r7\n");
449
          size += 4;
450
        }
451
      else if (adj <= 127 && adj >= -128)
452
        {
453
          fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr(STACK_POINTER_REGNUM));
454
          fprintf (file, "\tldw r13, r7\n");
455
          fprintf (file, "\tldli r6, %d\n", adj);
456
          fprintf (file, "\tadd r13, r6\n");
457
          fprintf (file, "\tstw r13, r7\n");
458
          size += 5;
459
        }
460
      else if (adj <= 0x7fff && adj >= -0x8000)
461
        {
462
          fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr(STACK_POINTER_REGNUM));
463
          fprintf (file, "\tldw r13, r7\n");
464
          fprintf (file, "\tldli r6, %d\n", (int8_t)(adj & 0xFF));
465
          fprintf (file, "\tldhi r6, %d\n", (int8_t)((adj >> 8) & 0xFF));
466
          fprintf (file, "\tadd r13, r6\n");
467
          fprintf (file, "\tstw r13, r7\n");
468
          size += 6;
469
        }
470
      else
471
        {
472
          fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr(STACK_POINTER_REGNUM));
473
          fprintf (file, "\tldw r13, r7\n");
474
          fprintf (file, "\tldhi r6, %d\n ", (int8_t)((adj >> 24) & 0xFF));
475
          fprintf (file, "\tldliu r6, %u\n", (adj >> 16) & 0xFF);
476
          fprintf (file, "\tsli r6, 8\n");
477
          fprintf (file, "\tldliu r6, %u\n", (adj >> 8) & 0xFF);
478
          fprintf (file, "\tsli r6, 8\n");
479
          fprintf (file, "\tldliu r6, %u\n", (adj >> 0) & 0xFF);
480
          fprintf (file, "\tadd r13, r6\n");
481
          fprintf (file, "\tstw r13, r7\n");
482
          size += 10;
483
        }
484
    }
485
  return size;
486
}
487
 
488
/* Output function prologue */
489
 
490
static void
491
scarts32_output_function_prologue (FILE *file, HOST_WIDE_INT size)
492
{
493
  char *l;
494
  int   reg;
495
  int   interrupt_func_p, signal_func_p, main_p;
496
  HARD_REG_SET  set;
497
  HOST_WIDE_INT cfa_offset;
498
 
499
  cfa_offset = INCOMING_FRAME_SP_OFFSET;
500
  last_insn_address = prologue_size = 0;
501
 
502
  fprintf (file, "\t; prologue: stack frame size=%ld\n", size);
503
 
504
  if (scarts32_naked_function_p (current_function_decl))
505
  {
506
    fprintf(file, "\t; prologue: naked\n");
507
    goto out;
508
  }
509
 
510
  interrupt_func_p = interrupt_function_p (current_function_decl);
511
  signal_func_p = signal_function_p (current_function_decl);
512
  main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
513
 
514
  if (interrupt_func_p || signal_func_p)
515
  {
516
    /* Push r7 on the stack. */
517
    fprintf (file, "\tstfpz_dec r7, -1\n");
518
    prologue_size += 1;
519
 
520
    if (dwarf2out_do_frame ())
521
    {
522
      cfa_offset += (1 * UNITS_PER_WORD);
523
 
524
      l = (char *) dwarf2out_cfi_label ();
525
      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
526
      dwarf2out_reg_save (l, 7, -cfa_offset);
527
    }
528
 
529
    /* Push r13 on the stack. */
530
    fprintf (file, "\tstfpz_dec r13, -1\n");
531
    prologue_size += 1;
532
 
533
    if (dwarf2out_do_frame ())
534
    {
535
      cfa_offset += (1 * UNITS_PER_WORD);
536
 
537
      l = (char *) dwarf2out_cfi_label ();
538
      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
539
      dwarf2out_reg_save (l, 13, -cfa_offset);
540
    }
541
  }
542
 
543
  if (interrupt_func_p)
544
  {
545
    /* Push r15 on the stack. */
546
    fprintf(file, "\tstfpz_dec r15, -1\n");
547
    prologue_size += 1;
548
 
549
    if (dwarf2out_do_frame ())
550
    {
551
      cfa_offset += (1 * UNITS_PER_WORD);
552
 
553
      l = (char *) dwarf2out_cfi_label ();
554
      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
555
      dwarf2out_reg_save (l, 15, -cfa_offset);
556
    }
557
 
558
    /* Push the saved custom status byte on the stack. */
559
    fprintf (file, "\tldli r7, -8\n");
560
    fprintf (file, "\tldbu r13, r7\n");
561
    fprintf (file, "\tstfpz_dec r13, -1\n");
562
    prologue_size += 3;
563
 
564
    if (dwarf2out_do_frame ())
565
    {
566
      cfa_offset += (1 * UNITS_PER_WORD);
567
 
568
      l = (char *) dwarf2out_cfi_label ();
569
      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
570
      dwarf2out_reg_save (l, 13, -cfa_offset);
571
    }
572
 
573
    /* Set the GIE flag in the custom config byte. */
574
    fprintf (file, "\tldli r7, -29\n");
575
    fprintf (file, "\tldbu r13, r7\n");
576
    fprintf (file, "\tbset r13, 7\n");
577
    fprintf (file, "\tstb r13, r7\n");
578
    prologue_size += 4;
579
  }
580
 
581
  scarts32_regs_to_save (&set);
582
  for (reg = 0; reg < FIRST_PSEUDO_REGISTER; ++reg)
583
  {
584
    if (TEST_HARD_REG_BIT (set, reg))
585
    {
586
      if (scarts32_regno_reg_class (reg) == POINTER_REGS)
587
      {
588
        /* Push FP-register on the stack. */
589
        fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr (reg));
590
        fprintf (file, "\tldw r13, r7\n");
591
        fprintf (file, "\tstfpz_dec r13, -1\n");
592
        prologue_size += 3;
593
 
594
        if (dwarf2out_do_frame ())
595
        {
596
          cfa_offset += (1 * UNITS_PER_WORD);
597
 
598
          l = (char *) dwarf2out_cfi_label ();
599
          dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
600
          dwarf2out_reg_save (l, reg, -cfa_offset);
601
        }
602
      }
603
      else
604
      {
605
        /* Push 'normal' register on the stack. */
606
        fprintf(file, "\tstfpz_dec %s, -1\n", scarts32_regnames[reg]);
607
        prologue_size += 1;
608
 
609
        if (dwarf2out_do_frame ())
610
        {
611
          cfa_offset += (1 * UNITS_PER_WORD);
612
 
613
          l = (char *) dwarf2out_cfi_label ();
614
          dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
615
 
616
          if (reg == RA_REGNO)
617
            dwarf2out_return_save (l, -cfa_offset);
618
          else
619
            dwarf2out_reg_save (l, reg, -cfa_offset);
620
        }
621
      }
622
    }
623
  }
624
 
625
  if (frame_pointer_needed)
626
  {
627
    /* Replace FP with current SP. */
628
    fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr (STACK_POINTER_REGNUM));
629
    fprintf (file, "\tldw r13, r7\n");
630
    fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr (FRAME_POINTER_REGNUM));
631
    fprintf (file, "\tstw r13, r7\n");
632
    prologue_size += 4;
633
 
634
    if (size != 0)
635
    {
636
      /* Move SP down to make room for local variables and callee saved registers. */
637
      prologue_size += out_adj_stack_ptr (file, size);
638
 
639
      if (dwarf2out_do_frame ())
640
      {
641
        cfa_offset += size;
642
 
643
        l = (char *) dwarf2out_cfi_label ();
644
        dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
645
      }
646
    }
647
  }
648
 
649
  out:
650
    fprintf (file, "\t; prologue end (size=%d)\n", prologue_size);
651
}
652
 
653
/* Output function epilogue */
654
 
655
static void
656
scarts32_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
657
{
658
  int function_size, reg;
659
  int interrupt_func_p, signal_func_p, main_p;
660
  rtx first, last;
661
  HARD_REG_SET set;
662
 
663
  function_size = 0;
664
  interrupt_func_p = interrupt_function_p (current_function_decl);
665
  signal_func_p = signal_function_p (current_function_decl);
666
  main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
667
  last = get_last_nonnote_insn ();
668
 
669
  epilogue_size = 0;
670
 
671
  if (last)
672
  {
673
    first = get_first_nonnote_insn ();
674
    function_size += (INSN_ADDRESSES (INSN_UID (last)) - INSN_ADDRESSES (INSN_UID (first)));
675
    function_size += get_attr_length (last);
676
  }
677
 
678
  fprintf (file, "\t; epilogue: stack frame size=%ld\n", size);
679
 
680
  if (scarts32_naked_function_p (current_function_decl))
681
  {
682
    fprintf (file, "\t; epilogue: naked\n");
683
    goto out;
684
  }
685
 
686
  if (last && GET_CODE (last) == BARRIER)
687
  {
688
    fprintf (file, "\t; epilogue: noreturn\n");
689
    goto out;
690
  }
691
 
692
  scarts32_regs_to_save (&set);
693
  if (frame_pointer_needed)
694
  {
695
    if (size != 0)
696
    {
697
      epilogue_size += out_adj_stack_ptr (file, -size);
698
    }
699
  }
700
 
701
  for (reg = FIRST_PSEUDO_REGISTER-1; reg >= 0; --reg)
702
  {
703
    if (TEST_HARD_REG_BIT (set, reg))
704
    {
705
      if (scarts32_regno_reg_class(reg) == POINTER_REGS)
706
      {
707
        fprintf (file, "\tldli r7, %d\n", ptrreg_to_addr(reg));
708
        fprintf (file, "\tldfpz_inc r13, 0\n");
709
        fprintf (file, "\tstw r13, r7\n");
710
        epilogue_size += 3;
711
      }
712
      else
713
      {
714
        fprintf (file, "\tldfpz_inc %s, 0\n", scarts32_regnames[reg]);
715
        epilogue_size += 1;
716
      }
717
    }
718
  }
719
 
720
  if (interrupt_func_p)
721
  {
722
    /* Restore the saved custom status byte from the stack. */
723
    fprintf (file, "\tldli r7, -8\n");
724
    fprintf (file, "\tldfpz_inc r13, 0\n");
725
    fprintf (file, "\tstb r13, r7\n");
726
 
727
    fprintf (file, "\tldfpz_inc r15, 0\n");
728
    epilogue_size += 4;
729
 
730
  }
731
 
732
  if (interrupt_func_p || signal_func_p)
733
  {
734
    fprintf (file, "\tldfpz_inc r13, 0\n");
735
    fprintf (file, "\tldfpz_inc r7, 0\n");
736
    fprintf (file, "\trte\n");
737
    epilogue_size += 3;
738
  }
739
  else
740
  {
741
    fprintf (file, "\trts\n");
742
    epilogue_size += 1;
743
  }
744
 
745
  out:
746
    fprintf (file, "\t;epilogue end (size=%d)\n", epilogue_size);
747
    fprintf (file, "\t;function %s size %d (%d)\n",
748
      (* targetm.strip_name_encoding) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))),
749
      prologue_size + function_size + epilogue_size, function_size);
750
 
751
    commands_in_file += prologue_size + function_size + epilogue_size;
752
    commands_in_prologues += prologue_size;
753
    commands_in_epilogues += epilogue_size;
754
}
755
 
756
 
757
/* Return nonzero if X (an RTX) is a legitimate memory address on the target
758
   machine for a memory operand of mode MODE.  */
759
 
760
int
761
legitimate_address_p (enum machine_mode mode, rtx x, int strict)
762
{
763
  enum reg_class r = NO_REGS;
764
 
765
  if (TARGET_ALL_DEBUG)
766
    {
767
      fprintf (stderr, "mode: (%s) %s %s %s %s:",
768
               GET_MODE_NAME(mode),
769
               strict ? "(strict)": "",
770
               reload_completed ? "(reload_completed)": "",
771
               reload_in_progress ? "(reload_in_progress)": "",
772
               reg_renumber ? "(reg_renumber)" : "");
773
      if (GET_CODE (x) == PLUS
774
          && REG_P (XEXP (x, 0))
775
          && GET_CODE (XEXP (x, 1)) == CONST_INT
776
          && INTVAL (XEXP (x, 1)) >= (-16*UNITS_PER_WORD)
777
          && INTVAL (XEXP (x, 1)) <= (15*UNITS_PER_WORD)
778
          && reg_renumber
779
          )
780
        fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
781
                 true_regnum (XEXP (x, 0)));
782
      debug_rtx (x);
783
    }
784
 
785
  if (REG_P (x))
786
    {
787
      r = ALL_REGS;
788
      if (strict && (REGNO (x) >= FIRST_PSEUDO_REGISTER))
789
        {
790
          r = NO_REGS;
791
        }
792
    }
793
  else if (mode == SImode
794
           && GET_CODE (x) == PLUS
795
           && REG_P (XEXP (x, 0))
796
           && GET_CODE (XEXP (x, 1)) == CONST_INT)
797
    {
798
      if ((INTVAL (XEXP (x, 1)) >= (-16*UNITS_PER_WORD))
799
          && (INTVAL (XEXP (x, 1)) <= (15*UNITS_PER_WORD))
800
          && ((INTVAL (XEXP (x, 1)) % UNITS_PER_WORD) == 0)
801
          && ((REGNO (XEXP (x, 0)) == PTR_W)
802
              || (REGNO (XEXP (x, 0)) == PTR_X)
803
              || (REGNO (XEXP (x, 0)) == PTR_Y)
804
              || (REGNO (XEXP (x, 0)) == PTR_Z)))
805
        {
806
          r = POINTER_REGS;
807
        }
808
    }
809
 
810
  if (TARGET_ALL_DEBUG)
811
    {
812
      fprintf (stderr, "   ret = %d\n", r);
813
    }
814
  return r == NO_REGS ? 0 : (int)r;
815
}
816
 
817
/* Output X as assembler operand to file FILE */
818
void
819
print_operand (FILE *file, rtx x, int code)
820
{
821
  int abcd = 0;
822
  int signbit = 0;
823
 
824
  if (code >= 'A' && code <= 'B')
825
    abcd = code - 'A';
826
 
827
  if (code == 's')
828
    signbit = 1;
829
 
830
  if (REG_P (x))
831
    {
832
      fprintf (file, "%s", reg_names[true_regnum (x) + abcd]);
833
    }
834
  else if ((GET_CODE (x) == CONST_INT)
835
           || ((GET_CODE (x) == CONST_DOUBLE)
836
               && (GET_MODE (x) == VOIDmode)))
837
    {
838
      if (code == 't')
839
        {
840
          fprintf (file, "%d", (int8_t)((INTVAL (x) >> 0) & 0xFF));
841
        }
842
      else if (code == 'u')
843
        {
844
          fprintf (file, "%d", (int8_t)((INTVAL (x) >> 8) & 0xFF));
845
        }
846
      else if (code == 'v')
847
        {
848
          fprintf (file, "%d", (int8_t)((INTVAL (x) >> 16) & 0xFF));
849
        }
850
      else if (code == 'w')
851
        {
852
          fprintf (file, "%d", (int8_t)((INTVAL (x) >> 24) & 0xFF));
853
        }
854
      else if ((code == 'T') || (code == 'U') || (code == 'V') || (code == 'W'))
855
        {
856
          if (GET_CODE(x) == CONST_INT)
857
            {
858
              /* MWA: the code below creates the 64-bit target datatypes
859
                 on a 64-bit host machine.
860
                 FIXME: the higher 4 bytes of double data types also get
861
                 created by this code, which probably is not correct. */
862
              if (code == 'T')
863
                {
864
                  fprintf (file, "%d", (int8_t)((INTVAL (x) >> 32) & 0xFF));
865
                }
866
              else if (code == 'U')
867
                {
868
                  fprintf (file, "%d", (int8_t)((INTVAL (x) >> 40) & 0xFF));
869
                }
870
              else if (code == 'V')
871
                {
872
                  fprintf (file, "%d", (int8_t)((INTVAL (x) >> 48) & 0xFF));
873
                }
874
              else if (code == 'W')
875
                {
876
                  fprintf (file, "%d", (int8_t)((INTVAL (x) >> 56) & 0xFF));
877
                }
878
              else
879
                {
880
                  fprintf (file, "%d", INTVAL(x) >= 0 ? 0 : -1);
881
                }
882
            }
883
          else
884
            {
885
              if (code == 'T')
886
                {
887
                  fprintf (file, "%d", (int8_t)((CONST_DOUBLE_HIGH (x) >> 0) & 0xFF));
888
                }
889
              else if (code == 'U')
890
                {
891
                  fprintf (file, "%d", (int8_t)((CONST_DOUBLE_HIGH (x) >> 8) & 0xFF));
892
                }
893
              else if (code == 'V')
894
                {
895
                  fprintf (file, "%d", (int8_t)((CONST_DOUBLE_HIGH (x) >> 16) & 0xFF));
896
                }
897
              else if (code == 'W')
898
                {
899
                  fprintf (file, "%d", (int8_t)((CONST_DOUBLE_HIGH (x) >> 24) & 0xFF));
900
                }
901
            }
902
        }
903
      else
904
        {
905
          if (signbit)
906
            {
907
              fprintf (file, "%d", INTVAL(x) >= 0 ? 0 : -1);
908
            }
909
          else
910
            {
911
              fprintf (file, "%d", (int)(INTVAL (x) + abcd));
912
            }
913
        }
914
    }
915
  else if (GET_CODE (x) == MEM)
916
    {
917
      rtx addr = XEXP (x,0);
918
      output_address (addr);
919
    }
920
  else if (GET_CODE (x) == CONST_DOUBLE)
921
    {
922
      long val [2];
923
      REAL_VALUE_TYPE rv;
924
 
925
      REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
926
      if (GET_MODE (x) == SFmode)
927
        {
928
          REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
929
        }
930
      else
931
        {
932
          REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
933
        }
934
 
935
      if (code == 't')
936
        {
937
          fprintf (file, "%d", (int8_t)((val[0] >> 0) & 0xFF));
938
        }
939
      else if (code == 'u')
940
        {
941
          fprintf (file, "%d", (int8_t)((val[0] >> 8) & 0xFF));
942
        }
943
      else if (code == 'v')
944
        {
945
          fprintf (file, "%d", (int8_t)((val[0] >> 16) & 0xFF));
946
        }
947
      else if (code == 'w')
948
        {
949
          fprintf (file, "%d", (int8_t)((val[0] >> 24) & 0xFF));
950
        }
951
      else if (code == 'T')
952
        {
953
          fprintf (file, "%d", (int8_t)((val[1] >> 0) & 0xFF));
954
        }
955
      else if (code == 'U')
956
        {
957
          fprintf (file, "%d", (int8_t)((val[1] >> 8) & 0xFF));
958
        }
959
      else if (code == 'V')
960
        {
961
          fprintf (file, "%d", (int8_t)((val[1] >> 16) & 0xFF));
962
        }
963
      else if (code == 'W')
964
        {
965
          fprintf (file, "%d", (int8_t)((val[1] >> 24) & 0xFF));
966
        }
967
      else
968
        {
969
          fatal_insn ("internal compiler error. Invalid constant for output:", x);
970
        }
971
    }
972
  else
973
    {
974
      if (code == 'S')
975
        {
976
          if (GET_CODE (x) == SYMBOL_REF
977
              || GET_CODE (x) == LABEL_REF)
978
            {
979
              output_addr_const (file, x);
980
            }
981
          else if ((GET_CODE (x) == CONST)
982
                   && (GET_CODE (XEXP (x, 0)) == PLUS)
983
                   && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
984
            {
985
              output_addr_const (file, XEXP (XEXP (x, 0), 0));
986
            }
987
        }
988
      else
989
        {
990
          output_addr_const (file, x);
991
        }
992
    }
993
}
994
 
995
/* Recognize operand OP of mode MODE used in call instructions */
996
int
997
call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
998
{
999
  if (GET_CODE (op) == MEM)
1000
    {
1001
      rtx inside = XEXP (op, 0);
1002
 
1003
      if (register_operand (inside, Pmode))
1004
        return 1;
1005
      if (CONSTANT_ADDRESS_P (inside))
1006
        return 1;
1007
    }
1008
  return 0;
1009
}
1010
 
1011
/* Choose mode for jump insn:
1012
   SCARTS32_NEAR_JUMP - relative jump in range -256 <= x <= 511
1013
   SCARTS32_FAR_JUMP - relative jump outside of near range */
1014
int
1015
scarts32_jump_mode (rtx x, rtx insn)
1016
{
1017
  int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1018
                                            ? XEXP (x, 0) : x));
1019
  int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1020
  int jump_distance = dest_addr - cur_addr;
1021
 
1022
  if ((jump_distance >= -256) && (jump_distance <= 511))
1023
    return SCARTS32_NEAR_JUMP;
1024
 
1025
  return SCARTS32_FAR_JUMP;
1026
}
1027
 
1028
/* Output all insn addresses and their sizes into the assembly language
1029
   output file.  This is helpful for debugging whether the length attributes
1030
   in the md file are correct.
1031
   Output insn cost for next insn.  */
1032
 
1033
void
1034
final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, int num_operands ATTRIBUTE_UNUSED)
1035
{
1036
  int uid = INSN_UID (insn);
1037
 
1038
  if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1039
    {
1040
      fprintf (asm_out_file, "\t; DEBUG: 0x%x\t\t%d\t%d\n",
1041
               INSN_ADDRESSES (uid),
1042
               INSN_ADDRESSES (uid) - last_insn_address,
1043
               rtx_cost (PATTERN (insn), INSN));
1044
    }
1045
  last_insn_address = INSN_ADDRESSES (uid);
1046
 
1047
  if (TARGET_RTL_DUMP)
1048
    {
1049
      fprintf (asm_out_file, "#################\n");
1050
      print_rtl_single (asm_out_file, insn);
1051
      fprintf (asm_out_file, "#################\n");
1052
    }
1053
}
1054
 
1055
/* Returns nonzero if REGNO is the number of a hard
1056
   register in which function arguments are sometimes passed.  */
1057
int
1058
function_arg_regno_p(int r)
1059
{
1060
 /* argument passing is done in the registers r1 to r4 */
1061
  return (r >= FIRST_CUM_REG && r < (FIRST_CUM_REG+4));
1062
}
1063
 
1064
/* Initializing the variable cum for the state at the beginning
1065
   of the argument list.  */
1066
 
1067
void
1068
init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname, tree fndecl ATTRIBUTE_UNUSED)
1069
{
1070
  cum->nregs = 4; /* four registers are available for argument passing */
1071
  cum->regno = FIRST_CUM_REG;
1072
  if (!libname && fntype)
1073
    {
1074
      int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1075
                    && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1076
                        != void_type_node));
1077
      if (stdarg)
1078
        cum->nregs = 0;
1079
    }
1080
}
1081
 
1082
/* Returns the number of registers to allocate for a function argument.  */
1083
 
1084
static int
1085
scarts32_num_arg_regs (enum machine_mode mode, tree type)
1086
{
1087
  int size;
1088
 
1089
  if (mode == BLKmode)
1090
    size = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1091
  else
1092
    size = ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1093
 
1094
  return size;
1095
}
1096
 
1097
/* Controls whether a function argument is passed
1098
   in a register, and which register. */
1099
 
1100
rtx
1101
function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED)
1102
{
1103
  int regs = scarts32_num_arg_regs (mode, type);
1104
 
1105
  if ((cum->nregs > 0)
1106
      && (regs <= cum->nregs)
1107
      && (mode != BLKmode))
1108
    {
1109
      return gen_rtx_REG (mode, cum->regno);
1110
    }
1111
 
1112
  return NULL_RTX;
1113
}
1114
 
1115
/* Update the summarizer variable CUM to advance past an argument
1116
   in the argument list.  */
1117
 
1118
void
1119
function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED)
1120
{
1121
  int regs = scarts32_num_arg_regs (mode, type);
1122
 
1123
  cum->nregs -= regs;
1124
  cum->regno += regs;
1125
 
1126
  if (cum->nregs <= 0)
1127
    {
1128
      cum->nregs = 0;
1129
      cum->regno = FIRST_CUM_REG;
1130
    }
1131
}
1132
 
1133
/* Modifies the length assigned to instruction INSN
1134
   LEN is the initially computed length of the insn.  */
1135
 
1136
int
1137
adjust_insn_length (rtx insn ATTRIBUTE_UNUSED, int len)
1138
{
1139
  return len;
1140
}
1141
 
1142
/* Sets section name for declaration DECL */
1143
 
1144
static void
1145
scarts32_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1146
{
1147
  int len;
1148
  const char *name, *prefix;
1149
  char *string;
1150
 
1151
  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1152
  name = (* targetm.strip_name_encoding) (name);
1153
 
1154
  if (TREE_CODE (decl) == FUNCTION_DECL)
1155
    {
1156
      prefix = "__text.";
1157
    }
1158
  else if (TREE_PUBLIC (decl))
1159
    {
1160
      prefix = "";
1161
    }
1162
  else
1163
    {
1164
      prefix = "__data.";
1165
    }
1166
 
1167
  len = strlen (name) + strlen (prefix);
1168
  string = alloca (len + 1);
1169
  sprintf (string, "%s%s", prefix, name);
1170
  DECL_SECTION_NAME (decl) = build_string (len, string);
1171
}
1172
 
1173
/* Valid attributes:
1174
   progmem - put data to program memory;
1175
   signal - make a function to be hardware interrupt. After function
1176
   prologue interrupts are disabled;
1177
   interrupt - make a function to be hardware interrupt. After function
1178
   prologue interrupts are enabled;
1179
   naked     - don't generate function prologue/epilogue and `ret' command.
1180
 
1181
   Only `progmem' attribute valid for type.  */
1182
 
1183
const struct attribute_spec scarts32_attribute_table[] =
1184
  {
1185
    /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1186
    { "progmem",   0, 0, false, false, false,  scarts32_handle_progmem_attribute },
1187
    { "signal",    0, 0, true,  false, false,  scarts32_handle_fndecl_attribute },
1188
    { "interrupt", 0, 0, true,  false, false,  scarts32_handle_fndecl_attribute },
1189
    { "naked",     0, 0, true,  false, false,  scarts32_handle_fndecl_attribute },
1190
    { NULL,        0, 0, false, false, false, NULL }
1191
  };
1192
 
1193
/* Handle a "progmem" attribute; arguments as in
1194
   struct attribute_spec.handler.  */
1195
static tree
1196
scarts32_handle_progmem_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1197
{
1198
  if (DECL_P (*node))
1199
    {
1200
      if (TREE_CODE (*node) == TYPE_DECL)
1201
        {
1202
          /* This is really a decl attribute, not a type attribute,
1203
             but try to handle it for GCC 3.0 backwards compatibility.  */
1204
 
1205
          tree type = TREE_TYPE (*node);
1206
          tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
1207
          tree newtype = build_type_attribute_variant (type, attr);
1208
 
1209
          TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
1210
          TREE_TYPE (*node) = newtype;
1211
          *no_add_attrs = true;
1212
        }
1213
      else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
1214
        {
1215
          if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
1216
            {
1217
              warning (0, "only initialized variables can be placed into program memory area");
1218
              *no_add_attrs = true;
1219
            }
1220
        }
1221
      else
1222
        {
1223
          warning (0, "`%s' attribute ignored", IDENTIFIER_POINTER (name));
1224
          *no_add_attrs = true;
1225
        }
1226
    }
1227
 
1228
  return NULL_TREE;
1229
}
1230
 
1231
/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
1232
   struct attribute_spec.handler.  */
1233
static tree
1234
scarts32_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1235
{
1236
  if (TREE_CODE (*node) != FUNCTION_DECL)
1237
    {
1238
      warning (0, "`%s' attribute only applies to functions",
1239
               IDENTIFIER_POINTER (name));
1240
      *no_add_attrs = true;
1241
    }
1242
 
1243
  return NULL_TREE;
1244
}
1245
 
1246
/* Look for attribute `progmem' in DECL
1247
   if found return 1, otherwise 0.  */
1248
 
1249
int
1250
scarts32_progmem_p (tree decl)
1251
{
1252
  tree a;
1253
 
1254
  if (TREE_CODE (decl) != VAR_DECL)
1255
    return 0;
1256
 
1257
  if (NULL_TREE
1258
      != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
1259
    return 1;
1260
 
1261
  a=decl;
1262
  do
1263
    a = TREE_TYPE(a);
1264
  while (TREE_CODE (a) == ARRAY_TYPE);
1265
 
1266
  if (a == error_mark_node)
1267
    return 0;
1268
 
1269
  if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
1270
    return 1;
1271
 
1272
  return 0;
1273
}
1274
 
1275
static unsigned int
1276
scarts32_section_type_flags (tree decl, const char *name, int reloc)
1277
{
1278
  unsigned int flags = default_section_type_flags (decl, name, reloc);
1279
 
1280
  if (strncmp (name, ".noinit", 7) == 0)
1281
    {
1282
      if (decl && TREE_CODE (decl) == VAR_DECL
1283
          && DECL_INITIAL (decl) == NULL_TREE)
1284
        flags |= SECTION_BSS;  /* @nobits */
1285
      else
1286
        warning (0, "only uninitialized variables can be placed in the .noinit section");
1287
    }
1288
 
1289
  return flags;
1290
}
1291
 
1292
/* Outputs to the stdio stream FILE some
1293
   appropriate text to go at the start of an assembler file.  */
1294
 
1295
void
1296
scarts32_asm_file_start (void)
1297
{
1298
  fprintf (asm_out_file, "\t.file\t");
1299
  output_quoted_string (asm_out_file, main_input_filename);
1300
  fprintf (asm_out_file, "\n");
1301
 
1302
  commands_in_file = 0;
1303
  commands_in_prologues = 0;
1304
  commands_in_epilogues = 0;
1305
}
1306
 
1307
/* Outputs to the stdio stream FILE some
1308
   appropriate text to go at the end of an assembler file.  */
1309
 
1310
void
1311
scarts32_asm_file_end (void)
1312
{
1313
  if (flag_verbose_asm)
1314
    {
1315
      fprintf (asm_out_file, "\t; file ");
1316
      output_quoted_string (asm_out_file, main_input_filename);
1317
      fprintf (asm_out_file,
1318
               ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d\n",
1319
               commands_in_file,
1320
               commands_in_file,
1321
               commands_in_file - commands_in_prologues - commands_in_epilogues,
1322
               commands_in_prologues, commands_in_epilogues);
1323
    }
1324
}
1325
 
1326
static bool
1327
scarts32_rtx_costs (rtx x, int code, int outer_code, int *total)
1328
{
1329
  bool retval = false;
1330
 
1331
  switch (code)
1332
    {
1333
    case MEM:
1334
      *total = 2 + GET_MODE_SIZE (GET_MODE (x));
1335
      break;
1336
 
1337
    case CONST_DOUBLE:
1338
      if (GET_MODE (x) != VOIDmode)
1339
        {
1340
          *total = 6 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1341
          retval = true;
1342
          break;
1343
        }
1344
      else
1345
        {
1346
          /* fall through */
1347
        }
1348
    case CONST_INT:
1349
      if (outer_code == AND
1350
          && scarts32_const_ok_for_letter(INTVAL (x), 'I'))
1351
        *total = 0;
1352
      else if (outer_code == IOR
1353
               && scarts32_const_ok_for_letter(INTVAL (x), 'J'))
1354
        *total = 0;
1355
      else if (INTVAL (x) <= 15 && INTVAL (x) >= -16)
1356
        *total = 0;
1357
      else
1358
        *total = 6 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1359
      retval = true;
1360
      break;
1361
 
1362
    case CONST:
1363
    case LABEL_REF:
1364
    case SYMBOL_REF:
1365
      *total = 6 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1366
      retval = true;
1367
      break;
1368
 
1369
    case SUBREG:
1370
    case REG:
1371
      *total = 0;
1372
      retval = true;
1373
      break;
1374
 
1375
    case MINUS:
1376
    case PLUS:
1377
      if (outer_code == MEM)
1378
        *total = 1;
1379
      else
1380
        *total = 1 + GET_MODE_SIZE (GET_MODE (x));
1381
      break;
1382
 
1383
    case MULT:
1384
      *total = 10 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1385
      break;
1386
 
1387
    case DIV:
1388
    case UDIV:
1389
      *total = 30 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1390
      break;
1391
 
1392
    case MOD:
1393
    case UMOD:
1394
      *total = 35 * (1 + GET_MODE_SIZE (GET_MODE (x)));
1395
      break;
1396
 
1397
    default:
1398
      *total = 1 + GET_MODE_SIZE (GET_MODE (x));
1399
      break;
1400
    }
1401
 
1402
  *total *= COSTS_N_INSNS(1);
1403
 
1404
  return retval;
1405
}
1406
 
1407
/*  EXTRA_CONSTRAINT helper */
1408
int
1409
extra_constraint (rtx x ATTRIBUTE_UNUSED, int c ATTRIBUTE_UNUSED)
1410
{
1411
  return 0;
1412
}
1413
 
1414
/* Ceate an RTX representing the place where a
1415
   library function returns a value of mode MODE.  */
1416
 
1417
rtx
1418
scarts32_libcall_value (enum machine_mode mode)
1419
{
1420
  int offs = GET_MODE_SIZE (mode);
1421
  if (offs <= UNITS_PER_WORD)
1422
    return gen_rtx_REG (mode, RET_REGISTER);
1423
  else
1424
    return gen_rtx_REG (mode, -1);
1425
}
1426
 
1427
/* Create an RTX representing the place where a
1428
   function returns a value of data type VALTYPE.  */
1429
 
1430
rtx
1431
scarts32_function_value (tree type, tree func ATTRIBUTE_UNUSED)
1432
{
1433
  if (TYPE_MODE (type) != BLKmode)
1434
    return scarts32_libcall_value (TYPE_MODE (type));
1435
 
1436
  return gen_rtx_REG (BLKmode, -1);
1437
}
1438
 
1439
int
1440
test_hard_reg_class (enum reg_class class, rtx x)
1441
{
1442
  int regno = true_regnum (x);
1443
 
1444
  if (regno < 0)
1445
    return 0;
1446
 
1447
  if (TEST_HARD_REG_CLASS (class, regno))
1448
    return 1;
1449
 
1450
  return 0;
1451
}
1452
 
1453
const char *
1454
scarts32_out_movqi (rtx insn ATTRIBUTE_UNUSED, rtx operands [], int alternative)
1455
{
1456
  switch (alternative)
1457
    {
1458
    case 0:
1459
      output_asm_insn ("mov %0,%1", operands);
1460
      break;
1461
    case 1:
1462
      output_asm_insn ("ldli %0,%1", operands);
1463
      break;
1464
    case 2:
1465
      {
1466
        /* operands: src, dest [, offset] */
1467
        rtx x = XEXP (operands[0], 0);
1468
        if (REG_P (x))
1469
          {
1470
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1471
              {
1472
                operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(x)));
1473
                output_asm_insn ("ldli r13, %0", operands);
1474
                output_asm_insn ("ldw r13, r13", operands);
1475
                output_asm_insn ("stb %1,r13", operands);
1476
              }
1477
            else
1478
              {
1479
                output_asm_insn ("stb %1,%0", operands);
1480
              }
1481
          }
1482
        else
1483
          {
1484
            fatal_insn ("internal compiler error. Invalid memory insn:",
1485
                        operands[0]);
1486
          }
1487
      }
1488
      break;
1489
    case 3:
1490
      {
1491
        /* operands: dest, src [, offset] */
1492
        rtx x = XEXP (operands[1], 0);
1493
        if (REG_P (x))
1494
          {
1495
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1496
              {
1497
                operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(x)));
1498
                output_asm_insn ("ldli r13, %1", operands);
1499
                output_asm_insn ("ldw r13, r13", operands);
1500
                output_asm_insn ("ldbu %0,r13", operands);
1501
              }
1502
            else
1503
              {
1504
                output_asm_insn ("ldbu %0,%1", operands);
1505
              }
1506
          }
1507
        else
1508
          {
1509
            fatal_insn ("internal compiler error. Invalid memory insn:",
1510
                        operands[1]);
1511
          }
1512
      }
1513
      break;
1514
    default:
1515
      gcc_unreachable();
1516
    }
1517
  return "";
1518
}
1519
 
1520
const char *
1521
scarts32_out_movhi (rtx insn ATTRIBUTE_UNUSED, rtx operands [], int alternative)
1522
{
1523
  switch (alternative)
1524
    {
1525
    case 0:
1526
      output_asm_insn ("mov %0,%1", operands);
1527
      break;
1528
    case 1:
1529
      output_asm_insn ("ldli %0,%1", operands);
1530
      break;
1531
    case 2:
1532
      output_asm_insn ("ldli %0,%t1", operands);
1533
      output_asm_insn ("ldhi %0,%u1", operands);
1534
      break;
1535
    case 3:
1536
      {
1537
        /* operands: src, dest [, offset] */
1538
        rtx x = XEXP (operands[0], 0);
1539
        if (REG_P (x))
1540
          {
1541
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1542
              {
1543
                operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(x)));
1544
                output_asm_insn ("ldli r13, %0", operands);
1545
                output_asm_insn ("ldw r13, r13", operands);
1546
                output_asm_insn ("sth %1,r13", operands);
1547
              }
1548
            else
1549
              {
1550
                output_asm_insn ("sth %1,%0", operands);
1551
              }
1552
          }
1553
        else
1554
          {
1555
            fatal_insn ("internal compiler error. Invalid memory insn:",
1556
                        operands[0]);
1557
          }
1558
      }
1559
      break;
1560
    case 4:
1561
      {
1562
        /* operands: dest, src [, offset] */
1563
        rtx x = XEXP (operands[1], 0);
1564
        if (REG_P (x))
1565
          {
1566
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1567
              {
1568
                operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(x)));
1569
                output_asm_insn ("ldli r13, %1", operands);
1570
                output_asm_insn ("ldw r13, r13", operands);
1571
                output_asm_insn ("ldhu %0,r13", operands);
1572
              }
1573
            else
1574
              {
1575
                output_asm_insn ("ldhu %0,%1", operands);
1576
              }
1577
          }
1578
        else
1579
          {
1580
            fatal_insn ("internal compiler error. Invalid memory insn:",
1581
                        operands[1]);
1582
          }
1583
      }
1584
      break;
1585
    default:
1586
      gcc_unreachable();
1587
    }
1588
  return "";
1589
}
1590
 
1591
const char *
1592
scarts32_out_movsi (rtx insn ATTRIBUTE_UNUSED, rtx operands [], int alternative)
1593
{
1594
  switch (alternative)
1595
    {
1596
    case 0:
1597
      output_asm_insn ("mov %0,%1", operands);
1598
      break;
1599
    case 1:
1600
      output_asm_insn ("ldli %0,%1", operands);
1601
      break;
1602
    case 2:
1603
      output_asm_insn ("ldli %0,%t1", operands);
1604
      output_asm_insn ("ldhi %0,%u1", operands);
1605
      break;
1606
    case 3:
1607
      output_asm_insn ("ldhi  %0,%w1", operands);
1608
      output_asm_insn ("ldliu %0,%v1", operands);
1609
      output_asm_insn ("sli   %0,8", operands);
1610
      output_asm_insn ("ldliu %0,%u1", operands);
1611
      output_asm_insn ("sli   %0,8", operands);
1612
      output_asm_insn ("ldliu %0,%t1", operands);
1613
      break;
1614
    case 4:
1615
      output_asm_insn ("ldhi  %0,4th(%1)", operands);
1616
      output_asm_insn ("ldliu %0,3rd(%1)", operands);
1617
      output_asm_insn ("sli   %0,8", operands);
1618
      output_asm_insn ("ldliu %0,hi(%1)", operands);
1619
      output_asm_insn ("sli   %0,8", operands);
1620
      output_asm_insn ("ldliu %0,lo(%1)", operands);
1621
      break;
1622
    case 5:
1623
      {
1624
        /* operands: src, dest [, offset] */
1625
        rtx x = XEXP (operands[0], 0);
1626
        if (GET_CODE (x) == PLUS)
1627
          {
1628
            operands[0] = (XEXP (x, 0));
1629
            operands[2] = (XEXP (x, 1));
1630
 
1631
            if (REG_P (XEXP (x, 0)) && (GET_CODE (XEXP (x, 1)) == CONST_INT))
1632
              {
1633
                int disp = INTVAL (XEXP (x, 1));
1634
 
1635
                if ((disp >= (-16*UNITS_PER_WORD)) && (disp <= (15*UNITS_PER_WORD))
1636
                    && ((disp % UNITS_PER_WORD) == 0))
1637
                  {
1638
                    operands[2] = gen_rtx_CONST_INT(SImode, disp/UNITS_PER_WORD);
1639
 
1640
                    if (scarts32_regno_reg_class(true_regnum(operands[1])) == POINTER_REGS)
1641
                      {
1642
                        int clobbered = 0;
1643
 
1644
                        if (true_regnum(operands[1]) == STACK_POINTER_REGNUM)
1645
                          {
1646
                            clobbered = 1;
1647
                          }
1648
 
1649
                        operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[1])));
1650
 
1651
                        output_asm_insn ("stfpz_dec r7,-1", operands);
1652
                        output_asm_insn ("ldli r13,%1", operands);
1653
                        output_asm_insn ("ldw r7,r13", operands);
1654
                        if (clobbered)
1655
                          {
1656
                            output_asm_insn ("addi r7, 4", operands);
1657
                          }
1658
                        output_asm_insn ("st%0 r7,%2", operands);
1659
                        output_asm_insn ("ldfpz_inc r7,0", operands);
1660
                      }
1661
                    else
1662
                      {
1663
                        output_asm_insn ("st%0 %1,%2", operands);
1664
                      }
1665
                  }
1666
                else
1667
                  {
1668
                    fatal_insn ("internal compiler error. Invalid memory insn:",
1669
                                operands[0]);
1670
                  }
1671
              }
1672
            else
1673
              {
1674
                fatal_insn ("internal compiler error. Invalid memory insn:",
1675
                            operands[0]);
1676
              }
1677
          }
1678
        else if (REG_P (x))
1679
          {
1680
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1681
              {
1682
                if (scarts32_regno_reg_class(true_regnum(operands[1])) == POINTER_REGS)
1683
                  {
1684
                    int clobbered = 0;
1685
 
1686
                    if (true_regnum(operands[1]) == STACK_POINTER_REGNUM)
1687
                      {
1688
                        clobbered = 1;
1689
                      }
1690
 
1691
                    operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[1])));
1692
 
1693
                    output_asm_insn ("stfpz_dec r7,-1", operands);
1694
                    output_asm_insn ("ldli r13,%1", operands);
1695
                    output_asm_insn ("ldw r7,r13", operands);
1696
                    if (clobbered)
1697
                      {
1698
                        output_asm_insn ("addi r7, 4", operands);
1699
                      }
1700
                    output_asm_insn ("st%0 r7,0", operands);
1701
                    output_asm_insn ("ldfpz_inc r7,0", operands);
1702
                  }
1703
                else
1704
                  {
1705
                    output_asm_insn ("st%0 %1,0", operands);
1706
                  }
1707
              }
1708
            else
1709
              {
1710
                if (scarts32_regno_reg_class(true_regnum(operands[1])) == POINTER_REGS)
1711
                  {
1712
                    int clobbered = 0;
1713
 
1714
                    if (true_regnum(operands[1]) == STACK_POINTER_REGNUM)
1715
                      {
1716
                        clobbered = 1;
1717
                      }
1718
 
1719
                    operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[1])));
1720
 
1721
                    output_asm_insn ("stfpz_dec r7,-1", operands);
1722
                    output_asm_insn ("ldli r13,%1", operands);
1723
                    output_asm_insn ("ldw r7,r13", operands);
1724
                    if (clobbered)
1725
                      {
1726
                        output_asm_insn ("addi r7, 4", operands);
1727
                      }
1728
                    output_asm_insn ("stw r7,%0", operands);
1729
                    output_asm_insn ("ldfpz_inc r7,0", operands);
1730
                  }
1731
                else
1732
                  {
1733
                    output_asm_insn ("stw %1,%0", operands);
1734
                  }
1735
              }
1736
          }
1737
        else
1738
          {
1739
            fatal_insn ("internal compiler error. Invalid memory insn:",
1740
                        operands[0]);
1741
          }
1742
      }
1743
      break;
1744
 
1745
    case 6:
1746
      {
1747
        /* operands: dest, src [, offset] */
1748
        rtx x = XEXP (operands[1], 0);
1749
        if (GET_CODE (x) == PLUS)
1750
          {
1751
            operands[1] = (XEXP (x, 0));
1752
            operands[2] = (XEXP (x, 1));
1753
 
1754
            if (REG_P (operands[1]) && (GET_CODE (operands[2]) == CONST_INT))
1755
              {
1756
                int disp = INTVAL (XEXP (x, 1));
1757
 
1758
                if ((disp >= (-16*UNITS_PER_WORD)) && (disp <= (15*UNITS_PER_WORD))
1759
                    && ((disp % UNITS_PER_WORD) == 0))
1760
                  {
1761
                    operands[2] = gen_rtx_CONST_INT(SImode, disp/UNITS_PER_WORD);
1762
 
1763
                    if (scarts32_regno_reg_class(true_regnum(operands[0])) == POINTER_REGS)
1764
                      {
1765
                        if (true_regnum(operands[0]) == STACK_POINTER_REGNUM)
1766
                          {
1767
                            fatal_insn ("internal compiler error. Clobbered stack-pointer:", operands[1]);
1768
                          }
1769
 
1770
                        operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[0])));
1771
 
1772
                        output_asm_insn ("stfpz_dec r7,-1", operands);
1773
                        output_asm_insn ("ld%1 r7,%2", operands);
1774
                        output_asm_insn ("ldli r13,%0", operands);
1775
                        output_asm_insn ("stw r7,r13", operands);
1776
                        output_asm_insn ("ldfpz_inc r7,0", operands);
1777
                      }
1778
                    else
1779
                      {
1780
                        output_asm_insn ("ld%1 %0,%2", operands);
1781
                      }
1782
                  }
1783
                else
1784
                  {
1785
                    fatal_insn ("internal compiler error. Invalid memory insn:",
1786
                                operands[1]);
1787
                  }
1788
              }
1789
            else
1790
              {
1791
                fatal_insn ("internal compiler error. Invalid memory insn:",
1792
                            operands[1]);
1793
              }
1794
          }
1795
        else if (REG_P (x))
1796
          {
1797
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1798
              {
1799
                if (scarts32_regno_reg_class(true_regnum(operands[0])) == POINTER_REGS)
1800
                  {
1801
                    if (true_regnum(operands[0]) == STACK_POINTER_REGNUM)
1802
                      {
1803
                        fatal_insn ("internal compiler error. Clobbered stack-pointer:", operands[1]);
1804
                      }
1805
 
1806
                    operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[0])));
1807
 
1808
                    output_asm_insn ("stfpz_dec r7,-1", operands);
1809
                    output_asm_insn ("ld%1 r7,0", operands);
1810
                    output_asm_insn ("ldli r13,%0", operands);
1811
                    output_asm_insn ("stw r7,r13", operands);
1812
                    output_asm_insn ("ldfpz_inc r7,0", operands);
1813
                  }
1814
                else
1815
                  {
1816
                    output_asm_insn ("ld%1 %0,0", operands);
1817
                  }
1818
              }
1819
            else
1820
              {
1821
                if (scarts32_regno_reg_class(true_regnum(operands[0])) == POINTER_REGS)
1822
                  {
1823
                    if (true_regnum(operands[0]) == STACK_POINTER_REGNUM)
1824
                      {
1825
                        fatal_insn ("internal compiler error. Clobbered stack-pointer:", operands[1]);
1826
                      }
1827
 
1828
                    operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[0])));
1829
 
1830
                    output_asm_insn ("stfpz_dec r7,-1", operands);
1831
                    output_asm_insn ("ldw r7,%1", operands);
1832
                    output_asm_insn ("ldli r13,%0", operands);
1833
                    output_asm_insn ("stw r7,r13", operands);
1834
                    output_asm_insn ("ldfpz_inc r7,0", operands);
1835
                  }
1836
                else
1837
                  {
1838
                    output_asm_insn ("ldw %0,%1", operands);
1839
                  }
1840
              }
1841
          }
1842
        else
1843
          {
1844
            fatal_insn ("internal compiler error. Invalid memory insn:",
1845
                        operands[1]);
1846
          }
1847
      }
1848
      break;
1849
 
1850
    case 7:
1851
      {
1852
        if (scarts32_regno_reg_class(true_regnum(operands[1])) == POINTER_REGS)
1853
          {
1854
            if (scarts32_regno_reg_class(true_regnum(operands[0])) == POINTER_REGS)
1855
              {
1856
                int clobbered = 0;
1857
 
1858
                if (true_regnum(operands[0]) == STACK_POINTER_REGNUM)
1859
                  {
1860
                    fatal_insn ("internal compiler error. Clobbered stack-pointer:", operands[1]);
1861
                  }
1862
                else if (true_regnum(operands[1]) == STACK_POINTER_REGNUM)
1863
                  {
1864
                    clobbered = 1;
1865
                  }
1866
 
1867
                operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[0])));
1868
                operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[1])));
1869
 
1870
                output_asm_insn ("stfpz_dec r7,-1", operands);
1871
                output_asm_insn ("ldli r13,%1", operands);
1872
                output_asm_insn ("ldw r7,r13", operands);
1873
                if (clobbered)
1874
                  {
1875
                    output_asm_insn ("addi r7, 4", operands);
1876
                  }
1877
                output_asm_insn ("ldli r13,%0", operands);
1878
                output_asm_insn ("stw r7,r13", operands);
1879
                output_asm_insn ("ldfpz_inc r7,0", operands);
1880
              }
1881
            else
1882
              {
1883
                operands[1] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[1])));
1884
                output_asm_insn ("ldli r13,%1", operands);
1885
                output_asm_insn ("ldw %0,r13", operands);
1886
              }
1887
          }
1888
        else
1889
          {
1890
            if (scarts32_regno_reg_class(true_regnum(operands[0])) == POINTER_REGS)
1891
              {
1892
                operands[0] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[0])));
1893
                output_asm_insn ("ldli r13,%0", operands);
1894
                output_asm_insn ("stw %1,r13", operands);
1895
              }
1896
            else
1897
              {
1898
                output_asm_insn ("mov %0,%1", operands);
1899
              }
1900
          }
1901
      }
1902
      break;
1903
 
1904
    default:
1905
      gcc_unreachable();
1906
    }
1907
  return "";
1908
}
1909
 
1910
const char *
1911
scarts32_out_movdi (rtx insn ATTRIBUTE_UNUSED, rtx operands [], int alternative)
1912
{
1913
  switch (alternative)
1914
    {
1915
    case 0:
1916
      if (true_regnum(operands[0]) < true_regnum(operands[1]))
1917
        {
1918
          output_asm_insn ("mov %A0,%A1", operands);
1919
          output_asm_insn ("mov %B0,%B1", operands);
1920
        }
1921
      else
1922
        {
1923
          output_asm_insn ("mov %B0,%B1", operands);
1924
          output_asm_insn ("mov %A0,%A1", operands);
1925
        }
1926
      break;
1927
    case 1:
1928
      output_asm_insn ("ldli %A0,%1", operands);
1929
      output_asm_insn ("ldli %B0,%s1", operands);
1930
      break;
1931
    case 2:
1932
      output_asm_insn ("ldhi  %A0,%w1", operands);
1933
      output_asm_insn ("ldliu %A0,%v1", operands);
1934
      output_asm_insn ("sli   %A0,8", operands);
1935
      output_asm_insn ("ldliu %A0,%u1", operands);
1936
      output_asm_insn ("sli   %A0,8", operands);
1937
      output_asm_insn ("ldliu %A0,%t1", operands);
1938
      output_asm_insn ("ldhi  %B0,%W1", operands);
1939
      output_asm_insn ("ldliu %B0,%V1", operands);
1940
      output_asm_insn ("sli   %B0,8", operands);
1941
      output_asm_insn ("ldliu %B0,%U1", operands);
1942
      output_asm_insn ("sli   %B0,8", operands);
1943
      output_asm_insn ("ldliu %B0,%T1", operands);
1944
      break;
1945
    case 3:
1946
      {
1947
        /* operands: src, dest [, offset] */
1948
        rtx x = XEXP (operands[0], 0);
1949
        if (GET_CODE (x) == PLUS)
1950
          {
1951
            operands[0] = (XEXP (x, 0));
1952
            operands[2] = (XEXP (x, 1));
1953
 
1954
            if (REG_P (XEXP (x, 0)) && (GET_CODE (XEXP (x, 1)) == CONST_INT))
1955
              {
1956
                int disp = INTVAL (XEXP (x, 1));
1957
 
1958
                if ((disp >= (-16*UNITS_PER_WORD)) && (disp <= (14*UNITS_PER_WORD))
1959
                    && ((disp % UNITS_PER_WORD) == 0))
1960
                  {
1961
                    operands[2] = gen_rtx_CONST_INT(SImode, disp/UNITS_PER_WORD);
1962
 
1963
                    output_asm_insn ("st%0 %A1,%A2", operands);
1964
                    output_asm_insn ("st%0 %B1,%B2", operands);
1965
                  }
1966
                else
1967
                  {
1968
                    fatal_insn ("internal compiler error. Invalid memory insn:",
1969
                                operands[0]);
1970
                  }
1971
              }
1972
            else
1973
              {
1974
                fatal_insn ("internal compiler error. Invalid memory insn:",
1975
                            operands[0]);
1976
              }
1977
          }
1978
        else if (REG_P (x))
1979
          {
1980
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
1981
              {
1982
                output_asm_insn ("st%0 %A1,0", operands);
1983
                output_asm_insn ("st%0 %B1,1", operands);
1984
              }
1985
            else
1986
              {
1987
                output_asm_insn ("mov r13,%0", operands);
1988
                output_asm_insn ("stw %A1,r13", operands);
1989
                output_asm_insn ("addi r13, 4", operands);
1990
                output_asm_insn ("stw %B1,r13", operands);
1991
              }
1992
          }
1993
        else
1994
          {
1995
            fatal_insn ("internal compiler error. Invalid memory insn:",
1996
                        operands[0]);
1997
          }
1998
      }
1999
      break;
2000
    case 4:
2001
      {
2002
        /* operands: dest, src [, offset] */
2003
        rtx x = XEXP (operands[1], 0);
2004
        if (GET_CODE (x) == PLUS)
2005
          {
2006
            operands[1] = (XEXP (x, 0));
2007
            operands[2] = (XEXP (x, 1));
2008
 
2009
            if (REG_P (XEXP (x, 0)) && (GET_CODE (XEXP (x, 1)) == CONST_INT))
2010
              {
2011
                int disp = INTVAL (XEXP (x, 1));
2012
 
2013
                if ((disp >= (-16*UNITS_PER_WORD)) && (disp <= (14*UNITS_PER_WORD))
2014
                    && ((disp % UNITS_PER_WORD) == 0))
2015
                  {
2016
                    operands[2] = gen_rtx_CONST_INT(SImode, disp/UNITS_PER_WORD);
2017
 
2018
                    output_asm_insn ("ld%1 %A0,%A2", operands);
2019
                    output_asm_insn ("ld%1 %B0,%B2", operands);
2020
                  }
2021
                else
2022
                  {
2023
                    fatal_insn ("internal compiler error. Invalid memory insn:",
2024
                                operands[1]);
2025
                  }
2026
              }
2027
            else
2028
              {
2029
                fatal_insn ("internal compiler error. Invalid memory insn:",
2030
                            operands[1]);
2031
              }
2032
          }
2033
        else if (REG_P (x))
2034
          {
2035
            if (scarts32_regno_reg_class(true_regnum(x)) == POINTER_REGS)
2036
              {
2037
                output_asm_insn ("ld%1 %A0,0", operands);
2038
                output_asm_insn ("ld%1 %B0,1", operands);
2039
              }
2040
            else
2041
              {
2042
                output_asm_insn ("mov r13,%1", operands);
2043
                output_asm_insn ("ldw %A0,r13", operands);
2044
                output_asm_insn ("addi r13, 4", operands);
2045
                output_asm_insn ("ldw %B0,r13", operands);
2046
              }
2047
          }
2048
        else
2049
          {
2050
            fatal_insn ("internal compiler error. Invalid memory insn:",
2051
                        operands[1]);
2052
          }
2053
      }
2054
      break;
2055
    default:
2056
      gcc_unreachable();
2057
    }
2058
  return "";
2059
}
2060
 
2061
const char *
2062
scarts32_out_addsi (rtx insn ATTRIBUTE_UNUSED, rtx operands [], int alternative)
2063
{
2064
  switch (alternative)
2065
    {
2066
    case 0:
2067
      if (scarts32_regno_reg_class(true_regnum(operands[2])) == POINTER_REGS)
2068
        {
2069
          operands[2] = gen_rtx_CONST_INT(SImode, ptrreg_to_addr(true_regnum(operands[2])));
2070
          output_asm_insn ("ldli r13, %2", operands);
2071
          output_asm_insn ("ldw r13, r13", operands);
2072
          output_asm_insn ("add %0, r13", operands);
2073
        }
2074
      else
2075
        {
2076
          output_asm_insn ("add %0,%2", operands);
2077
        }
2078
      break;
2079
    case 1:
2080
      output_asm_insn ("addi %0,%2", operands);
2081
      break;
2082
    default:
2083
      gcc_unreachable();
2084
    }
2085
  return "";
2086
}
2087
 
2088
static int ptrreg_to_addr(int reg)
2089
{
2090
  if (reg == PTR_W)
2091
    {
2092
      return -24;
2093
    }
2094
  else if (reg == PTR_X)
2095
    {
2096
      return -20;
2097
    }
2098
  else if (reg == PTR_Y)
2099
    {
2100
      return -16;
2101
    }
2102
  else if (reg == PTR_Z)
2103
    {
2104
      return -12;
2105
    }
2106
 
2107
  gcc_unreachable();
2108
}
2109
 
2110
static rtx next_cc_user(rtx insn)
2111
{
2112
  rtx user = next_active_insn(insn);
2113
 
2114
  /* find real user of condition code */
2115
  while (regno_use_in(CC_REGNO, PATTERN (user) ) == NULL_RTX)
2116
    {
2117
      /* must be an unconditional jump */
2118
      if (JUMP_P(user))
2119
        {
2120
          /* follow the jump */
2121
          user = next_active_insn(follow_jumps(JUMP_LABEL(user)));
2122
        }
2123
      else
2124
        {
2125
          /* get next insn */
2126
          user = next_active_insn(user);
2127
        }
2128
    }
2129
 
2130
  return user;
2131
}
2132
 
2133
const char *
2134
scarts32_out_compare (rtx insn, rtx operands [])
2135
{
2136
  enum rtx_code code;
2137
 
2138
  rtx user = next_cc_user(insn);
2139
 
2140
  /* which comparison do we want */
2141
  if (GET_CODE(PATTERN (user)) == COND_EXEC)
2142
    {
2143
      code = GET_CODE ( COND_EXEC_TEST ( PATTERN (user) ));
2144
    }
2145
  else
2146
    {
2147
      code = GET_CODE ( XEXP ( XEXP ( PATTERN (user), 1), 0));
2148
    }
2149
 
2150
  if (GET_MODE(operands[0]) == SImode)
2151
    {
2152
      switch(code)
2153
        {
2154
        case NE: /* inverse jump */
2155
        case EQ: /* straight jump */
2156
          if (CONSTANT_P(operands[1]))
2157
            output_asm_insn ("cmpi_eq %0,%1", operands);
2158
          else
2159
            output_asm_insn ("cmp_eq %0,%1", operands);
2160
          break;
2161
        case GE: /* inverse jump */
2162
        case LT: /* straight jump */
2163
          if (CONSTANT_P(operands[1]))
2164
            output_asm_insn ("cmpi_lt %0,%1", operands);
2165
          else
2166
            output_asm_insn ("cmp_lt %0,%1", operands);
2167
          break;
2168
        case GEU: /* inverse jump */
2169
        case LTU: /* straight jump */
2170
          if (CONSTANT_P(operands[1]))
2171
            {
2172
              output_asm_insn ("ldli r13,%1", operands);
2173
              output_asm_insn ("cmpu_lt %0,r13", operands);
2174
            }
2175
          else
2176
            output_asm_insn ("cmpu_lt %0,%1", operands);
2177
          break;
2178
        case LE: /* inverse jump */
2179
        case GT: /* straight jump */
2180
          if (CONSTANT_P(operands[1]))
2181
            output_asm_insn ("cmpi_gt %0,%1", operands);
2182
          else
2183
            output_asm_insn ("cmp_gt %0,%1", operands);
2184
          break;
2185
        case LEU: /* inverse jump */
2186
        case GTU: /* straight jump */
2187
          if (CONSTANT_P(operands[1]))
2188
            {
2189
              output_asm_insn ("ldli r13,%1", operands);
2190
              output_asm_insn ("cmpu_gt %0,r13", operands);
2191
            }
2192
          else
2193
            output_asm_insn ("cmpu_gt %0,%1", operands);
2194
          break;
2195
        default:
2196
          fatal_insn ("internal compiler error.  Unknown operator:", user);
2197
        }
2198
    }
2199
  else if (GET_MODE(operands[0]) == DImode)
2200
    {
2201
      switch(code)
2202
        {
2203
        case NE: /* inverse jump */
2204
        case EQ: /* straight jump */
2205
          output_asm_insn ("cmp_eq %B0,%B1", operands);
2206
          output_asm_insn ("jmpi_cf .T%=", operands);
2207
          output_asm_insn ("cmp_eq %A0,%A1\n.T%=:", operands);
2208
          break;
2209
        case GE: /* inverse jump */
2210
        case LT: /* straight jump */
2211
          output_asm_insn ("cmp_lt %B0,%B1", operands);
2212
          output_asm_insn ("jmpi_ct .T%=", operands);
2213
          output_asm_insn ("cmp_gt %B0,%B1", operands);
2214
          output_asm_insn ("jmpi_ct .F%=", operands);
2215
          output_asm_insn ("cmpu_lt %A0,%A1", operands);
2216
          output_asm_insn ("jmpi_ct .T%=", operands);
2217
          output_asm_insn (".F%=: cmp_lt r13,r13", operands);
2218
          output_asm_insn (".T%=:", operands);
2219
          break;
2220
        case GEU: /* inverse jump */
2221
        case LTU: /* straight jump */
2222
          output_asm_insn ("cmpu_lt %B0,%B1", operands);
2223
          output_asm_insn ("jmpi_ct .T%=", operands);
2224
          output_asm_insn ("cmpu_gt %B0,%B1", operands);
2225
          output_asm_insn ("jmpi_ct .F%=", operands);
2226
          output_asm_insn ("cmpu_lt %A0,%A1", operands);
2227
          output_asm_insn ("jmpi_ct .T%=", operands);
2228
          output_asm_insn (".F%=: cmp_lt r13,r13", operands);
2229
          output_asm_insn (".T%=:", operands);
2230
          break;
2231
        case LE: /* inverse jump */
2232
        case GT: /* straight jump */
2233
          output_asm_insn ("cmp_gt %B0,%B1", operands);
2234
          output_asm_insn ("jmpi_ct .T%=", operands);
2235
          output_asm_insn ("cmp_lt %B0,%B1", operands);
2236
          output_asm_insn ("jmpi_ct .F%=", operands);
2237
          output_asm_insn ("cmpu_gt %A0,%A1", operands);
2238
          output_asm_insn ("jmpi_ct .T%=", operands);
2239
          output_asm_insn (".F%=: cmp_lt r13,r13", operands);
2240
          output_asm_insn (".T%=:", operands);
2241
          break;
2242
        case LEU: /* inverse jump */
2243
        case GTU: /* straight jump */
2244
          output_asm_insn ("cmpu_gt %B0,%B1", operands);
2245
          output_asm_insn ("jmpi_ct .T%=", operands);
2246
          output_asm_insn ("cmpu_lt %B0,%B1", operands);
2247
          output_asm_insn ("jmpi_ct .F%=", operands);
2248
          output_asm_insn ("cmpu_gt %A0,%A1", operands);
2249
          output_asm_insn ("jmpi_ct .T%=", operands);
2250
          output_asm_insn (".F%=: cmp_lt r13,r13", operands);
2251
          output_asm_insn (".T%=:", operands);
2252
          break;
2253
        default:
2254
          fatal_insn ("internal compiler error.  Unknown operator:", user);
2255
        }
2256
    }
2257
  else
2258
    {
2259
      fatal_insn ("internal compiler error.  Unknown or unsupported mode:", insn);
2260
    }
2261
 
2262
  return "";
2263
}
2264
 
2265
const char *
2266
scarts32_out_bittest (rtx insn, rtx operands [])
2267
{
2268
  enum rtx_code code;
2269
 
2270
  rtx cond;
2271
  rtx user = next_cc_user(insn);
2272
 
2273
  rtx op0, op1;
2274
 
2275
  /* which comparison do we want */
2276
  if (GET_CODE(PATTERN (user)) == COND_EXEC)
2277
    {
2278
      cond = COND_EXEC_TEST ( PATTERN (user) );
2279
    }
2280
  else
2281
    {
2282
      cond = XEXP ( XEXP ( PATTERN (user), 1), 0);
2283
    }
2284
 
2285
  code = GET_CODE(cond);
2286
 
2287
  /* copy operands, as they might be clobbered by the following */
2288
  op0 = operands[0];
2289
  op1 = operands[1];
2290
 
2291
  /* we have to reverse the condition for bit tests */
2292
  validate_replace_rtx (cond, reversed_condition (cond), user);
2293
 
2294
  /* copy back operands */
2295
  operands[0] = op0;
2296
  operands[1] = op1;
2297
 
2298
  if (GET_MODE(operands[0]) == SImode)
2299
    {
2300
      switch(code)
2301
        {
2302
        case EQ:
2303
        case LT:
2304
        case LTU:
2305
        case GT:
2306
        case GTU:
2307
        case NE:
2308
        case GE:
2309
        case GEU:
2310
        case LE:
2311
        case LEU:
2312
          output_asm_insn ("btest %0,%1", operands);
2313
          break;
2314
        default:
2315
          fatal_insn ("internal compiler error.  Unknown operator:", user);
2316
        }
2317
    }
2318
  else
2319
    {
2320
      fatal_insn ("internal compiler error.  Unknown or unsupported mode:", insn);
2321
    }
2322
 
2323
  return "";
2324
}
2325
 
2326
const char *
2327
scarts32_out_branch (rtx insn, rtx operands [], enum rtx_code code)
2328
{
2329
  int inverse_jump = 0;
2330
  int far_jump = (scarts32_jump_mode(operands[0], insn) == SCARTS32_FAR_JUMP);
2331
 
2332
  switch(code)
2333
    {
2334
    case EQ:
2335
    case LT:
2336
    case LTU:
2337
    case GT:
2338
    case GTU:
2339
      inverse_jump = 0;
2340
      break;
2341
    case NE:
2342
    case GE:
2343
    case GEU:
2344
    case LE:
2345
    case LEU:
2346
      inverse_jump = 1;
2347
      break;
2348
    default:
2349
      fatal_insn ("internal compiler error.  Unknown operator:", insn);
2350
    }
2351
 
2352
  if (far_jump)
2353
    {
2354
      output_asm_insn ("ldhi  r13,4th(%0)", operands);
2355
      output_asm_insn ("ldliu r13,3rd(%0)", operands);
2356
      output_asm_insn ("sli   r13,8", operands);
2357
      output_asm_insn ("ldliu r13,hi(%0)", operands);
2358
      output_asm_insn ("sli   r13,8", operands);
2359
      output_asm_insn ("ldliu r13,lo(%0)", operands);
2360
 
2361
      if (!inverse_jump)
2362
        {
2363
          output_asm_insn ("jmp_ct r13", operands);
2364
        }
2365
      else
2366
        {
2367
          output_asm_insn ("jmp_cf r13", operands);
2368
        }
2369
    }
2370
  else
2371
    {
2372
      if (!inverse_jump)
2373
        {
2374
          output_asm_insn ("jmpi_ct %0", operands);
2375
        }
2376
      else
2377
        {
2378
          output_asm_insn ("jmpi_cf %0", operands);
2379
        }
2380
    }
2381
 
2382
  return "";
2383
}
2384
 
2385
const char *
2386
scarts32_out_jump (rtx insn, rtx operands [])
2387
{
2388
  int far_jump;
2389
 
2390
  far_jump = (scarts32_jump_mode(operands[0], insn) == SCARTS32_FAR_JUMP);
2391
  if (far_jump)
2392
    {
2393
      output_asm_insn ("ldhi  r13,4th(%0)", operands);
2394
      output_asm_insn ("ldliu r13,3rd(%0)", operands);
2395
      output_asm_insn ("sli   r13,8", operands);
2396
      output_asm_insn ("ldliu r13,hi(%0)", operands);
2397
      output_asm_insn ("sli   r13,8", operands);
2398
      output_asm_insn ("ldliu r13,lo(%0)", operands);
2399
      output_asm_insn ("jmp r13", operands);
2400
    }
2401
  else
2402
    {
2403
      output_asm_insn ("jmpi %0", operands);
2404
    }
2405
 
2406
  return "";
2407
}
2408
 
2409
void
2410
scarts32_output_aligned_common(FILE *stream, const char *name, int size, int align)
2411
{
2412
  bss_section();
2413
  ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2414
  fprintf (stream, "\t.comm\t");
2415
  assemble_name (stream, name);
2416
  fprintf (stream, ",%d\n", size);
2417
}
2418
 
2419
void
2420
scarts32_output_aligned_local(FILE *stream, const char *name, int size, int align)
2421
{
2422
  bss_section();
2423
  ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2424
  fprintf (stream, "\t.lcomm\t");
2425
  assemble_name (stream, name);
2426
  fprintf (stream, ",%d\n", size);
2427
}
2428
 
2429
void
2430
scarts32_output_aligned_bss(FILE *stream, tree decl ATTRIBUTE_UNUSED,
2431
                           const char *name, int size, int align)
2432
{
2433
  bss_section();
2434
  ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2435
  ASM_OUTPUT_LABEL (stream, name);
2436
  fprintf (stream, "\t.skip\t%d\n", size);
2437
}
2438
 
2439
void
2440
scarts32_asm_named_section(const char *name,
2441
                          unsigned int flags ATTRIBUTE_UNUSED,
2442
                          tree decl ATTRIBUTE_UNUSED)
2443
{
2444
  fprintf (asm_out_file, "\t.section\t%s\n", name);
2445
}
2446
 
2447
/* Return an RTX indicating where the return address to the
2448
   calling function can be found. */
2449
rtx
2450
scarts32_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2451
{
2452
  if (count != 0)
2453
    return NULL_RTX;
2454
 
2455
  return get_hard_reg_initial_val (Pmode, RA_REGNO);
2456
}
2457
 

powered by: WebSVN 2.1.0

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