Annotation of GNUtools/cc/config/h8300/h8300.c, revision 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.