Annotation of GNUtools/cc/config/h8300/h8300.c, revision 1.1.1.1

1.1       root        1: /* Subroutines for insn-output.c for Hitachi H8/300.
                      2:    Copyright (C) 1992,1993 Free Software Foundation, Inc.
                      3: 
                      4:    Contributed by Steve Chamberlain ([email protected]) and
                      5:    Jim Wilson ([email protected]).
                      6: 
                      7: This file is part of GNU CC.
                      8: 
                      9: GNU CC is free software; you can redistribute it and/or modify
                     10: it under the terms of the GNU General Public License as published by
                     11: the Free Software Foundation; either version 2, or (at your option)
                     12: any later version.
                     13: 
                     14: GNU CC is distributed in the hope that it will be useful,
                     15: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: GNU General Public License for more details.
                     18: 
                     19: You should have received a copy of the GNU General Public License
                     20: along with GNU CC; see the file COPYING.  If not, write to
                     21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     22: 
                     23: #include <stdio.h>
                     24: #include "config.h"
                     25: #include "rtl.h"
                     26: #include "regs.h"
                     27: #include "hard-reg-set.h"
                     28: #include "real.h"
                     29: #include "insn-config.h"
                     30: #include "conditions.h"
                     31: #include "insn-flags.h"
                     32: #include "output.h"
                     33: #include "insn-attr.h"
                     34: #include "flags.h"
                     35: #include "recog.h"
                     36: #include "expr.h"
                     37: #include "tree.h"
                     38: 
                     39: /* Forward declarations.  */
                     40: void print_operand_address ();
                     41: char *index ();
                     42: 
                     43: /* True if a #pragma interrupt has been seen for the current function.  */
                     44: int pragma_interrupt;
                     45: 
                     46: /* True if a #pragma saveall has been seen for the current function.  */
                     47: int pragma_saveall;
                     48: 
                     49: char *names_big[] 
                     50:  = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"};
                     51: 
                     52: char *
                     53: byte_reg (x, b)
                     54:      rtx x;
                     55:      int b;
                     56: {
                     57:   static char *names_small[] 
                     58:     =  {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
                     59:        "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7lBAD", "r7hBAD"};
                     60: 
                     61:   return names_small[REGNO (x) * 2 + b];
                     62: }
                     63: 
                     64: /* REGNO must be saved/restored across calls if this macro is true.  */
                     65: static int 
                     66: word_reg_used (regno)
                     67: int regno;
                     68: {
                     69:   if (regno < 7  
                     70:       && (pragma_interrupt || pragma_saveall 
                     71:          || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])
                     72:          || (regs_ever_live[regno] & ! call_used_regs[regno])))
                     73:     return 1;
                     74:   return 0;
                     75: }
                     76: 
                     77: /* Output assembly language to FILE for the operation OP with operand size
                     78:    SIZE.  */
                     79: static void
                     80: dosize (file, op, size, fped)
                     81:      FILE *file;
                     82:      char *op;
                     83:      unsigned int size;
                     84:      int fped;
                     85: {
                     86:   switch (size)
                     87:     {
                     88:     case 4:
                     89:     case 3:
                     90:       fprintf (file, "\t%ss\t#%d,sp\n", op, 2);
                     91:       size -= 2;
                     92:       /* Fall through...  */
                     93:     case 2:
                     94:     case 1:
                     95:       fprintf (file, "\t%ss\t#%d,sp\n", op, size);
                     96:       size = 0;
                     97:       break;
                     98:     case 0:
                     99:       break;
                    100:     default:
                    101:       fprintf (file, "\tmov.w\t#%d,r5\n\t%s.w\tr5,sp\n", size, op);
                    102:       size = 0;
                    103:       break;
                    104:     }
                    105: }
                    106: 
                    107: /* Output assembly language code for the function prologue.  */
                    108: static int push_order[FIRST_PSEUDO_REGISTER] 
                    109:   = {6, 5, 4, 3, 2, 1, 0, -1, -1};
                    110: static int pop_order[FIRST_PSEUDO_REGISTER] 
                    111:   = {0, 1, 2, 3, 4, 5, 6, -1, -1};
                    112: 
                    113: /* This is what the stack looks like after the prolog of 
                    114:    a function with a frame has been set up:
                    115: 
                    116:        <pushed args>
                    117:        return pc
                    118:    fp->        old fp
                    119:        <locals>
                    120:        <saved register-0> 
                    121:        <saved register-1> 
                    122:    sp->        <saved register-n>
                    123: 
                    124: 
                    125:    This is what the stack looks like after the prolog of
                    126:    a function which doesn't have a frame:
                    127: 
                    128:        <pushed args>
                    129:        return pc
                    130:        <locals>
                    131:        <saved register-0>
                    132:    sp-> <saved register-n>
                    133: */
                    134: 
                    135: void
                    136: function_prologue (file, size)
                    137:      FILE *file;
                    138:      int size;
                    139: {
                    140:   register int mask = 0;
                    141:   int fsize = (size + 1) & -2;
                    142:   int idx;
                    143: 
                    144:   if (frame_pointer_needed)
                    145:     {
                    146:       /* Push the fp.  */
                    147:       fprintf (file, "\tpush\t%s\n", names_big[FRAME_POINTER_REGNUM]);
                    148:       fprintf (file, "\tmov.w\tr7,r6\n");
                    149: 
                    150:       /* Leave room for the locals.  */
                    151:       dosize (file, "sub", fsize, 1);
                    152: 
                    153:       /* Push the rest of the registers.  */
                    154:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++) 
                    155:        {
                    156:          int regno = push_order[idx];
                    157: 
                    158:          if (regno >= 0 && word_reg_used (regno)
                    159:              && regno != FRAME_POINTER_REGNUM)
                    160:            fprintf (file, "\tpush\t%s\n", names_big[regno]);
                    161:        }
                    162:     }
                    163:   else
                    164:     {
                    165:       dosize (file, "sub", fsize, 0);
                    166:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    167:        {
                    168:          int regno = push_order[idx];
                    169: 
                    170:          if (regno >= 0 && word_reg_used (regno))
                    171:            fprintf (file, "\tpush\t%s\n", names_big[regno]);
                    172:        }
                    173:     }
                    174: }
                    175: 
                    176: /* Output assembly language code for the function epilogue.  */
                    177: 
                    178: void
                    179: function_epilogue (file, size)
                    180:      FILE *file;
                    181:      int size;
                    182: {
                    183:   register int regno;
                    184:   register int mask = 0;
                    185:   int fsize = (size + 1) & -2;
                    186:   int nregs;
                    187:   int offset;
                    188:   int idx;
                    189:   rtx insn = get_last_insn ();
                    190: 
                    191:   /* If the last insn was a BARRIER, we don't have to write any code.  */
                    192:   if (GET_CODE (insn) == NOTE)
                    193:     insn = prev_nonnote_insn (insn);
                    194:   if (insn && GET_CODE (insn) == BARRIER)
                    195:     return;
                    196: 
                    197:   nregs = 0;
                    198: 
                    199:   if (frame_pointer_needed)
                    200:     {
                    201:       /* Pop saved registers.  */
                    202:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    203:        {
                    204:          regno = pop_order[idx];
                    205:          if (regno >= 0 && regno != FRAME_POINTER_REGNUM
                    206:              && word_reg_used (regno))
                    207:            fprintf (file, "\tpop\t%s\n", names_big[regno]);
                    208:        }
                    209:       /* Deallocate locals.  */
                    210:       dosize (file, "add", fsize, 1);
                    211:       /* Pop frame pointer.  */
                    212:       fprintf (file, "\tpop\t%s\n", names_big[FRAME_POINTER_REGNUM]);
                    213:     }
                    214:   else
                    215:     {
                    216:       /* Deallocate locals and pop saved registers.  */
                    217:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    218:        {
                    219:          regno = pop_order[idx];
                    220:          if (regno >= 0 && word_reg_used (regno))
                    221:            fprintf (file, "\tpop\t%s\n", names_big[regno]);
                    222:        }
                    223:       dosize (file, "add", fsize, 0);
                    224:     }
                    225:   if (pragma_interrupt)
                    226:     fprintf (file, "\trte\n");
                    227:   else
                    228:     fprintf (file, "\trts\n");
                    229: 
                    230:   pragma_interrupt = 0;
                    231:   pragma_saveall = 0;
                    232: }
                    233: 
                    234: /* Return true if VALUE is a valid constant for constraint 'P'.  */
                    235: 
                    236: int
                    237: potl8 (value)
                    238: {
                    239:   switch (value)
                    240:     {
                    241:     case 1:
                    242:     case 2:
                    243:     case 4:
                    244:     case 8:
                    245:     case 16:
                    246:     case 32:
                    247:     case 64:
                    248:     case 128:
                    249:       return 1;
                    250:     }
                    251:   return 0;
                    252: }
                    253: 
                    254: /* Return true if VALUE is a valid constant for constraint 'O'.  */
                    255: int
                    256: potg8 (value)
                    257:      int value;
                    258: {
                    259:   switch (value)
                    260:     {
                    261:     case 256:
                    262:     case 512:
                    263:     case 1024:
                    264:     case 2048:
                    265:     case 4096:
                    266:     case 8192:
                    267:     case 16384:
                    268:     case 32768:
                    269:       return 1;
                    270:     }
                    271:   return 0;
                    272: }
                    273: 
                    274: /* Return true is OP is a valid source operand for an integer move
                    275:    instruction.  */
                    276: int
                    277: general_operand_src (op, mode)
                    278:      rtx op;
                    279:      enum machine_mode mode;
                    280: {
                    281:   /* We can't have a pre-dec as a source.  */
                    282:   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC)
                    283:     return 0;
                    284:   return general_operand (op, mode);
                    285: }
                    286: 
                    287: /* Return true if OP is a valid destination operand for an integer move
                    288:    instruction.  */
                    289: int
                    290: general_operand_dst (op, mode)
                    291:      rtx op;
                    292:      enum machine_mode mode;
                    293: {
                    294:   /* We can't have a post-inc as a dest.  */
                    295:   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
                    296:     return 0;
                    297:   return general_operand (op, mode);
                    298: }
                    299: 
                    300: /* Handle machine specific pragmas for compatibility with existing
                    301:    compilers for the H8/300
                    302: 
                    303:    pragma saveall generates prolog/epilog code which saves and
                    304:    restores all the registers on function entry.
                    305:    
                    306:    pragma interrupt saves and restores all registers, and exits with
                    307:    an rte instruction rather than an rts.  A pointer to a function
                    308:    with this attribute may be safely used in an interrupt vector.  */
                    309: int
                    310: handle_pragma (file)
                    311:      FILE *file;
                    312: {
                    313:   int c;
                    314:   char pbuf[20];
                    315:   int psize;
                    316: 
                    317:   c = getc (file);
                    318:   while (c == ' ' || c == '\t')
                    319:     c = getc (file);
                    320: 
                    321:   if (c == '\n' || c == EOF)
                    322:     return c;
                    323: 
                    324:   for (psize = 0; psize < sizeof (pbuf) - 1 && isalpha (c); psize++)
                    325:     {
                    326:       pbuf[psize] = c;
                    327:       c = getc (file);
                    328:     }
                    329: 
                    330:   pbuf[psize] = 0;
                    331: 
                    332:   if (strcmp (pbuf, "interrupt") == 0)
                    333:     pragma_interrupt = 1;
                    334: 
                    335:   if (strcmp (pbuf, "saveall") == 0)
                    336:     pragma_saveall = 1;
                    337: 
                    338:   return c;
                    339: }
                    340: 
                    341: /* If the next arg with MODE and TYPE is to be passed in a register, return
                    342:    the rtx to represent where it is passed.  CUM represents the state after
                    343:    the last argument.  NAMED is not used.  */
                    344: 
                    345: rtx
                    346: function_arg (cum, mode, type, named)
                    347:      CUMULATIVE_ARGS *cum;
                    348:      enum machine_mode mode;
                    349:      tree type;
                    350:      int named;
                    351: {
                    352:   rtx result = 0;
                    353:   int libcall = 0;
                    354: 
                    355:   /* Right now reload has a problem with reg passing with small reg
                    356:      classes.  */
                    357: 
                    358:   if (cum->libcall || (named && TARGET_QUICKCALL))
                    359:     libcall = 1;
                    360: 
                    361:   if (TARGET_NOQUICK)
                    362:     libcall = 0;
                    363: 
                    364:   if (mode != VOIDmode && libcall && mode != DFmode && mode != SFmode)
                    365:     {
                    366:       switch (cum->nbytes)
                    367:        {
                    368:        case 0:
                    369:          result = gen_rtx (REG, mode, 0);
                    370:          break;
                    371:        case 2:
                    372:          result = gen_rtx (REG, mode, 1);
                    373:          break;
                    374:        case 4:
                    375:          result = gen_rtx (REG, mode, 4);
                    376:          break;
                    377:        case 6:
                    378:          result = gen_rtx (REG, mode, 5);
                    379:          break;
                    380:        default:
                    381:          return 0;
                    382:        }
                    383:     }
                    384:   return result;
                    385: }
                    386: 
                    387: /* Documentation for the machine specific operand escapes:
                    388: 
                    389:    'C' print (operand - 2).
                    390:    'E' low byte of reg or -ve lsb of constant
                    391:    'F' high byte of reg of -ve  msb of constant
                    392: 
                    393:    'G' negate constant
                    394:    'L' fake label, changed after used twice.
                    395:    'M' turn a 'M' constant into its negative mod 2.
                    396:    'T' print operand as a word
                    397:    'V' print log2 of constant - used for bset instructions
                    398:    'X' 8 bit register or other operand
                    399: 
                    400:    'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8.
                    401:    'Z' print int & 7
                    402: 
                    403:    'e' first word of 32 bit value
                    404:    'f' second word of 32 bit value
                    405: 
                    406:    'j' print operand as condition code.
                    407:    'k' print operand as reverse condition code.
                    408: 
                    409:    's' low byte of 16 bit value
                    410:    't' high byte of 16 bit value
                    411: 
                    412:    'w' 1st byte of 32 bit value           zzzzzzzz yyyyyyyy xxxxxxxx wwwwwwww
                    413:    'x' 2nd byte of 32 bit value
                    414:    'y' 3rd byte of 32 bit value
                    415:    'z' 4th byte of 32 bit value
                    416: 
                    417:  */
                    418: 
                    419: /* Return assembly language string which identifies a comparison type.  */
                    420: 
                    421: char *
                    422: cond_string (code)
                    423:      enum rtx_code code;
                    424: {
                    425:   switch (code)
                    426:     {
                    427:     case NE:
                    428:       return "ne";
                    429:     case EQ:
                    430:       return "eq";
                    431:     case GE:
                    432:       return "ge";
                    433:     case GT:
                    434:       return "gt";
                    435:     case LE:
                    436:       return "le";
                    437:     case LT:
                    438:       return "lt";
                    439:     case GEU:
                    440:       return "hs";
                    441:     case GTU:
                    442:       return "hi";
                    443:     case LEU:
                    444:       return "ls";
                    445:     case LTU:
                    446:       return "lo";
                    447:     default:
                    448:       abort ();
                    449:     }
                    450: }
                    451: 
                    452: /* Print operand X using operand code CODE to assembly language output file
                    453:    FILE.  */
                    454: 
                    455: void
                    456: print_operand (file, x, code)
                    457:      FILE *file;
                    458:      rtx x;
                    459:      int code;
                    460: {
                    461:   /* This is used to general unique labels for the 'L' code.  */
                    462:   static int lab = 1000;
                    463: 
                    464:   /* This is used for communication between the 'P' and 'U' codes.  */
                    465:   static char *last_p;
                    466: 
                    467:   /* This is used for communication between the 'Z' and 'Y' codes.  */
                    468:   static int bitint;
                    469: 
                    470:   switch (code)
                    471:     {
                    472:     case 'L':
                    473:       /* 'L' must always be used twice in a single pattern.  It generates
                    474:         the same lable twice, and then will generate a unique label the
                    475:         next time it is used.  */
                    476:       asm_fprintf (file, "tl%d", (lab++) / 2);
                    477:       break;
                    478: 
                    479:     case 'X':
                    480:       if (GET_CODE (x) == REG)
                    481:        fprintf (file, "%s", byte_reg (x, 0));
                    482:       else
                    483:        goto def;
                    484:       break;
                    485: 
                    486:     case 'G':
                    487:       if (GET_CODE (x) != CONST_INT)
                    488:        abort ();
                    489:       fprintf (file, "#%d", 0xff & (-INTVAL (x)));
                    490:       break;
                    491: 
                    492:     case 'T':
                    493:       if (GET_CODE (x) == REG)
                    494:        fprintf (file, "%s", names_big[REGNO (x)]);
                    495:       else
                    496:        goto def;
                    497:       break;
                    498: 
                    499:     case 'w':
                    500:       if (GET_CODE (x) == CONST_INT)
                    501:        fprintf (file, "#%d", INTVAL (x) & 0xff);
                    502:       else
                    503:        fprintf (file, "%s", byte_reg (x, 2));
                    504:       break;
                    505: 
                    506:     case 'x':
                    507:       if (GET_CODE (x) == CONST_INT)
                    508:        fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
                    509:       else
                    510:        fprintf (file, "%s", byte_reg (x, 3));
                    511:       break;
                    512: 
                    513:     case 'y':
                    514:       if (GET_CODE (x) == CONST_INT)
                    515:        fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff);
                    516:       else
                    517:        fprintf (file, "%s", byte_reg (x, 0));
                    518:       break;
                    519: 
                    520:     case 'z':
                    521:       if (GET_CODE (x) == CONST_INT)
                    522:        fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff);
                    523:       else
                    524:        fprintf (file, "%s", byte_reg (x, 1));
                    525:       break;
                    526: 
                    527:       /* FOR 16 bits.  */
                    528:     case 't':
                    529:       if (GET_CODE (x) == CONST_INT)
                    530:        fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
                    531:       else
                    532:        fprintf (file, "%s", byte_reg (x, 1));
                    533:       break;
                    534: 
                    535:     case 's':
                    536:       if (GET_CODE (x) == CONST_INT)
                    537:        fprintf (file, "#%d", (INTVAL (x)) & 0xff);
                    538:       else
                    539:        fprintf (file, "%s", byte_reg (x, 0));
                    540:       break;
                    541: 
                    542:     case 'u':
                    543:       if (GET_CODE (x) != CONST_INT)
                    544:        abort ();
                    545:       fprintf (file, "%d", INTVAL (x));
                    546:       break;
                    547: 
                    548:     case 'Z':
                    549:       bitint = INTVAL (x);
                    550:       fprintf (file, "#%d", bitint & 7);
                    551:       break;
                    552: 
                    553:     case 'Y':
                    554:       fprintf (file, "%c", bitint > 7 ? 'h' : 'l');
                    555:       break;
                    556: 
                    557:     case 'O':
                    558:       bitint = exact_log2 ((~INTVAL (x)) & 0xff);
                    559:       if (bitint == -1)
                    560:        abort ();
                    561:       fprintf (file, "#%d", bitint & 7);
                    562:       break;
                    563: 
                    564:     case 'V':
                    565:       bitint = exact_log2 (INTVAL (x));
                    566:       if (bitint == -1)
                    567:        abort ();
                    568:       fprintf (file, "#%d", bitint & 7);
                    569:       break;
                    570: 
                    571:     case 'P':
                    572:       if (REGNO (XEXP (XEXP (x, 0), 0)) == STACK_POINTER_REGNUM)
                    573:        {
                    574:          last_p = "";
                    575:          fprintf (file, ".w");
                    576:        }
                    577:       else
                    578:        {
                    579:          last_p = "l";
                    580:          fprintf (file, ".b");
                    581:        }
                    582:       break;
                    583: 
                    584:     case 'U':
                    585:       fprintf (file, "%s%s", names_big[REGNO (x)], last_p);
                    586:       break;
                    587: 
                    588:     case 'M':
                    589:       /* For -4 and -2, the other 2 is handled separately.  */
                    590:       switch (INTVAL (x))
                    591:        {
                    592:        case -2:
                    593:        case -4:
                    594:          fprintf (file, "#2");
                    595:          break;
                    596:        case -1:
                    597:        case -3:
                    598:          fprintf (file, "#1");
                    599:          break;
                    600: 
                    601:        default:
                    602:          abort ();
                    603:        }
                    604:       break;
                    605: 
                    606:     case 'e':
                    607:       switch (GET_CODE (x))
                    608:        {
                    609:        case REG:
                    610:          fprintf (file, "%s", names_big[REGNO (x)]);
                    611:          break;
                    612:        case MEM:
                    613:          x = adj_offsettable_operand (x, 0);
                    614:          print_operand (file, x, 0);
                    615:          break;
                    616:        case CONST_INT:
                    617:          fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff));
                    618:          break;
                    619:        default:
                    620:          abort ();
                    621:          break;
                    622:        }
                    623:       break;
                    624: 
                    625:     case 'f':
                    626:       switch (GET_CODE (x))
                    627:        {
                    628:        case REG:
                    629:          fprintf (file, "%s", names_big[REGNO (x) + 1]);
                    630:          break;
                    631: 
                    632:        case MEM:
                    633:          x = adj_offsettable_operand (x, 2);
                    634:          print_operand (file, x, 0);
                    635:          break;
                    636: 
                    637:        case CONST_INT:
                    638:          fprintf (file, "#%d", INTVAL (x) & 0xffff);
                    639:          break;
                    640: 
                    641:        default:
                    642:          abort ();
                    643:        }
                    644:       break;
                    645: 
                    646:     case 'C':
                    647:       fprintf (file, "#%d", INTVAL (x) - 2);
                    648:       break;
                    649: 
                    650:     case 'E':
                    651:       switch (GET_CODE (x))
                    652:        {
                    653:        case REG:
                    654:          fprintf (file, "%sl", names_big[REGNO (x)]);
                    655:          break;
                    656: 
                    657:        case CONST_INT:
                    658:          fprintf (file, "#%d", (-INTVAL (x)) & 0xff);
                    659:          break;
                    660: 
                    661:        default:
                    662:          abort ();
                    663:        }
                    664:       break;
                    665: 
                    666:     case 'F':
                    667:       switch (GET_CODE (x))
                    668:        {
                    669:        case REG:
                    670:          fprintf (file, "%sh", names_big[REGNO (x)]);
                    671:          break;
                    672: 
                    673:        case CONST_INT:
                    674:          fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8);
                    675:          break;
                    676: 
                    677:        default:
                    678:          abort ();
                    679:        }
                    680:       break;
                    681: 
                    682:     case 'j':
                    683:       asm_fprintf (file, cond_string (GET_CODE (x)));
                    684:       break;
                    685: 
                    686:     case 'k':
                    687:       asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
                    688:       break;
                    689:     def: ;
                    690:     default:
                    691:       switch (GET_CODE (x))
                    692:        {
                    693:        case REG:
                    694:          fprintf (file, "%s", names_big[REGNO (x)]);
                    695:          break;
                    696: 
                    697:        case MEM:
                    698:          fprintf (file, "@");
                    699:          output_address (XEXP (x, 0));
                    700:          break;
                    701: 
                    702:        case CONST_INT:
                    703:        case SYMBOL_REF:
                    704:        case CONST:
                    705:        case LABEL_REF:
                    706:          fprintf (file, "#");
                    707:          print_operand_address (file, x);
                    708:          break;
                    709:        }
                    710:     }
                    711: }
                    712: 
                    713: /* Output assembly language output for the address ADDR to FILE.  */
                    714: 
                    715: void
                    716: print_operand_address (file, addr)
                    717:      FILE *file;
                    718:      rtx addr;
                    719: {
                    720:   switch (GET_CODE (addr))
                    721:     {
                    722:     case REG:
                    723:       fprintf (file, "%s", names_big[REGNO (addr)]);
                    724:       break;
                    725: 
                    726:     case PRE_DEC:
                    727:       fprintf (file, "-%s", names_big[REGNO (XEXP (addr, 0))]);
                    728:       break;
                    729: 
                    730:     case POST_INC:
                    731:       fprintf (file, "%s+", names_big[REGNO (XEXP (addr, 0))]);
                    732:       break;
                    733: 
                    734:     case PLUS:
                    735:       fprintf (file, "(");
                    736:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    737:        {
                    738:          /* reg,foo */
                    739:          print_operand_address (file, XEXP (addr, 1));
                    740:          fprintf (file, ",");
                    741:          print_operand_address (file, XEXP (addr, 0));
                    742:        }
                    743:       else
                    744:        {
                    745:          /* foo+k */
                    746:          print_operand_address (file, XEXP (addr, 0));
                    747:          fprintf (file, "+");
                    748:          print_operand_address (file, XEXP (addr, 1));
                    749:        }
                    750:       fprintf (file, ")");
                    751:       break;
                    752: 
                    753:     case CONST_INT:
                    754:       if (INTVAL (addr) < 0)
                    755:        {
                    756:          int v = -INTVAL (addr);
                    757: 
                    758:          fprintf (file, "-%d", v);
                    759:        }
                    760:       else
                    761:        fprintf (file, "%d", INTVAL (addr));
                    762:       break;
                    763: 
                    764:     default:
                    765:       output_addr_const (file, addr);
                    766:       break;
                    767:     }
                    768: }
                    769: 
                    770: /* Output to FILE a reference to the user-level label NAME.
                    771:    Strip off the section name if any.  It is separated from the label name
                    772:    by a space.  */
                    773: 
                    774: void
                    775: asm_output_labelref (file, name)
                    776:      FILE *file;
                    777:      char *name;
                    778: {
                    779:   char *p;
                    780: 
                    781:   fputc ('_', file);
                    782: 
                    783:   for (p = name; *p; p++)
                    784:     {
                    785:       if (*p == ' ')
                    786:        {
                    787:          /* If we found a space in the name, then we've skipped over the
                    788:             section encoding.  */
                    789:          fputs (p + 1, file);
                    790:          return;
                    791:        }
                    792:     }
                    793: 
                    794:   /* No space, so no section.  */
                    795:   fputs (name, file);
                    796: }
                    797: 
                    798: /* Output all insn addresses and their sizes into the assembly language
                    799:    output file.  This is helpful for debugging whether the length attributes
                    800:    in the md file are correct.  This is not meant to be a user selectable
                    801:    option.  */
                    802: 
                    803: void
                    804: final_prescan_insn (insn, operand, num_operands)
                    805:      rtx insn, *operand;
                    806:      int num_operands;
                    807: {
                    808:   /* This holds the last insn address.  */
                    809:   static int last_insn_address = 0;
                    810: 
                    811:   int uid = INSN_UID (insn);
                    812: 
                    813:   if (TARGET_ADDRESSES)
                    814:     {
                    815:       fprintf (asm_out_file, "; %d %d\n", insn_addresses[uid],
                    816:               insn_addresses[uid] - last_insn_address);
                    817:       last_insn_address = insn_addresses[uid];
                    818:     }
                    819: }
                    820: 
                    821: static void
                    822: shift_n_bits (lval, operand, f, notzero)
                    823:      rtx lval;
                    824:      rtx operand;
                    825:      rtx (*f) ();
                    826:      int notzero;
                    827: {
                    828:   rtx label = gen_label_rtx ();
                    829:   rtx bot = gen_label_rtx ();
                    830: 
                    831:   if (! notzero)
                    832:     {
                    833:       /* Have to put a zero test at the top.  */
                    834:       emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, lval));
                    835:       emit_jump_insn (gen_beq (bot));
                    836:     }
                    837:   emit_label (label);
                    838:   f (operand);
                    839:   emit_insn (gen_rtx (SET, QImode, lval,
                    840:                      gen_rtx (MINUS, QImode, lval, const1_rtx)));
                    841:   emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, lval));
                    842:   emit_jump_insn (gen_bne (label));
                    843: 
                    844:   emit_label (bot);
                    845:   /* We can't end an expand with a label.  */
                    846:   emit_move_insn (operand, operand);
                    847: }
                    848: 
                    849: int
                    850: can_shift (code, operands, f, limit, fby_eight)
                    851:      int code;
                    852:      rtx operands[];
                    853:      rtx (*f) ();
                    854:      int limit;
                    855:      rtx (*fby_eight) ();
                    856: {
                    857:   extern int rtx_equal_function_value_matters;
                    858: 
                    859:   emit_move_insn (operands[0], operands[1]);
                    860: 
                    861:   if (GET_CODE (operands[2]) != CONST_INT)
                    862:     {
                    863:       rtx lval;
                    864: 
                    865:       /* Can't define expand a loop after rtl generation.  */
                    866:       if (! rtx_equal_function_value_matters)
                    867:        return 0;
                    868: 
                    869:       lval = gen_reg_rtx (QImode);
                    870: 
                    871:       convert_move (lval, operands[2], 1);
                    872:       shift_n_bits (lval, operands[0], f, 0);
                    873:     }
                    874:   else
                    875:     {
                    876:       int i;
                    877: 
                    878:       i = INTVAL (operands[2]);
                    879:       if (i >= 8 && fby_eight)
                    880:        {
                    881:          fby_eight (operands[0]);
                    882:          i -= 8;
                    883:        }
                    884:       if (i > limit)
                    885:        {
                    886:          rtx lval;
                    887: 
                    888:          /* Can't define expand a loop after rtl generation.  */
                    889:          if (! rtx_equal_function_value_matters)
                    890:            return 0;
                    891:          lval = gen_reg_rtx (QImode);
                    892:          emit_move_insn (lval, gen_rtx (CONST_INT, VOIDmode, i));
                    893:          shift_n_bits (lval, operands[0], f, 1);
                    894:        }
                    895:       else
                    896:        {
                    897:          while (i--)
                    898:            f (operands[0]);
                    899:        }
                    900:     }
                    901:   return 1;
                    902: }
                    903: 
                    904: int
                    905: domovsi (operands)
                    906:      rtx operands[];
                    907: {
                    908:   rtx src = operands[1];
                    909:   rtx dst = operands[0];
                    910: 
                    911:   if (push_operand (dst, GET_MODE (dst)))
                    912:     {
                    913:       /* Source must be a reg.  */
                    914:       if (! REG_P (src))
                    915:        {
                    916:          rtx tmp = gen_reg_rtx (GET_MODE (dst));
                    917: 
                    918:          emit_move_insn (tmp, src);
                    919:          operands[1] = tmp;
                    920:        }
                    921:     }
                    922:   return 0;
                    923: }
                    924: 
                    925: int
                    926: io (FROM, TO)
                    927: {
                    928:   int OFFSET = 0;
                    929: 
                    930:   if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)
                    931:     (OFFSET) = 2 + frame_pointer_needed * 2;
                    932:   else
                    933:     {
                    934:       int regno;
                    935:       int offset = 0;
                    936: 
                    937:       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                    938:        if ((regs_ever_live[regno]
                    939:             && (! call_used_regs[regno] || regno == FRAME_POINTER_REGNUM)))
                    940:          offset += 2;
                    941: 
                    942:       (OFFSET) = offset + get_frame_size ();
                    943: 
                    944:       if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)
                    945:        (OFFSET) += 2;          /* Skip saved PC.  */
                    946:     }
                    947:   return OFFSET;
                    948: }

unix.superglobalmegacorp.com

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