Annotation of gcc/config/sh/sh.c, revision 1.1.1.1

1.1       root        1: /* Output routines for GCC for Hitachi Super-H
                      2:    Copyright (C) 1993 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: /* Contributed by Steve Chamberlain ([email protected]) */
                     22: 
                     23: #include <stdio.h>
                     24: #include "assert.h"
                     25: #include "config.h"
                     26: #include "rtl.h"
                     27: #include "regs.h"
                     28: #include "hard-reg-set.h"
                     29: #include "real.h"
                     30: #include "insn-config.h"
                     31: #include "conditions.h"
                     32: #include "insn-flags.h"
                     33: #include "tree.h"
                     34: #include "output.h"
                     35: #include "insn-attr.h"
                     36: #include "flags.h"
                     37: #include "obstack.h"
                     38: #include "expr.h"
                     39: 
                     40: 
                     41: static int add_constant ();
                     42: static int dump_constants ();
                     43: 
                     44: int current_function_anonymous_args;
                     45: extern int current_function_pretend_args_size;
                     46: 
                     47: /* Global variables for machine-dependent things. */
                     48: 
                     49: /* Saved operands from the last compare to use when we generate an scc
                     50:   or bcc insn. */
                     51: 
                     52: rtx sh_compare_op0;
                     53: rtx sh_compare_op1;
                     54: 
                     55: /* Provides the class number of the smallest class containing
                     56:    reg number */
                     57: 
                     58: int regno_reg_class[FIRST_PSEUDO_REGISTER] =
                     59: {
                     60:   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     61:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     62:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     63:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     64:   GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, MAC_REGS,
                     65:   MAC_REGS,
                     66: };
                     67: 
                     68: /* Provide reg_class from a letter such as appears in the machine
                     69:    description. */
                     70: 
                     71: enum reg_class reg_class_from_letter[] =
                     72: {
                     73:   /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
                     74:   /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
                     75:   /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
                     76:   /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
                     77:   /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
                     78:   /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
                     79:   /* y */ NO_REGS, /* z */ R0_REGS
                     80: };
                     81: 
                     82: 
                     83: /* Local label counter, used for constants in the pool and inside
                     84:    pattern branches.  */
                     85: 
                     86: static int lf = 100;
                     87: 
                     88: /* Used to work out sizes of instructions */
                     89: static int first_pc;
                     90: static int pc;
                     91: #define MAYBE_DUMP_LEVEL 900
                     92: #define MUST_DUMP_LEVEL 1000
                     93: static int dumpnext;
                     94: 
                     95: /* Functions for generating procedure prologue and epilogue code */
                     96: 
                     97: /* Adjust the stack and return the number of bytes taken to do it */
                     98: 
                     99: static int
                    100: output_stack_adjust (file, direction, size)
                    101:      FILE *file;
                    102:      int direction;
                    103:      int size;
                    104: {
                    105:   int code_size;
                    106: 
                    107:   if (size > 127)
                    108:     {
                    109:       fprintf (file, "\tmov.l  LK%d,r13\n",
                    110:               add_constant (GEN_INT (size * direction), SImode));
                    111: 
                    112:       fprintf (file, "\tadd    r13,r15\n");
                    113:       code_size += 4;
                    114:     }
                    115:   else if (size)
                    116:     {
                    117:       fprintf (file, "\tadd    #%d,r15\n", direction * size);
                    118:       code_size += 2;
                    119:     }
                    120:   return code_size;
                    121: }
                    122: 
                    123: /* Generate code to push the regs specified in the mask, and return
                    124:    the number of bytes the insns take. */
                    125: 
                    126: static int
                    127: push_regs (f, mask)
                    128:      FILE *f;
                    129:      int mask;
                    130: {
                    131:   int i;
                    132:   int size = 0;
                    133: 
                    134:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                    135:     {
                    136:       if (mask & (1 << i))
                    137:        {
                    138:          fprintf (f, "\tmov.l  r%d,@-r15\n", i);
                    139:          size += 2;
                    140:        }
                    141:     }
                    142:   return size;
                    143: }
                    144: 
                    145: 
                    146: /* Working out the right code to use for an epilogue can get quite
                    147:    hairy, since there are only certain insns which can go in the delay
                    148:    slot, and there may or may not be a delay insn provided already.
                    149: 
                    150:    We generate a canonical list of the instructions to use to perform
                    151:    the exit, massage that and output from that list */
                    152: 
                    153: 
                    154: /* The structure of a canonical element. */
                    155: 
                    156: typedef struct
                    157: {
                    158:   enum epi_type
                    159:     {
                    160:       STACK_ADJUST,            /* add i to stack pointer       */
                    161:       POP,                     /* pop into register i          */
                    162:       RTS,                     /* rts instruction              */
                    163:       DELAY,                   /* delay slot instruction       */
                    164:       NOP,                     /* a nop                        */
                    165:       DELETED,
                    166:     } type;
                    167:   int i;
                    168: }
                    169: 
                    170: epilogue_insn;
                    171: 
                    172: static epilogue_insn epilogue_vec[20];
                    173: static int epilogue_vec_len;
                    174: 
                    175: static void
                    176: set_epilogue_insn (type, l)
                    177:      enum epi_type type;
                    178:      int l;
                    179: {
                    180:   epilogue_vec[epilogue_vec_len].type = type;
                    181:   epilogue_vec[epilogue_vec_len].i = l;
                    182:   epilogue_vec_len++;
                    183: }
                    184: 
                    185: /* Delete an insn from the epilogue list. */
                    186: 
                    187: static void
                    188: delete_epilogue_insn (n)
                    189:      int n;
                    190: {
                    191:   int j;
                    192: 
                    193:   for (j = n; j < epilogue_vec_len; j++)
                    194:     epilogue_vec[j] = epilogue_vec[j + 1];
                    195: 
                    196:   epilogue_vec_len--;
                    197: }
                    198: 
                    199: /* Run through the epilogue list and optimize it. */
                    200: 
                    201: static void
                    202: optimize_epilogue_vec ()
                    203: {
                    204:   int i;
                    205: 
                    206:   /* Turn two adds in a row into one add and kill empty adds */
                    207:   for (i = 0; i < epilogue_vec_len - 1; i++)
                    208:     {
                    209:       if (epilogue_vec[i].type == STACK_ADJUST
                    210:          && epilogue_vec[i + 1].type == STACK_ADJUST)
                    211:        {
                    212:          epilogue_vec[i].i += epilogue_vec[i + 1].i;
                    213:          delete_epilogue_insn (i + 1);
                    214:        }
                    215:       if (epilogue_vec[i].type == STACK_ADJUST
                    216:          && epilogue_vec[i].i == 0)
                    217:        delete_epilogue_insn (i);
                    218:     }
                    219: 
                    220:   /* If the instruction after the RTS is a nop, see if it can be
                    221:      changed */
                    222: 
                    223:   for (i = 1; i < epilogue_vec_len - 1; i++)
                    224:     {
                    225:       if (epilogue_vec[i].type == RTS
                    226:          && epilogue_vec[i + 1].type == NOP)
                    227:        {
                    228:          epilogue_vec[i + 1] = epilogue_vec[i - 1];
                    229:          delete_epilogue_insn (i - 1);
                    230:        }
                    231:     }
                    232: 
                    233:   /* Delete all the instructions after the rts's delay slot */
                    234:   for (i = 0; i < epilogue_vec_len; i++)
                    235:     {
                    236:       if (epilogue_vec[i].type == RTS)
                    237:        {
                    238:          int j;
                    239: 
                    240:          for (j = i + 2; j < epilogue_vec_len; j++)
                    241:            epilogue_vec[j].type = DELETED;
                    242:          return;
                    243:        }
                    244:     }
                    245: }
                    246: 
                    247: /* Dump out the insns in epilogue vector. */
                    248: 
                    249: static void
                    250: output_epilogue_vec ()
                    251: {
                    252:   int i;
                    253: 
                    254:   for (i = 0; i < epilogue_vec_len; i++)
                    255:     {
                    256:       switch (epilogue_vec[i].type)
                    257:        {
                    258:        case STACK_ADJUST:
                    259:          fprintf (asm_out_file, "\tadd #%d,r15\n", epilogue_vec[i].i);
                    260:          break;
                    261: 
                    262:        case NOP:
                    263:          fprintf (asm_out_file, "\tor  r0,r0\n");
                    264:          break;
                    265: 
                    266:        case DELAY:
                    267:          final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
                    268:                           asm_out_file, 1, 0, 1);
                    269:          break;
                    270: 
                    271:        case DELETED:
                    272:          fprintf (asm_out_file, "\t!delete_epilogue_insnd\n");
                    273:          break;
                    274: 
                    275:        case RTS:
                    276:          fprintf (asm_out_file, "\trts\n");
                    277:          break;
                    278: 
                    279:        case POP:
                    280:          fprintf (asm_out_file, "\tmov.l       @r15+,r%d\n",
                    281:                   epilogue_vec[i].i);
                    282:          break;
                    283:        }
                    284:     }
                    285:   epilogue_vec_len = 0;
                    286: }
                    287: 
                    288: /* Number of bytes pushed for anonymous args */
                    289: 
                    290: static int extra_push;
                    291: 
                    292: /* Work out the registers which need to be saved, both as a mask and a
                    293:    count */
                    294: 
                    295: int
                    296: calc_live_regs (count)
                    297:      int *count;
                    298: {
                    299:   int reg;
                    300:   int live_regs_mask = 0;
                    301:   *count = 0;
                    302: 
                    303:   for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
                    304:     {
                    305:       if (regs_ever_live[reg] && !call_used_regs[reg])
                    306:        {
                    307:          (*count)++;
                    308:          live_regs_mask |= (1 << reg);
                    309:        }
                    310:     }
                    311:   return live_regs_mask;
                    312: }
                    313: 
                    314: /* Generate a procedure prologue.  */
                    315: 
                    316: void
                    317: output_prologue (f, frame_size)
                    318:      FILE *f;
                    319:      int frame_size;
                    320: {
                    321:   int live_regs_mask;
                    322:   int d;
                    323: 
                    324:   pc = 0;
                    325: 
                    326:   /* This only happens when an arg has been split, part in
                    327:      registers, part in memory.  Allocate the stack space so there is
                    328:      somewhere to put the value */
                    329: 
                    330:   output_stack_adjust (f, -1, current_function_pretend_args_size);
                    331: 
                    332:   live_regs_mask = calc_live_regs (&d);
                    333: 
                    334:   extra_push = 0;
                    335: 
                    336:   if (current_function_anonymous_args)
                    337:     {
                    338:       /* Push arg regs as if they'd been provided by caller in stack */
                    339:       int i;
                    340:       for (i = 0; i < NPARM_REGS; i++)
                    341:        {
                    342:          int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
                    343:          if (i > NPARM_REGS - current_function_args_info)
                    344:            break;
                    345:          fprintf (f, "\tmov.l  r%d,@-r15\n", rn);
                    346:          extra_push += 4;
                    347:          pc += 2;
                    348:        }
                    349:     }
                    350: 
                    351:   if (frame_pointer_needed)
                    352:     {
                    353:       /* Don't need to push the fp with the rest of the registers. */
                    354:       live_regs_mask &= ~(1 << FRAME_POINTER_REGNUM);
                    355:       pc += push_regs (f, live_regs_mask);
                    356:       if (regs_ever_live[PR_REG])
                    357:        {
                    358: 
                    359:          fprintf (f, "\tsts.l  pr,@-r15\n");
                    360:          pc += 2;
                    361:        }
                    362: 
                    363:       fprintf (f, "\tmov.l     r14,@-r15\n");
                    364:       fprintf (f, "\tmov       r15,r14\n");
                    365:       pc += 4;
                    366:       pc += output_stack_adjust (f, -1, frame_size);
                    367:     }
                    368:   else
                    369:     {
                    370:       pc += push_regs (f, live_regs_mask);
                    371: 
                    372:       if (regs_ever_live[PR_REG])
                    373:        {
                    374: 
                    375:          fprintf (f, "\tsts.l  pr,@-r15\n");
                    376:          pc += 2;
                    377:        }
                    378:       pc += output_stack_adjust (f, -1, frame_size);
                    379:     }
                    380: }
                    381: 
                    382: 
                    383: /* Generate a procedure epilogue. */
                    384: 
                    385: void
                    386: output_epilogue (f, frame_size)
                    387:      FILE *f;
                    388:      int frame_size;
                    389: {
                    390:   int live_regs_mask = 0;
                    391:   int d;
                    392:   int i;
                    393:   rtx delay_insn;
                    394:   
                    395:   live_regs_mask = calc_live_regs (&d);
                    396: 
                    397: 
                    398:   /* See if the delay insn is really ok for the slot. */
                    399:   if (current_function_epilogue_delay_list) {
                    400:     delay_insn = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
                    401: 
                    402:   if (GET_CODE (delay_insn) == SET
                    403:       && SET_DEST (delay_insn) == stack_pointer_rtx)
                    404:     {
                    405:       /* Can not use this instruction in the delay slot because
                    406:         it changes the stack pointer, so emit it now.  */
                    407:       final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
                    408:                       asm_out_file, 1, 0, 1);
                    409:       current_function_epilogue_delay_list = 0;
                    410:     }
                    411:   }
                    412:   
                    413: 
                    414:   /* Reclaim the room for the automatics. */
                    415: 
                    416:   output_stack_adjust (f, 1, frame_size);
                    417: 
                    418:   /* Make the frame pointer. */
                    419: 
                    420:   if (frame_pointer_needed)
                    421:     {
                    422:       fprintf (f, "\tmov       r14,r15\n");
                    423:       fprintf (f, "\tmov.l     @r15+,r14\n");
                    424:       live_regs_mask &= ~(1 << FRAME_POINTER_REGNUM);
                    425:     }
                    426: 
                    427:   /* Get the PR register if it was clobbered in the function. */
                    428: 
                    429:   if (regs_ever_live[PR_REG])
                    430:     fprintf (f, "\tlds.l       @r15+,pr\n");
                    431: 
                    432:   /* Pop all the registers */
                    433:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                    434:     {
                    435:       int j = (FIRST_PSEUDO_REGISTER - 1) - i;
                    436:       if (live_regs_mask & (1 << j))
                    437:        {
                    438:          set_epilogue_insn (POP, j);
                    439:        }
                    440:     }
                    441: 
                    442:   /* Need to adjust the stack by some amount of bytes since we've pushed
                    443:      some of the args which normally come in registers */
                    444: 
                    445:   set_epilogue_insn (STACK_ADJUST, extra_push);
                    446: 
                    447:   /* Need to adjust the stack by some amount of bytes if there
                    448:      an arg has been split part register and part stack */
                    449: 
                    450:   set_epilogue_insn (STACK_ADJUST, current_function_pretend_args_size);
                    451: 
                    452:   set_epilogue_insn (RTS, 0);
                    453: 
                    454:   /* Got here without dumping a register pop into the delay slot */
                    455:   if (current_function_epilogue_delay_list)
                    456:     {
                    457:       set_epilogue_insn (DELAY, 0);
                    458:     }
                    459:   set_epilogue_insn (NOP, 0);
                    460: 
                    461:   optimize_epilogue_vec ();
                    462: 
                    463:   output_epilogue_vec ();
                    464: 
                    465:   dump_constants (0);
                    466:   current_function_anonymous_args = 0;
                    467: }
                    468: 
                    469: /* Print the operand address in x to the stream */
                    470: 
                    471: void
                    472: print_operand_address (stream, x)
                    473:      FILE *stream;
                    474:      rtx x;
                    475: {
                    476:   switch (GET_CODE (x))
                    477:     {
                    478:     case REG:
                    479:       fprintf (stream, "@%s", reg_names[REGNO (x)]);
                    480:       break;
                    481: 
                    482:     case PLUS:
                    483:       {
                    484:        rtx base = XEXP (x, 0);
                    485:        rtx index = XEXP (x, 1);
                    486: 
                    487:        if (GET_CODE (base) != REG)
                    488:          {
                    489:            /* Ensure that BASE is a register (one of them must be). */
                    490:            rtx temp = base;
                    491:            base = index;
                    492:            index = temp;
                    493:          }
                    494: 
                    495:        switch (GET_CODE (index))
                    496:          {
                    497:          case CONST_INT:
                    498:            fprintf (stream, "@(%d,%s)",
                    499:                     INTVAL (index),
                    500:                     reg_names[REGNO (base)]);
                    501:            break;
                    502: 
                    503:          case REG:
                    504:            fprintf (stream, "@(%s,%s)",
                    505:                     reg_names[REGNO (base)],
                    506:                     reg_names[REGNO (index)]);
                    507:            break;
                    508: 
                    509:          default:
                    510:            abort ();
                    511:          }
                    512:       }
                    513: 
                    514:       break;
                    515:     case PRE_DEC:
                    516:       fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
                    517:       break;
                    518: 
                    519:     case POST_INC:
                    520:       fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
                    521:       break;
                    522: 
                    523:     default:
                    524:       output_addr_const (stream, x);
                    525:       break;
                    526:     }
                    527: }
                    528: 
                    529: /* Print operand x (an rtx) in assembler syntax to file stream
                    530:    according to modifier code.
                    531: 
                    532:  '*'  print a local label
                    533:  '^'  increment the local label number
                    534:  '!'  dump the constant table
                    535:  '#'  output a nop if there is nothing to put in the delay slot
                    536:  'R'  print the next register or memory location along, ie the lsw in
                    537:       a double word value
                    538:  'I'  put something into the constant pool and print its label */
                    539: 
                    540: void
                    541: print_operand (stream, x, code)
                    542:      FILE *stream;
                    543:      rtx x;
                    544:      int code;
                    545: {
                    546:   switch (code)
                    547:     {
                    548:     case '*':
                    549:       fprintf (stream, "LF%d", lf);
                    550:       break;
                    551:     case '!':
                    552:       dump_constants (0);
                    553:       break;
                    554:     case '^':
                    555:       lf++;
                    556:       break;
                    557: 
                    558:     case '#':
                    559:       /* Output a nop if there's nothing in the delay slot */
                    560:       if (dbr_sequence_length () == 0)
                    561:        {
                    562:          fprintf (stream, "\n\tor      r0,r0\t!wasted slot");
                    563:        }
                    564:       break;
                    565: 
                    566:     case 'I':
                    567:       fprintf (asm_out_file, "LK%d", add_constant (x, SImode));
                    568:       break;
                    569: 
                    570:     case 'R':
                    571:       /* Next location along in memory or register*/
                    572:       switch (GET_CODE (x))
                    573:        {
                    574:        case REG:
                    575:          fputs (reg_names[REGNO (x) + 1], (stream));
                    576:          break;
                    577:        case MEM:
                    578:          print_operand_address (stream,
                    579:                               XEXP (adj_offsettable_operand (x, 4), 0), 0);
                    580:          break;
                    581:        }
                    582:       break;
                    583: 
                    584:     default:
                    585:       switch (GET_CODE (x))
                    586:        {
                    587:        case REG:
                    588:          fputs (reg_names[REGNO (x)], (stream));
                    589:          break;
                    590:        case MEM:
                    591:          output_address (XEXP (x, 0));
                    592:          break;
                    593:        default:
                    594:          fputc ('#', stream);
                    595:          output_addr_const (stream, x);
                    596:          break;
                    597: 
                    598:        }
                    599:       break;
                    600:     }
                    601: }
                    602: 
                    603: 
                    604: 
                    605: /* Define the offset between two registers, one to be eliminated, and 
                    606:    the other its replacement, at the start of a routine.  */
                    607: 
                    608: int
                    609: initial_elimination_offset (from, to)
                    610: {
                    611:   int regs_saved;
                    612:   int d = calc_live_regs (&regs_saved);
                    613:   int total_saved_regs_space = (regs_saved + regs_ever_live[PR_REG]) * 4;
                    614:   int total_auto_space = get_frame_size ();
                    615: 
                    616: 
                    617:   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
                    618:     {
                    619:       return total_saved_regs_space;
                    620:     }
                    621: 
                    622:   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
                    623:     {
                    624:       return total_saved_regs_space + total_auto_space;
                    625:     }
                    626: 
                    627:   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
                    628:     {
                    629:       return total_auto_space;
                    630:     }
                    631: }
                    632: 
                    633: delay_slots_for_epilogue ()
                    634: {
                    635:   /* We need to find something to fill the epilogue if there won't be
                    636:      any instructions to make the stack or pop registers which can be
                    637:      moved into the slot */
                    638: 
                    639:   int d;
                    640:   calc_live_regs (&d);
                    641:   return !(get_frame_size () + d);
                    642: }
                    643: 
                    644: 
                    645: /* Prepare operands for a move define_expand; specifically, one of the
                    646:    operands must be in a register */
                    647: 
                    648: void
                    649: prepare_move_operands (operands, mode)
                    650:      rtx operands[];
                    651:      enum machine_mode mode;
                    652: {
                    653:   /* One of the operands has to be a register */
                    654:   if ((!register_operand (operands[0], mode)
                    655:        && !register_operand (operands[1], mode))
                    656:       || GET_CODE(operands[1]) == PLUS)
                    657:     {
                    658:       /* copy the source to a register */
                    659:       operands[1] = copy_to_mode_reg (mode, operands[1]);
                    660:     }
                    661: }
                    662: 
                    663: 
                    664: /* Prepare the operands for an scc instruction; make sure that the
                    665:    compare has been done.  */
                    666: rtx
                    667: prepare_scc_operands (code)
                    668: {
                    669:   if (GET_CODE(sh_compare_op0) != REG 
                    670:       || REGNO(sh_compare_op0) != T_REG)
                    671:     {
                    672:       /* First need a compare insn */
                    673:       emit_insn (gen_rtx (SET, SImode, 
                    674:                          gen_rtx (REG, SImode, T_REG),
                    675:                          gen_rtx (code, SImode, sh_compare_op0,
                    676:                                   sh_compare_op1)));
                    677:     }
                    678:   return gen_rtx(REG, SImode, T_REG);
                    679: }
                    680: 
                    681: /* Functions to output assembly */
                    682: 
                    683: /* Return a sequence of instructions to perform DI move, taking into
                    684:    account overlapping source and dest registers */
                    685: 
                    686: char *
                    687: output_movedouble (operands, mode)
                    688:      rtx operands[];
                    689:      enum machine_mode mode;
                    690: {
                    691:   if (register_operand (operands[0], mode)
                    692:       && register_operand (operands[1], mode))
                    693:     {
                    694:       if (REGNO (operands[1]) == MACH_REG)
                    695:        return "sts     mach,%0\n\tsts  macl,%R0";
                    696:       if (REGNO (operands[1]) > REGNO (operands[0])) 
                    697:        {
                    698:          return "mov   %1,%0\n\tmov    %R1,%R0";
                    699:        }
                    700:       else 
                    701:        {
                    702:          return "mov   %R1,%R0\n\tmov  %1,%0";
                    703:        }
                    704:     }
                    705: 
                    706:   if (GET_CODE (operands[1]) == CONST_INT)
                    707:     {
                    708:       if (INTVAL (operands[1]) < 0)
                    709:        return "mov     #-1,%0\n\tmov   %1,%R0";
                    710:       else
                    711:        return "mov     #0,%0\n\tmov    %1,%R0";
                    712:     }
                    713: 
                    714:   if (GET_CODE (operands[1]) == MEM)
                    715:     {
                    716:       int idxreg = -1;
                    717:       rtx inside = XEXP (operands[1], 0);
                    718: 
                    719:       if (GET_CODE (inside) == REG)
                    720:        idxreg = REGNO (inside);
                    721:       else if (GET_CODE (inside) == PLUS)
                    722:        {
                    723:          rtx lhs = XEXP (inside, 0);
                    724:          rtx rhs = XEXP (inside, 1);
                    725:          if (GET_CODE (lhs) == REG)
                    726:            idxreg = REGNO (lhs);
                    727:          else if (GET_CODE (rhs) == REG)
                    728:            idxreg = REGNO (rhs);
                    729:          else
                    730:            abort ();
                    731:        }
                    732:       else
                    733:        abort ();
                    734: 
                    735:       if (REGNO (operands[0]) != idxreg)
                    736:        {
                    737:          /* The dest register is mentioned in the addressing mode,
                    738:             so print them the other way around */
                    739:          return "mov.l %1,%0\n\tmov.l  %R1,%R0 ! one way";
                    740:        }
                    741:       return "mov.l    %R1,%R0\n\tmov.l        %1,%0 ! other way";
                    742:     }
                    743: 
                    744:   return "mov.l        %R1,%R0\n\tmov.l        %1,%0";
                    745: }
                    746: 
                    747: /* Emit assembly to shift reg by k bits */
                    748: 
                    749: char *
                    750: output_shift (string, reg, k)
                    751:      char *string;
                    752:      rtx reg;
                    753:      rtx k;
                    754: {
                    755:   int s = INTVAL (k);
                    756:   while (s)
                    757:     {
                    758:       char *out;
                    759:       int d;
                    760: 
                    761:       if (s >= 16)
                    762:        {
                    763:          d = 16;
                    764:          out = "16";
                    765:        }
                    766:       else if (s >= 8)
                    767:        {
                    768:          d = 8;
                    769:          out = "8";
                    770:        }
                    771:       else if (s >= 2)
                    772:        {
                    773:          d = 2;
                    774:          out = "2";
                    775:        }
                    776:       else
                    777:        {
                    778:          d = 1;
                    779:          out = "";
                    780:        }
                    781:       fprintf (asm_out_file, "\t%s%s\tr%d\n", string, out, REGNO (reg));
                    782:       s -= d;
                    783:     }
                    784:   return "";
                    785: }
                    786: 
                    787: /* Return the text of the branch instruction which matches its length
                    788:    attribute.  */
                    789: 
                    790: char *
                    791: output_branch (logic, insn)
                    792:      int logic;
                    793:      rtx *insn;
                    794: {
                    795:   extern rtx recog_operand[];
                    796:   int label = lf++;
                    797:   
                    798:   switch (get_attr_length (insn))
                    799:     {
                    800:     case 2:
                    801:       /* Simple branch in range -200..+200 bytes */
                    802:       return logic ? "bt       %l0" : "bf      %l0";
                    803: 
                    804:     case 6:
                    805:       /* Branch in range -4000..+4000 bytes */
                    806:       fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
                    807:       output_asm_insn ("bra    %l0     ! 12 bit cond ", recog_operand);
                    808:       fprintf (asm_out_file, "\tor     r0,r0\n");
                    809:       label = dump_constants (label);
                    810:       fprintf (asm_out_file, "LF%d:\n", label);
                    811:       return "";
                    812: 
                    813:     case 8:
                    814:       /* Branches a long way away */
                    815:        
                    816:       fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
                    817:       output_asm_insn ("mov.l  %I0,r13", recog_operand);
                    818:       fprintf (asm_out_file, "\tjmp    @r13    ! 32 cond \n");
                    819:       fprintf (asm_out_file, "\tor     r0,r0\n");
                    820:       fprintf (asm_out_file, "LF%d:\n", label);
                    821:       return "";
                    822:     }
                    823:   return "bad";
                    824: 
                    825: }
                    826: 
                    827: /* Predicates used by the templates */
                    828: 
                    829: /* Nonzero if OP is a normal arithmetic register. */
                    830: 
                    831: int
                    832: arith_reg_operand(op, mode)
                    833:      rtx op;
                    834:      enum machine_mode mode;
                    835: {
                    836:   if (register_operand (op, mode))
                    837:     {
                    838:       if (GET_CODE (op) == REG)
                    839:        return REGNO (op) != T_REG;
                    840:       return 1;
                    841:     }
                    842:   return 0;
                    843: }
                    844: 
                    845:   
                    846: /* Nonzero if OP is a valid source operand for an arithmetic insn.  */
                    847: 
                    848: int
                    849: arith_operand (op, mode)
                    850:      rtx op;
                    851:      enum machine_mode mode;
                    852: {
                    853:   if (register_operand (op, mode))
                    854:     return 1;
                    855: 
                    856:   if (GET_CODE (op) == CONST_INT)
                    857:     {
                    858:       if (CONST_OK_FOR_I (INTVAL (op)))
                    859:        return 1;
                    860:     }
                    861:   return 0;
                    862: }
                    863: 
                    864: 
                    865: /* Nonzero if OP is a valid source operand for a logical operation */
                    866: 
                    867: int
                    868: logical_operand (op, mode)
                    869:      rtx op;
                    870:      enum machine_mode mode;
                    871: {
                    872:   if (register_operand (op, mode))
                    873:     return 1;
                    874: 
                    875:   if (GET_CODE (op) == CONST_INT)
                    876:     {
                    877:       if (CONST_OK_FOR_L (INTVAL (op)))
                    878:        return 1;
                    879:     }
                    880:   return 0;
                    881: }
                    882: 
                    883: /* Nonzero if p is a valid shift operand for lshr and ashl */
                    884: 
                    885: int
                    886: ok_shift_value (p)
                    887:      rtx p;
                    888: {
                    889:   if (GET_CODE (p) == CONST_INT)
                    890:     {
                    891:       switch (INTVAL (p))
                    892:        {
                    893:        case 1:
                    894:        case 2:
                    895:        case 8:
                    896:        case 16:
                    897:          return 1;
                    898:        default:
                    899:          if (TARGET_FASTCODE)
                    900:            return INTVAL(p) >= 0;
                    901:        }
                    902:     }
                    903:   return 0;
                    904: }
                    905: 
                    906: /* Nonzero if the arg is an immediate which has to be loaded from
                    907:    memory */
                    908: 
                    909: int
                    910: hard_immediate_operand (op, mode)
                    911:      rtx op;
                    912:      enum machine_mode mode;
                    913: {
                    914:   if (immediate_operand (op, mode))
                    915:     {
                    916:       if (GET_CODE (op) == CONST_INT
                    917:          && INTVAL (op) >= -128 && INTVAL (op) < 127)
                    918:        return 0;
                    919:       return 1;
                    920:     }
                    921:   return 0;
                    922: }
                    923: 
                    924: /* The SH cannot load a large constant into a register, constants have to
                    925:    come from a pc relative load.  The reference of a pc relative load
                    926:    instruction must be less than 1k infront of the instruction.  This
                    927:    means that we often have to dump a constant inside a function, and
                    928:    generate code to branch around it.
                    929: 
                    930:    It is important to minimize this, since the branches will slow things
                    931:    down and make things bigger.
                    932: 
                    933:   Worst case code looks like:
                    934: 
                    935:       mov.l L1,rn
                    936:       bra   L2
                    937:       nop
                    938:       align
                    939: L1:   .long value
                    940: L2:
                    941:       ..
                    942: 
                    943:       mov.l L3,rn
                    944:       bra   L4
                    945:       nop
                    946:       align
                    947: L3:   .long value
                    948: L4:
                    949:       ..
                    950: 
                    951:    During shorten_branches we notice the instructions which can have a
                    952:    constant table in them, if we see two that are close enough
                    953:    together, we move the constants from the first table to the second
                    954:    table and continue.  This process can happen again and again, and
                    955:    in the best case, moves the constant table outside of the function.
                    956: 
                    957:    In the above example, we can tell that L3 is within 1k of L1, so
                    958:    the first move can be shrunk from the 3 insn+constant sequence into
                    959:    just 1 insn, and the constant moved to L3 to make:
                    960: 
                    961:    mov.l       L1,rn
                    962:    ..
                    963:    mov.l       L3,rn
                    964:    bra         L4
                    965:    nop
                    966:    align
                    967: L3:.long value
                    968: L4:.long value
                    969: 
                    970:    Then the second move becomes the target for the shortening process.
                    971: 
                    972:    We keep a simple list of all the constants accumulated in the
                    973:    current pool so there are no duplicates in a single table, but
                    974:    they are not factored into the size estimates.
                    975: 
                    976: */
                    977: 
                    978: typedef struct
                    979: {
                    980:   rtx value;
                    981:   int number;
                    982:   enum machine_mode mode;
                    983: } pool_node;
                    984: 
                    985: /* The maximum number of constants that can fit into one pool, since
                    986:    the pc relative range is 0...1020 bytes and constants are at least 4
                    987:    bytes long */
                    988: 
                    989: #define MAX_POOL_SIZE (1020/4)
                    990: static pool_node pool_vector[MAX_POOL_SIZE];
                    991: static int pool_size;
                    992: 
                    993: 
                    994: /* Add a constant to the pool and return its label number.  */
                    995: 
                    996: static int
                    997: add_constant (x, mode)
                    998:      rtx x;
                    999:      enum machine_mode mode;
                   1000: {
                   1001:   int i;
                   1002: 
                   1003:   /* Start the countdown on the first constant */
                   1004: 
                   1005:   if (!pool_size)
                   1006:     {
                   1007:       first_pc = pc;
                   1008:     }
                   1009: 
                   1010:   /* First see if we've already got it */
                   1011: 
                   1012:   for (i = 0; i < pool_size; i++)
                   1013:     {
                   1014: 
                   1015:       if (x->code == pool_vector[i].value->code
                   1016:          && mode == pool_vector[i].mode)
                   1017:        {
                   1018:          if (x->code == CODE_LABEL)
                   1019:            {
                   1020:              if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
                   1021:                continue;
                   1022:            }
                   1023:        }
                   1024: 
                   1025:       if (rtx_equal_p (x, pool_vector[i].value))
                   1026:        return pool_vector[i].number;
                   1027:     }
                   1028:   
                   1029: 
                   1030:   pool_vector[pool_size].value = x;
                   1031:   pool_vector[pool_size].mode = mode;
                   1032:   pool_vector[pool_size].number = lf;
                   1033:   pool_size++;
                   1034: 
                   1035:   return lf++;
                   1036: }
                   1037: 
                   1038: /* Nonzero if the insn could take a constant table.  */
                   1039: 
                   1040: static int
                   1041: has_constant_table (insn)
                   1042:      rtx insn;
                   1043: {
                   1044:   rtx body;
                   1045: 
                   1046:   if (GET_CODE (insn) == NOTE
                   1047:       || GET_CODE (insn) == BARRIER
                   1048:       || GET_CODE (insn) == CODE_LABEL)
                   1049:     return 0;
                   1050: 
                   1051:   body = PATTERN (insn);
                   1052:   if (GET_CODE (body) == SEQUENCE)
                   1053:     return 0;
                   1054:   if (GET_CODE (body) == ADDR_VEC)
                   1055:     return 0;
                   1056:   if (GET_CODE (body) == USE)
                   1057:     return 0;
                   1058:   if (GET_CODE (body) == CLOBBER)
                   1059:     return 0;
                   1060:   if (get_attr_constneed (insn) == CONSTNEED_YES)
                   1061:     return 1;
                   1062: 
                   1063:   if (GET_CODE (body) == UNSPEC_VOLATILE)
                   1064:     {
                   1065:       return INTVAL (XVECEXP (body, 0, 0)) == 1;
                   1066:     }
                   1067:   return 0;
                   1068: }
                   1069: 
                   1070: /*  Adjust the length of an instruction.
                   1071: 
                   1072:     We'll look at the previous instruction which holds a constant
                   1073:     table and see if we can move the table to here instead. */
                   1074: 
                   1075: int target_insn_uid;
                   1076: int target_insn_smallest_size;
                   1077: 
                   1078: int target_pc;
                   1079: int target_insn_range;
                   1080: int current_pc;
                   1081: int table_size;
                   1082: 
                   1083: void
                   1084: adjust_insn_length (insn, insn_lengths)
                   1085:      rtx insn;
                   1086:      short *insn_lengths;
                   1087: {
                   1088:   int uid = INSN_UID (insn);
                   1089: 
                   1090:   current_pc += insn_lengths[uid];
                   1091: 
                   1092:   if (has_constant_table (insn)) 
                   1093:     {
                   1094:       if (current_pc >= target_insn_range)
                   1095:        {
                   1096:          /* This instruction is further away from the referencing
                   1097:             instruction than it can reach, so we'll stop accumulating
                   1098:             from that one and start fresh. */
                   1099:          target_pc = current_pc;
                   1100:          target_insn_range = current_pc + MAYBE_DUMP_LEVEL;
                   1101:        }
                   1102:       else
                   1103:        {
                   1104:          /* This instruction is within the reach of the target,
                   1105:             remove the constant table from the target by adjusting
                   1106:             downwards, and increase the size of this one to
                   1107:             compensate.  */
                   1108: 
                   1109: 
                   1110:          /* Add the stuff from this insn to what will go in the
                   1111:             growing table. */
                   1112: 
                   1113:          table_size += get_attr_constantsize (insn);
                   1114: 
                   1115:          /* The target shinks to its smallest natural size */
                   1116:          insn_lengths[target_insn_uid] = target_insn_smallest_size;
                   1117: 
                   1118:          /* The current insn grows to be its larger size plust the
                   1119:             table size. */
                   1120: 
                   1121:          insn_lengths[uid] = get_attr_largestsize (insn) + table_size;
                   1122: 
                   1123:        }
                   1124:       /* Current insn becomes the target.  */
                   1125:       target_insn_uid = uid;
                   1126:       target_insn_smallest_size = get_attr_smallestsize (insn);
                   1127: 
                   1128:     }
                   1129: 
                   1130: }
                   1131: 
                   1132: 
                   1133: /* Dump out the pending constant pool. 
                   1134:    If label provided then insert an branch in the middle of the table 
                   1135:   */
                   1136: 
                   1137: static int
                   1138: dump_constants (label)
                   1139: {
                   1140:   int i;
                   1141:   int rlabel = label;
                   1142:   int size = 0;
                   1143:   
                   1144:   for (i = 0; i < pool_size; i++)
                   1145:     {
                   1146:       pool_node *p = pool_vector + i;
                   1147:       fprintf (asm_out_file, "\n\t! constants - waited %d\n", pc - first_pc);
                   1148:       fprintf (asm_out_file, "\t.align\t2\n");
                   1149:       fprintf (asm_out_file, "LK%d:", p->number);
                   1150:       size += GET_MODE_SIZE (p->mode);
                   1151:       
                   1152:       switch (GET_MODE_CLASS (p->mode))
                   1153:        {
                   1154:        case MODE_INT:
                   1155:        case MODE_PARTIAL_INT:
                   1156:          assemble_integer (p->value, GET_MODE_SIZE (p->mode), 1);
                   1157:          break;
                   1158:        case MODE_FLOAT:
                   1159:          {
                   1160:            union real_extract u;
                   1161:            bcopy (&CONST_DOUBLE_LOW (p->value), &u, sizeof u);
                   1162:            assemble_real (u.d, p->mode);
                   1163:          }
                   1164:        }
                   1165:       
                   1166:       /* After 200 bytes of table, stick in another branch */
                   1167:       if (label && size > 200) 
                   1168:        {
                   1169:          rlabel = lf ++;
                   1170:          fprintf (asm_out_file,"LF%d:\tbra     LF%d\n", label, rlabel);
                   1171:          fprintf (asm_out_file,"\tor   r0,r0\n");
                   1172:          label = 0;
                   1173:        }
                   1174:       
                   1175:       fprintf (asm_out_file, "\n");
                   1176:     }
                   1177:   pool_size = 0;
                   1178:   current_pc = 0;
                   1179:   target_insn_range = 0;
                   1180:   return rlabel;
                   1181:   
                   1182: }
                   1183: 
                   1184: 
                   1185: /* Emit the text to load a value from a constant table.  */
                   1186: 
                   1187: char *
                   1188: output_movepcrel (insn, operands, mode)
                   1189:      rtx insn;
                   1190:      rtx operands[];
                   1191:      enum machine_mode mode;
                   1192: {
                   1193:   int len = GET_MODE_SIZE (mode);
                   1194:   int rn = REGNO (operands[0]);
                   1195: 
                   1196:   fprintf (asm_out_file, "\tmov.l      LK%d,r%d\n",
                   1197:           add_constant (operands[1], mode), rn);
                   1198: 
                   1199:   if (GET_MODE_SIZE(mode) > 4) 
                   1200:     {
                   1201:       fprintf (asm_out_file,
                   1202:               "\tmov.l LK%d+4,r%d\n",
                   1203:               add_constant (operands[1], mode),
                   1204:               rn + 1);
                   1205: 
                   1206:     } 
                   1207:   /* If this instruction is as small as it can be, there can be no 
                   1208:      constant table attached to it.  */
                   1209:   if (get_attr_length (insn) !=  get_attr_smallestsize (insn))
                   1210:     {
                   1211:       /* This needs a constant table */
                   1212:       fprintf (asm_out_file, "\t!constant table start\n");
                   1213:       fprintf (asm_out_file, "\tbra    LF%d\n", lf);
                   1214:       fprintf (asm_out_file, "\tor     r0,r0 ! wasted slot\n");
                   1215:       dump_constants (0);
                   1216:       fprintf (asm_out_file, "LF%d:\n", lf++);
                   1217:       fprintf (asm_out_file, "\t!constant table end\n");
                   1218:     }
                   1219:   return "";
                   1220: }
                   1221: 
                   1222: 
                   1223: /* Dump out interesting debug info */
                   1224: 
                   1225: void
                   1226: final_prescan_insn (insn, opvec, noperands)
                   1227:      rtx insn;
                   1228:      rtx *opvec;
                   1229:      int noperands;
                   1230: {
                   1231:   register rtx body = PATTERN (insn);
                   1232: 
                   1233:   if (target_flags & ISIZE_BIT)
                   1234:     {
                   1235:       extern int *insn_addresses;
                   1236: 
                   1237:       fprintf (asm_out_file, "\n!%04x*\n",
                   1238:               insn_addresses[INSN_UID (insn)] + 0x10);
                   1239: 
                   1240:       fprintf (asm_out_file, "\n!%04x %d %04x len=%d\n",
                   1241:               pc, pool_size, first_pc, get_attr_length (insn));
                   1242: 
                   1243:       if (TARGET_DUMP_RTL)
                   1244:        print_rtl (asm_out_file, body);
                   1245: 
                   1246: 
                   1247:     }
                   1248:   
                   1249:   pc += get_attr_length (insn);
                   1250: 
                   1251:   if (pool_size && pc - first_pc > MUST_DUMP_LEVEL)
                   1252:     {
                   1253:       /* For some reason we have not dumped out a constant table, and 
                   1254:       we have emitted a lot of code.  This can happen if the think
                   1255:       which wants the table is a long conditional branch (which has no
                   1256:       room for a constant table), and there has not been a move
                   1257:       constant anywhere. */
                   1258:       int label = lf++;
                   1259:       fprintf (asm_out_file, "\t!forced constant table\n");      
                   1260:       fprintf (asm_out_file, "\tbra    LF%d\n", label);
                   1261:       fprintf (asm_out_file, "\tor     r0,r0 ! wasted slot\n");
                   1262:       label = dump_constants (label);
                   1263:       fprintf (asm_out_file, "LF%d:\n", label);
                   1264:       fprintf (asm_out_file, "\t!constant table end\n");
                   1265:     }
                   1266:   
                   1267: }
                   1268: 
                   1269: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.