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

Subversion Repositories scarts

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

powered by: WebSVN 2.1.0

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