Annotation of gcc/config/m68k/m68k.c, revision 1.1.1.2

1.1       root        1: /* Subroutines for insn-output.c for Motorola 68000 family.
                      2:    Copyright (C) 1987, 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: /* Some output-actions in m68k.md need these.  */
                     22: #include <stdio.h>
                     23: #include "config.h"
                     24: #include "rtl.h"
                     25: #include "regs.h"
                     26: #include "hard-reg-set.h"
                     27: #include "real.h"
                     28: #include "insn-config.h"
                     29: #include "conditions.h"
                     30: #include "insn-flags.h"
                     31: #include "output.h"
                     32: #include "insn-attr.h"
                     33: 
                     34: /* Needed for use_return_insn.  */
                     35: #include "flags.h"
                     36: 
                     37: #ifdef SUPPORT_SUN_FPA
                     38: 
                     39: /* Index into this array by (register number >> 3) to find the
                     40:    smallest class which contains that register.  */
                     41: enum reg_class regno_reg_class[]
                     42:   = { DATA_REGS, ADDR_REGS, FP_REGS,
                     43:       LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
                     44: 
                     45: #endif /* defined SUPPORT_SUN_FPA */
                     46: 
                     47: /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
                     48:    if SGS_SWITCH_TABLE.  */
                     49: int switch_table_difference_label_flag;
                     50: 
                     51: static rtx find_addr_reg ();
                     52: rtx legitimize_pic_address ();
                     53: 
                     54: 
                     55: /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the 
                     56:    function at any time during the compilation process.  In the future 
                     57:    we should try and eliminate the USE if we can easily determine that 
                     58:    all PIC references were deleted from the current function.  That would 
                     59:    save an address register */
                     60:    
1.1.1.2 ! root       61: void
1.1       root       62: finalize_pic ()
                     63: {
                     64:   if (flag_pic && current_function_uses_pic_offset_table)
                     65:     emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
                     66: }
                     67: 
                     68: 
                     69: /* This function generates the assembly code for function entry.
                     70:    STREAM is a stdio stream to output the code to.
                     71:    SIZE is an int: how many units of temporary storage to allocate.
                     72:    Refer to the array `regs_ever_live' to determine which registers
                     73:    to save; `regs_ever_live[I]' is nonzero if register number I
                     74:    is ever used in the function.  This function is responsible for
                     75:    knowing which registers should not be saved even if used.  */
                     76: 
                     77: 
                     78: /* Note that the order of the bit mask for fmovem is the opposite
                     79:    of the order for movem!  */
                     80: 
                     81: 
                     82: void
                     83: output_function_prologue (stream, size)
                     84:      FILE *stream;
                     85:      int size;
                     86: {
                     87:   register int regno;
                     88:   register int mask = 0;
                     89:   int num_saved_regs = 0;
                     90:   extern char call_used_regs[];
                     91:   int fsize = (size + 3) & -4;
                     92:   
                     93: 
                     94:   if (frame_pointer_needed)
                     95:     {
                     96:       /* Adding negative number is faster on the 68040.  */
                     97:       if (fsize < 0x8000 && !TARGET_68040)
                     98:        {
                     99: #ifdef MOTOROLA
                    100:          asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
                    101:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    102: #else
                    103:          asm_fprintf (stream, "\tlink %s,%0I%d\n",
                    104:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    105: #endif
                    106:        }
                    107:       else if (TARGET_68020)
                    108:        {
                    109: #ifdef MOTOROLA
                    110:          asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
                    111:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    112: #else
                    113:          asm_fprintf (stream, "\tlink %s,%0I%d\n",
                    114:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    115: #endif
                    116:        }
                    117:       else
                    118:        {
                    119: #ifdef MOTOROLA
                    120:          asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
                    121:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    122: #else
                    123:          asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
                    124:                       reg_names[FRAME_POINTER_REGNUM], -fsize);
                    125: #endif
                    126:        }
                    127:     }
                    128:   else if (fsize)
                    129:     {
                    130:       /* Adding negative number is faster on the 68040.  */
                    131:       if (fsize + 4 < 0x8000)
                    132:        {
                    133: #ifdef MOTOROLA
                    134:          asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
                    135: #else
                    136:          asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
                    137: #endif
                    138:        }
                    139:       else
                    140:        {
                    141: #ifdef MOTOROLA
                    142:          asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
                    143: #else
                    144:          asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
                    145: #endif
                    146:        }
                    147:     }
                    148: #ifdef SUPPORT_SUN_FPA
                    149:   for (regno = 24; regno < 56; regno++)
                    150:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    151:       {
                    152: #ifdef MOTOROLA
                    153:        asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
                    154:                     reg_names[regno]);
                    155: #else
                    156:        asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
                    157:                     reg_names[regno]);
                    158: #endif
                    159:       }
                    160: #endif
                    161:   for (regno = 16; regno < 24; regno++)
                    162:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    163:        mask |= 1 << (regno - 16);
                    164:   if ((mask & 0xff) != 0)
                    165:     {
                    166: #ifdef MOTOROLA
                    167:       asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
                    168: #else
                    169:       asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
                    170: #endif
                    171:     }
                    172:   mask = 0;
                    173:   for (regno = 0; regno < 16; regno++)
                    174:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    175:       {
                    176:         mask |= 1 << (15 - regno);
                    177:         num_saved_regs++;
                    178:       }
                    179:   if (frame_pointer_needed)
                    180:     {
                    181:       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
                    182:       num_saved_regs--;
                    183:     }
                    184: 
                    185: #if NEED_PROBE
                    186:   fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
                    187: #endif
                    188: 
                    189:   if (num_saved_regs <= 2)
                    190:     {
                    191:       /* Store each separately in the same order moveml uses.
                    192:          Using two movel instructions instead of a single moveml
                    193:          is about 15% faster for the 68020 and 68030 at no expense
                    194:          in code size */
                    195: 
                    196:       int i;
                    197: 
                    198:       /* Undo the work from above. */
                    199:       for (i = 0; i< 16; i++)
                    200:         if (mask & (1 << i))
                    201:           asm_fprintf (stream,
                    202: #ifdef MOTOROLA
                    203:                       "\t%Omove.l %s,-(%Rsp)\n",
                    204: #else
                    205:                       "\tmovel %s,%Rsp@-\n",
                    206: #endif
                    207:                       reg_names[15 - i]);
                    208:     }
                    209:   else if (mask)
                    210:     {
                    211: #ifdef MOTOROLA
                    212:       asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
                    213: #else
                    214:       asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
                    215: #endif
                    216:     }
                    217:   if (flag_pic && current_function_uses_pic_offset_table)
                    218:     {
                    219: #ifdef MOTOROLA
                    220:       asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
                    221:                   reg_names[PIC_OFFSET_TABLE_REGNUM]);
                    222: #else
                    223:       asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
                    224:                   reg_names[PIC_OFFSET_TABLE_REGNUM]);
                    225:       asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
                    226:                   reg_names[PIC_OFFSET_TABLE_REGNUM],
                    227:                   reg_names[PIC_OFFSET_TABLE_REGNUM]);
                    228: #endif
                    229:     }
                    230: }
                    231: 
                    232: /* Return true if this function's epilogue can be output as RTL.  */
                    233: 
                    234: int
                    235: use_return_insn ()
                    236: {
                    237:   int regno;
                    238: 
                    239:   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
                    240:     return 0;
                    241:   
                    242:   /* Copied from output_function_epilogue ().  We should probably create a
                    243:      separate layout routine to perform the common work.  */
                    244:   
                    245:   for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
                    246:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    247:       return 0;
                    248:   
                    249:   return 1;
                    250: }
                    251: 
                    252: /* This function generates the assembly code for function exit,
                    253:    on machines that need it.  Args are same as for FUNCTION_PROLOGUE.
                    254: 
                    255:    The function epilogue should not depend on the current stack pointer!
                    256:    It should use the frame pointer only, if there is a frame pointer.
                    257:    This is mandatory because of alloca; we also take advantage of it to
                    258:    omit stack adjustments before returning.  */
                    259: 
                    260: void
                    261: output_function_epilogue (stream, size)
                    262:      FILE *stream;
                    263:      int size;
                    264: {
                    265:   register int regno;
                    266:   register int mask, fmask;
                    267:   register int nregs;
                    268:   int offset, foffset, fpoffset;
                    269:   extern char call_used_regs[];
                    270:   int fsize = (size + 3) & -4;
                    271:   int big = 0;
                    272:   rtx insn = get_last_insn ();
                    273:   
                    274:   /* If the last insn was a BARRIER, we don't have to write any code.  */
                    275:   if (GET_CODE (insn) == NOTE)
                    276:     insn = prev_nonnote_insn (insn);
                    277:   if (insn && GET_CODE (insn) == BARRIER)
                    278:     {
                    279:       /* Output just a no-op so that debuggers don't get confused
                    280:         about which function the pc is in at this address.  */
                    281:       asm_fprintf (stream, "\tnop\n");
                    282:       return;
                    283:     }
                    284: 
                    285: #ifdef FUNCTION_EXTRA_EPILOGUE
                    286:   FUNCTION_EXTRA_EPILOGUE (stream, size);
                    287: #endif
                    288:   nregs = 0;  fmask = 0; fpoffset = 0;
                    289: #ifdef SUPPORT_SUN_FPA
                    290:   for (regno = 24 ; regno < 56 ; regno++)
                    291:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    292:       nregs++;
                    293:   fpoffset = nregs * 8;
                    294: #endif
                    295:   nregs = 0;
                    296:   for (regno = 16; regno < 24; regno++)
                    297:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    298:       {
                    299:         nregs++;
                    300:        fmask |= 1 << (23 - regno);
                    301:       }
                    302:   foffset = fpoffset + nregs * 12;
                    303:   nregs = 0;  mask = 0;
                    304:   if (frame_pointer_needed)
                    305:     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
                    306:   for (regno = 0; regno < 16; regno++)
                    307:     if (regs_ever_live[regno] && ! call_used_regs[regno])
                    308:       {
                    309:         nregs++;
                    310:        mask |= 1 << regno;
                    311:       }
                    312:   offset = foffset + nregs * 4;
                    313:   if (offset + fsize >= 0x8000
                    314:       && frame_pointer_needed
                    315:       && (mask || fmask || fpoffset))
                    316:     {
                    317: #ifdef MOTOROLA
                    318:       asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra0\n", -fsize);
                    319: #else
                    320:       asm_fprintf (stream, "\tmovel %0I%d,%Ra0\n", -fsize);
                    321: #endif
                    322:       fsize = 0, big = 1;
                    323:     }
                    324:   if (nregs <= 2)
                    325:     {
                    326:       /* Restore each separately in the same order moveml does.
                    327:          Using two movel instructions instead of a single moveml
                    328:          is about 15% faster for the 68020 and 68030 at no expense
                    329:          in code size. */
                    330: 
                    331:       int i;
                    332: 
                    333:       /* Undo the work from above. */
                    334:       for (i = 0; i< 16; i++)
                    335:         if (mask & (1 << i))
                    336:           {
                    337:             if (big)
                    338:              {
                    339: #ifdef MOTOROLA
                    340:                asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra0.l),%s\n",
                    341:                             offset + fsize,
                    342:                             reg_names[FRAME_POINTER_REGNUM],
                    343:                             reg_names[i]);
                    344: #else
                    345:                asm_fprintf (stream, "\tmovel %s@(-%d,%Ra0:l),%s\n",
                    346:                             reg_names[FRAME_POINTER_REGNUM],
                    347:                             offset + fsize, reg_names[i]);
                    348: #endif
                    349:              }
                    350:             else if (! frame_pointer_needed)
                    351:              {
                    352: #ifdef MOTOROLA
                    353:                asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
                    354:                             reg_names[i]);
                    355: #else
                    356:                asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
                    357:                             reg_names[i]);
                    358: #endif
                    359:              }
                    360:             else
                    361:              {
                    362: #ifdef MOTOROLA
                    363:                asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
                    364:                             offset + fsize,
                    365:                             reg_names[FRAME_POINTER_REGNUM],
                    366:                             reg_names[i]);
                    367: #else
                    368:                asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
                    369:                             reg_names[FRAME_POINTER_REGNUM],
                    370:                             offset + fsize, reg_names[i]);
                    371: #endif
                    372:              }
                    373:             offset = offset - 4;
                    374:           }
                    375:     }
                    376:   else if (mask)
                    377:     {
                    378:       if (big)
                    379:        {
                    380: #ifdef MOTOROLA
                    381:          asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n",
                    382:                       offset + fsize,
                    383:                       reg_names[FRAME_POINTER_REGNUM],
                    384:                       mask);
                    385: #else
                    386:          asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n",
                    387:                       reg_names[FRAME_POINTER_REGNUM],
                    388:                       offset + fsize, mask);
                    389: #endif
                    390:        }
                    391:       else if (! frame_pointer_needed)
                    392:        {
                    393: #ifdef MOTOROLA
                    394:          asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
                    395: #else
                    396:          asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
                    397: #endif
                    398:        }
                    399:       else
                    400:        {
                    401: #ifdef MOTOROLA
                    402:          asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
                    403:                       offset + fsize,
                    404:                       reg_names[FRAME_POINTER_REGNUM],
                    405:                       mask);
                    406: #else
                    407:          asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
                    408:                       reg_names[FRAME_POINTER_REGNUM],
                    409:                       offset + fsize, mask);
                    410: #endif
                    411:        }
                    412:     }
                    413:   if (fmask)
                    414:     {
                    415:       if (big)
                    416:        {
                    417: #ifdef MOTOROLA
                    418:          asm_fprintf (stream, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n",
                    419:                       foffset + fsize,
                    420:                       reg_names[FRAME_POINTER_REGNUM],
                    421:                       fmask);
                    422: #else
                    423:          asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n",
                    424:                       reg_names[FRAME_POINTER_REGNUM],
                    425:                       foffset + fsize, fmask);
                    426: #endif
                    427:        }
                    428:       else if (! frame_pointer_needed)
                    429:        {
                    430: #ifdef MOTOROLA
                    431:          asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
                    432: #else
                    433:          asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
                    434: #endif
                    435:        }
                    436:       else
                    437:        {
                    438: #ifdef MOTOROLA
                    439:          asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
                    440:                       foffset + fsize,
                    441:                       reg_names[FRAME_POINTER_REGNUM],
                    442:                       fmask);
                    443: #else
                    444:          asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
                    445:                       reg_names[FRAME_POINTER_REGNUM],
                    446:                       foffset + fsize, fmask);
                    447: #endif
                    448:        }
                    449:     }
                    450:   if (fpoffset != 0)
                    451:     for (regno = 55; regno >= 24; regno--)
                    452:       if (regs_ever_live[regno] && ! call_used_regs[regno])
                    453:         {
                    454:          if (big)
                    455:            {
                    456: #ifdef MOTOROLA
                    457:              asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra0.l), %s\n",
                    458:                           fpoffset + fsize,
                    459:                           reg_names[FRAME_POINTER_REGNUM],
                    460:                           reg_names[regno]);
                    461: #else
                    462:              asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra0:l), %s\n",
                    463:                           reg_names[FRAME_POINTER_REGNUM],
                    464:                           fpoffset + fsize, reg_names[regno]);
                    465: #endif
                    466:            }
                    467:          else if (! frame_pointer_needed)
                    468:            {
                    469: #ifdef MOTOROLA
                    470:              asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
                    471:                           reg_names[regno]);
                    472: #else
                    473:              asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
                    474:                           reg_names[regno]);
                    475: #endif
                    476:            }
                    477:          else
                    478:            {
                    479: #ifdef MOTOROLA
                    480:              asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
                    481:                           fpoffset + fsize,
                    482:                           reg_names[FRAME_POINTER_REGNUM],
                    483:                           reg_names[regno]);
                    484: #else
                    485:              asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
                    486:                           reg_names[FRAME_POINTER_REGNUM],
                    487:                           fpoffset + fsize, reg_names[regno]);
                    488: #endif
                    489:            }
                    490:          fpoffset -= 8;
                    491:        }
                    492:   if (frame_pointer_needed)
                    493:     fprintf (stream, "\tunlk %s\n",
                    494:             reg_names[FRAME_POINTER_REGNUM]);
                    495:   else if (fsize)
                    496:     {
                    497:       if (fsize + 4 < 0x8000)
                    498:        {
                    499: #ifdef MOTOROLA
                    500:          asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
                    501: #else
                    502:          asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
                    503: #endif
                    504:        }
                    505:       else
                    506:        {
                    507: #ifdef MOTOROLA
                    508:          asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
                    509: #else
                    510:          asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
                    511: #endif
                    512:        }
                    513:     }
                    514:   if (current_function_pops_args)
                    515:     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
                    516:   else
                    517:     fprintf (stream, "\trts\n");
                    518: }
                    519: 
                    520: /* Similar to general_operand, but exclude stack_pointer_rtx.  */
                    521: 
                    522: int
                    523: not_sp_operand (op, mode)
                    524:      register rtx op;
                    525:      enum machine_mode mode;
                    526: {
                    527:   return op != stack_pointer_rtx && general_operand (op, mode);
                    528: }
                    529: 
                    530: /* Return TRUE if X is a valid comparison operator for the dbcc 
                    531:    instruction.  
                    532: 
                    533:    Note it rejects floating point comparison operators.
                    534:    (In the future we could use Fdbcc).
                    535: 
                    536:    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
                    537:    
                    538: int
                    539: valid_dbcc_comparison_p (x, mode)
                    540:      rtx x;
                    541:      enum machine_mode mode;
                    542: {
                    543:   /* We could add support for these in the future */
                    544:   if (cc_prev_status.flags & CC_IN_68881)
                    545:     return 0;
                    546: 
                    547:   switch (GET_CODE (x))
                    548:     {
                    549: 
                    550:       case EQ: case NE: case GTU: case LTU:
                    551:       case GEU: case LEU:
                    552:         return 1;
                    553: 
                    554:       /* Reject some when CC_NO_OVERFLOW is set.  This may be over
                    555:          conservative */
                    556:       case GT: case LT: case GE: case LE:
                    557:         return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
                    558:       default:
                    559:         return 0;
                    560:     }
                    561: }
                    562: 
                    563: /* Output a dbCC; jCC sequence.  Note we do not handle the 
                    564:    floating point version of this sequence (Fdbcc).  We also
                    565:    do not handle alternative conditions when CC_NO_OVERFLOW is
                    566:    set.  It is assumed that valid_dbcc_comparison_p will kick
                    567:    those out before we get here.  */
                    568: 
                    569: output_dbcc_and_branch (operands)
                    570:      rtx *operands;
                    571: {
                    572:  
                    573:   switch (GET_CODE (operands[3]))
                    574:     {
                    575:       case EQ:
                    576: #ifdef MOTOROLA
                    577:         output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
                    578: #else
                    579:         output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
                    580: #endif
                    581:         break;
                    582: 
                    583:       case NE:
                    584: #ifdef MOTOROLA
                    585:         output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
                    586: #else
                    587:         output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
                    588: #endif
                    589:         break;
                    590: 
                    591:       case GT:
                    592: #ifdef MOTOROLA
                    593:         output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
                    594: #else
                    595:         output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
                    596: #endif
                    597:         break;
                    598: 
                    599:       case GTU:
                    600: #ifdef MOTOROLA
                    601:         output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
                    602: #else
                    603:         output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
                    604: #endif
                    605:         break;
                    606: 
                    607:       case LT:
                    608: #ifdef MOTOROLA
                    609:         output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
                    610: #else
                    611:         output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
                    612: #endif
                    613:         break;
                    614: 
                    615:       case LTU:
                    616: #ifdef MOTOROLA
                    617:         output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
                    618: #else
                    619:         output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
                    620: #endif
                    621:         break;
                    622: 
                    623:       case GE:
                    624: #ifdef MOTOROLA
                    625:         output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
                    626: #else
                    627:         output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
                    628: #endif
                    629:         break;
                    630: 
                    631:       case GEU:
                    632: #ifdef MOTOROLA
                    633:         output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
                    634: #else
                    635:         output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
                    636: #endif
                    637:         break;
                    638: 
                    639:       case LE:
                    640: #ifdef MOTOROLA
                    641:         output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
                    642: #else
                    643:         output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
                    644: #endif
                    645:         break;
                    646: 
                    647:       case LEU:
                    648: #ifdef MOTOROLA
                    649:         output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
                    650: #else
                    651:         output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
                    652: #endif
                    653:         break;
                    654: 
                    655:       default:
                    656:        abort ();
                    657:     }
                    658: 
                    659:   /* If the decrement is to be done in SImode, then we have
                    660:      to compensate for the fact that dbcc decrements in HImode. */
                    661:   switch (GET_MODE (operands[0]))
                    662:     {
                    663:       case SImode:
                    664: #ifdef MOTOROLA
                    665:         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
                    666: #else
                    667:         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
                    668: #endif
                    669:         break;
                    670: 
                    671:       case HImode:
                    672:         break;
                    673: 
                    674:       default:
                    675:         abort ();
                    676:     }
                    677: }
                    678: 
                    679: char *
                    680: output_btst (operands, countop, dataop, insn, signpos)
                    681:      rtx *operands;
                    682:      rtx countop, dataop;
                    683:      rtx insn;
                    684:      int signpos;
                    685: {
                    686:   operands[0] = countop;
                    687:   operands[1] = dataop;
                    688: 
                    689:   if (GET_CODE (countop) == CONST_INT)
                    690:     {
                    691:       register int count = INTVAL (countop);
                    692:       /* If COUNT is bigger than size of storage unit in use,
                    693:         advance to the containing unit of same size.  */
                    694:       if (count > signpos)
                    695:        {
                    696:          int offset = (count & ~signpos) / 8;
                    697:          count = count & signpos;
                    698:          operands[1] = dataop = adj_offsettable_operand (dataop, offset);
                    699:        }
                    700:       if (count == signpos)
                    701:        cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
                    702:       else
                    703:        cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
                    704: 
                    705:       /* These three statements used to use next_insns_test_no...
                    706:         but it appears that this should do the same job.  */
                    707:       if (count == 31
                    708:          && next_insn_tests_no_inequality (insn))
                    709:        return "tst%.l %1";
                    710:       if (count == 15
                    711:          && next_insn_tests_no_inequality (insn))
                    712:        return "tst%.w %1";
                    713:       if (count == 7
                    714:          && next_insn_tests_no_inequality (insn))
                    715:        return "tst%.b %1";
                    716: 
                    717:       cc_status.flags = CC_NOT_NEGATIVE;
                    718:     }
                    719:   return "btst %0,%1";
                    720: }
                    721: 
                    722: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
                    723:    reference and a constant.  */
                    724: 
                    725: int
                    726: symbolic_operand (op, mode)
                    727:      register rtx op;
                    728:      enum machine_mode mode;
                    729: {
                    730:   switch (GET_CODE (op))
                    731:     {
                    732:     case SYMBOL_REF:
                    733:     case LABEL_REF:
                    734:       return 1;
                    735: 
                    736:     case CONST:
                    737:       op = XEXP (op, 0);
                    738:       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
                    739:               || GET_CODE (XEXP (op, 0)) == LABEL_REF)
                    740:              && GET_CODE (XEXP (op, 1)) == CONST_INT);
                    741: 
                    742: #if 0 /* Deleted, with corresponding change in m68k.h,
                    743:         so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
                    744:     case CONST_DOUBLE:
                    745:       return GET_MODE (op) == mode;
                    746: #endif
                    747: 
                    748:     default:
                    749:       return 0;
                    750:     }
                    751: }
                    752: 
                    753: 
                    754: /* Legitimize PIC addresses.  If the address is already
                    755:    position-independent, we return ORIG.  Newly generated
                    756:    position-independent addresses go to REG.  If we need more
                    757:    than one register, we lose.  
                    758: 
                    759:    An address is legitimized by making an indirect reference
                    760:    through the Global Offset Table with the name of the symbol
                    761:    used as an offset.  
                    762: 
                    763:    The assembler and linker are responsible for placing the 
                    764:    address of the symbol in the GOT.  The function prologue
                    765:    is responsible for initializing a5 to the starting address
                    766:    of the GOT.
                    767: 
                    768:    The assembler is also responsible for translating a symbol name
                    769:    into a constant displacement from the start of the GOT.  
                    770: 
                    771:    A quick example may make things a little clearer:
                    772: 
                    773:    When not generating PIC code to store the value 12345 into _foo
                    774:    we would generate the following code:
                    775: 
                    776:        movel #12345, _foo
                    777: 
                    778:    When generating PIC two transformations are made.  First, the compiler
                    779:    loads the address of foo into a register.  So the first transformation makes:
                    780: 
                    781:        lea     _foo, a0
                    782:        movel   #12345, a0@
                    783: 
                    784:    The code in movsi will intercept the lea instruction and call this
                    785:    routine which will transform the instructions into:
                    786: 
                    787:        movel   a5@(_foo:w), a0
                    788:        movel   #12345, a0@
                    789:    
                    790: 
                    791:    That (in a nutshell) is how *all* symbol and label references are 
                    792:    handled.  */
                    793: 
                    794: rtx
                    795: legitimize_pic_address (orig, mode, reg)
                    796:      rtx orig, reg;
                    797:      enum machine_mode mode;
                    798: {
                    799:   rtx pic_ref = orig;
                    800: 
                    801:   /* First handle a simple SYMBOL_REF or LABEL_REF */
                    802:   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
                    803:     {
                    804:       if (reg == 0)
                    805:        abort ();
                    806: 
                    807:       pic_ref = gen_rtx (MEM, Pmode,
                    808:                         gen_rtx (PLUS, Pmode,
                    809:                                  pic_offset_table_rtx, orig));
                    810:       current_function_uses_pic_offset_table = 1;
                    811:       RTX_UNCHANGING_P (pic_ref) = 1;
                    812:       emit_move_insn (reg, pic_ref);
                    813:       return reg;
                    814:     }
                    815:   else if (GET_CODE (orig) == CONST)
                    816:     {
                    817:       rtx base, offset;
                    818: 
                    819:       /* Make sure this is CONST has not already been legitimized */
                    820:       if (GET_CODE (XEXP (orig, 0)) == PLUS
                    821:          && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
                    822:        return orig;
                    823: 
                    824:       if (reg == 0)
                    825:        abort ();
                    826: 
                    827:       /* legitimize both operands of the PLUS */
                    828:       if (GET_CODE (XEXP (orig, 0)) == PLUS)
                    829:        {
                    830:          base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
                    831:          orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
                    832:                                         base == reg ? 0 : reg);
                    833:        }
                    834:       else abort ();
                    835: 
                    836:       if (GET_CODE (orig) == CONST_INT)
                    837:        return plus_constant_for_output (base, INTVAL (orig));
                    838:       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
                    839:       /* Likewise, should we set special REG_NOTEs here?  */
                    840:     }
                    841:   return pic_ref;
                    842: }
                    843: 
                    844: 
                    845: /* Return the best assembler insn template
                    846:    for moving operands[1] into operands[0] as a fullword.  */
                    847: 
                    848: static char *
                    849: singlemove_string (operands)
                    850:      rtx *operands;
                    851: {
                    852: #ifdef SUPPORT_SUN_FPA
                    853:   if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
                    854:     return "fpmoves %1,%0";
                    855: #endif
                    856:   if (DATA_REG_P (operands[0])
                    857:       && GET_CODE (operands[1]) == CONST_INT
                    858:       && INTVAL (operands[1]) < 128
                    859:       && INTVAL (operands[1]) >= -128)
                    860:     {
                    861: #if defined (MOTOROLA) && !defined (CRDS)
                    862:       return "moveq%.l %1,%0";
                    863: #else
                    864:       return "moveq %1,%0";
                    865: #endif
                    866:     }
                    867:   if (operands[1] != const0_rtx)
                    868:     return "move%.l %1,%0";
                    869:   if (! ADDRESS_REG_P (operands[0]))
                    870:     return "clr%.l %0";
                    871:   return "sub%.l %0,%0";
                    872: }
                    873: 
                    874: 
                    875: /* Output assembler code to perform a doubleword move insn
                    876:    with operands OPERANDS.  */
                    877: 
                    878: char *
                    879: output_move_double (operands)
                    880:      rtx *operands;
                    881: {
                    882:   enum
                    883:     {
                    884:       REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
                    885:     } optype0, optype1;
                    886:   rtx latehalf[2];
                    887:   rtx middlehalf[2];
1.1.1.2 ! root      888:   rtx xops[2];
1.1       root      889:   rtx addreg0 = 0, addreg1 = 0;
1.1.1.2 ! root      890:   int dest_overlapped_low = 0;
1.1       root      891:   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
                    892: 
                    893:   middlehalf[0] = 0;
                    894:   middlehalf[1] = 0;
                    895: 
                    896:   /* First classify both operands.  */
                    897: 
                    898:   if (REG_P (operands[0]))
                    899:     optype0 = REGOP;
                    900:   else if (offsettable_memref_p (operands[0]))
                    901:     optype0 = OFFSOP;
                    902:   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
                    903:     optype0 = POPOP;
                    904:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
                    905:     optype0 = PUSHOP;
                    906:   else if (GET_CODE (operands[0]) == MEM)
                    907:     optype0 = MEMOP;
                    908:   else
                    909:     optype0 = RNDOP;
                    910: 
                    911:   if (REG_P (operands[1]))
                    912:     optype1 = REGOP;
                    913:   else if (CONSTANT_P (operands[1]))
                    914:     optype1 = CNSTOP;
                    915:   else if (offsettable_memref_p (operands[1]))
                    916:     optype1 = OFFSOP;
                    917:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
                    918:     optype1 = POPOP;
                    919:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
                    920:     optype1 = PUSHOP;
                    921:   else if (GET_CODE (operands[1]) == MEM)
                    922:     optype1 = MEMOP;
                    923:   else
                    924:     optype1 = RNDOP;
                    925: 
                    926:   /* Check for the cases that the operand constraints are not
                    927:      supposed to allow to happen.  Abort if we get one,
                    928:      because generating code for these cases is painful.  */
                    929: 
                    930:   if (optype0 == RNDOP || optype1 == RNDOP)
                    931:     abort ();
                    932: 
                    933:   /* If one operand is decrementing and one is incrementing
                    934:      decrement the former register explicitly
                    935:      and change that operand into ordinary indexing.  */
                    936: 
                    937:   if (optype0 == PUSHOP && optype1 == POPOP)
                    938:     {
                    939:       operands[0] = XEXP (XEXP (operands[0], 0), 0);
                    940:       if (size == 12)
                    941:         output_asm_insn ("sub%.l %#12,%0", operands);
                    942:       else
                    943:         output_asm_insn ("subq%.l %#8,%0", operands);
                    944:       if (GET_MODE (operands[1]) == XFmode)
                    945:        operands[0] = gen_rtx (MEM, XFmode, operands[0]);
                    946:       else if (GET_MODE (operands[0]) == DFmode)
                    947:        operands[0] = gen_rtx (MEM, DFmode, operands[0]);
                    948:       else
                    949:        operands[0] = gen_rtx (MEM, DImode, operands[0]);
                    950:       optype0 = OFFSOP;
                    951:     }
                    952:   if (optype0 == POPOP && optype1 == PUSHOP)
                    953:     {
                    954:       operands[1] = XEXP (XEXP (operands[1], 0), 0);
                    955:       if (size == 12)
                    956:         output_asm_insn ("sub%.l %#12,%1", operands);
                    957:       else
                    958:         output_asm_insn ("subq%.l %#8,%1", operands);
                    959:       if (GET_MODE (operands[1]) == XFmode)
                    960:        operands[1] = gen_rtx (MEM, XFmode, operands[1]);
                    961:       else if (GET_MODE (operands[1]) == DFmode)
                    962:        operands[1] = gen_rtx (MEM, DFmode, operands[1]);
                    963:       else
                    964:        operands[1] = gen_rtx (MEM, DImode, operands[1]);
                    965:       optype1 = OFFSOP;
                    966:     }
                    967: 
                    968:   /* If an operand is an unoffsettable memory ref, find a register
                    969:      we can increment temporarily to make it refer to the second word.  */
                    970: 
                    971:   if (optype0 == MEMOP)
                    972:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
                    973: 
                    974:   if (optype1 == MEMOP)
                    975:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
                    976: 
                    977:   /* Ok, we can do one word at a time.
                    978:      Normally we do the low-numbered word first,
                    979:      but if either operand is autodecrementing then we
                    980:      do the high-numbered word first.
                    981: 
                    982:      In either case, set up in LATEHALF the operands to use
                    983:      for the high-numbered word and in some cases alter the
                    984:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    985: 
                    986:   if (size == 12)
                    987:     {
                    988:       if (optype0 == REGOP)
                    989:        {
                    990:          latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
                    991:          middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    992:        }
                    993:       else if (optype0 == OFFSOP)
                    994:        {
                    995:          middlehalf[0] = adj_offsettable_operand (operands[0], 4);
                    996:          latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
                    997:        }
                    998:       else
                    999:        {
                   1000:          middlehalf[0] = operands[0];
                   1001:          latehalf[0] = operands[0];
                   1002:        }
                   1003: 
                   1004:       if (optype1 == REGOP)
                   1005:        {
                   1006:          latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
                   1007:          middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                   1008:        }
                   1009:       else if (optype1 == OFFSOP)
                   1010:        {
                   1011:          middlehalf[1] = adj_offsettable_operand (operands[1], 4);
                   1012:          latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
                   1013:        }
                   1014:       else if (optype1 == CNSTOP)
                   1015:        {
                   1016:          if (GET_CODE (operands[1]) == CONST_DOUBLE)
                   1017:            {
                   1018:              REAL_VALUE_TYPE r;
                   1019:              long l[3];
                   1020: 
                   1021:              REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
                   1022:              REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
                   1023:              operands[1] = GEN_INT (l[0]);
                   1024:              middlehalf[1] = GEN_INT (l[1]);
                   1025:              latehalf[1] = GEN_INT (l[2]);
                   1026:            }
                   1027:          else if (CONSTANT_P (operands[1]))
                   1028:            {
                   1029:              /* actually, no non-CONST_DOUBLE constant should ever
                   1030:                 appear here.  */
                   1031:              abort ();
                   1032:              if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
                   1033:                latehalf[1] = constm1_rtx;
                   1034:              else
                   1035:                latehalf[1] = const0_rtx;
                   1036:            }
                   1037:        }
                   1038:       else
                   1039:        {
                   1040:          middlehalf[1] = operands[1];
                   1041:          latehalf[1] = operands[1];
                   1042:        }
                   1043:     }
                   1044:   else
                   1045:     /* size is not 12: */
                   1046:     {
                   1047:       if (optype0 == REGOP)
                   1048:        latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                   1049:       else if (optype0 == OFFSOP)
                   1050:        latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
                   1051:       else
                   1052:        latehalf[0] = operands[0];
                   1053: 
                   1054:       if (optype1 == REGOP)
                   1055:        latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                   1056:       else if (optype1 == OFFSOP)
                   1057:        latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
                   1058:       else if (optype1 == CNSTOP)
                   1059:        split_double (operands[1], &operands[1], &latehalf[1]);
                   1060:       else
                   1061:        latehalf[1] = operands[1];
                   1062:     }
                   1063: 
                   1064:   /* If insn is effectively movd N(sp),-(sp) then we will do the
                   1065:      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
                   1066:      for the low word as well, to compensate for the first decrement of sp.  */
                   1067:   if (optype0 == PUSHOP
                   1068:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
                   1069:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1.1.1.2 ! root     1070:     operands[1] = middlehalf[1] = latehalf[1];
        !          1071: 
        !          1072:   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
        !          1073:      if the upper part of reg N does not appear in the MEM, arrange to
        !          1074:      emit the move late-half first.  Otherwise, compute the MEM address
        !          1075:      into the upper part of N and use that as a pointer to the memory
        !          1076:      operand.  */
        !          1077:   if (optype0 == REGOP
        !          1078:       && (optype1 == OFFSOP || optype1 == MEMOP))
        !          1079:     {
        !          1080:       rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0]));
        !          1081: 
        !          1082:       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
        !          1083:          && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
        !          1084:        {
        !          1085:          /* If both halves of dest are used in the src memory address,
        !          1086:             compute the address into latehalf of dest.
        !          1087:             Note that this can't happen if the dest is two data regs.  */
        !          1088: compadr:
        !          1089:          xops[0] = latehalf[0];
        !          1090:          xops[1] = XEXP (operands[1], 0);
        !          1091:          output_asm_insn ("lea %a1,%0", xops);
        !          1092:          if( GET_MODE (operands[1]) == XFmode )
        !          1093:            {
        !          1094:              operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
        !          1095:              middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
        !          1096:              latehalf[1] = adj_offsettable_operand (operands[1], size-4);
        !          1097:            }
        !          1098:          else
        !          1099:            {
        !          1100:              operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
        !          1101:              latehalf[1] = adj_offsettable_operand (operands[1], size-4);
        !          1102:            }
        !          1103:        }
        !          1104:       else if (size == 12
        !          1105:               && reg_overlap_mentioned_p (middlehalf[0],
        !          1106:                                           XEXP (operands[1], 0)))
        !          1107:        {
        !          1108:          /* Check for two regs used by both source and dest.
        !          1109:             Note that this can't happen if the dest is all data regs.
        !          1110:             It can happen if the dest is d6, d7, a0.
        !          1111:             But in that case, latehalf is an addr reg, so
        !          1112:             the code at compadr does ok.  */
        !          1113: 
        !          1114:          if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
        !          1115:              || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
        !          1116:            goto compadr;
        !          1117: 
        !          1118:          /* JRV says this can't happen: */
        !          1119:          if (addreg0 || addreg1)
        !          1120:            abort ();
        !          1121: 
        !          1122:          /* Only the middle reg conflicts; simply put it last. */
        !          1123:          output_asm_insn (singlemove_string (operands), operands);
        !          1124:          output_asm_insn (singlemove_string (latehalf), latehalf);
        !          1125:          output_asm_insn (singlemove_string (middlehalf), middlehalf);
        !          1126:          return "";
        !          1127:        }
        !          1128:       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
        !          1129:        /* If the low half of dest is mentioned in the source memory
        !          1130:           address, the arrange to emit the move late half first.  */
        !          1131:        dest_overlapped_low = 1;
        !          1132:     }
1.1       root     1133: 
                   1134:   /* If one or both operands autodecrementing,
                   1135:      do the two words, high-numbered first.  */
                   1136: 
                   1137:   /* Likewise,  the first move would clobber the source of the second one,
                   1138:      do them in the other order.  This happens only for registers;
                   1139:      such overlap can't happen in memory unless the user explicitly
                   1140:      sets it up, and that is an undefined circumstance.  */
                   1141: 
                   1142:   if (optype0 == PUSHOP || optype1 == PUSHOP
                   1143:       || (optype0 == REGOP && optype1 == REGOP
                   1144:          && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1.1.1.2 ! root     1145:              || REGNO (operands[0]) == REGNO (latehalf[1])))
        !          1146:       || dest_overlapped_low)
1.1       root     1147:     {
                   1148:       /* Make any unoffsettable addresses point at high-numbered word.  */
                   1149:       if (addreg0)
                   1150:        {
                   1151:          if (size == 12)
                   1152:            output_asm_insn ("addql %#8,%0", &addreg0);
                   1153:          else
                   1154:            output_asm_insn ("addql %#4,%0", &addreg0);
                   1155:        }
                   1156:       if (addreg1)
                   1157:        {
                   1158:          if (size == 12)
                   1159:            output_asm_insn ("addql %#8,%0", &addreg1);
                   1160:          else
                   1161:            output_asm_insn ("addql %#4,%0", &addreg1);
                   1162:        }
                   1163: 
                   1164:       /* Do that word.  */
                   1165:       output_asm_insn (singlemove_string (latehalf), latehalf);
                   1166: 
                   1167:       /* Undo the adds we just did.  */
                   1168:       if (addreg0)
                   1169:        output_asm_insn ("subql %#4,%0", &addreg0);
                   1170:       if (addreg1)
                   1171:        output_asm_insn ("subql %#4,%0", &addreg1);
                   1172: 
                   1173:       if (size == 12)
                   1174:        {
                   1175:          output_asm_insn (singlemove_string (middlehalf), middlehalf);
                   1176:          if (addreg0)
                   1177:            output_asm_insn ("subql %#4,%0", &addreg0);
                   1178:          if (addreg1)
                   1179:            output_asm_insn ("subql %#4,%0", &addreg1);
                   1180:        }
                   1181: 
                   1182:       /* Do low-numbered word.  */
                   1183:       return singlemove_string (operands);
                   1184:     }
                   1185: 
                   1186:   /* Normal case: do the two words, low-numbered first.  */
                   1187: 
                   1188:   output_asm_insn (singlemove_string (operands), operands);
                   1189: 
                   1190:   /* Do the middle one of the three words for long double */
                   1191:   if (size == 12)
                   1192:     {
                   1193:       if (addreg0)
                   1194:        output_asm_insn ("addql %#4,%0", &addreg0);
                   1195:       if (addreg1)
                   1196:        output_asm_insn ("addql %#4,%0", &addreg1);
                   1197: 
                   1198:       output_asm_insn (singlemove_string (middlehalf), middlehalf);
                   1199:     }
                   1200: 
                   1201:   /* Make any unoffsettable addresses point at high-numbered word.  */
                   1202:   if (addreg0)
                   1203:     output_asm_insn ("addql %#4,%0", &addreg0);
                   1204:   if (addreg1)
                   1205:     output_asm_insn ("addql %#4,%0", &addreg1);
                   1206: 
                   1207:   /* Do that word.  */
                   1208:   output_asm_insn (singlemove_string (latehalf), latehalf);
                   1209: 
                   1210:   /* Undo the adds we just did.  */
                   1211:   if (addreg0)
                   1212:     {
                   1213:       if (size == 12)
                   1214:         output_asm_insn ("subql %#8,%0", &addreg0);
                   1215:       else
                   1216:         output_asm_insn ("subql %#4,%0", &addreg0);
                   1217:     }
                   1218:   if (addreg1)
                   1219:     {
                   1220:       if (size == 12)
                   1221:         output_asm_insn ("subql %#8,%0", &addreg1);
                   1222:       else
                   1223:         output_asm_insn ("subql %#4,%0", &addreg1);
                   1224:     }
                   1225: 
                   1226:   return "";
                   1227: }
                   1228: 
                   1229: /* Return a REG that occurs in ADDR with coefficient 1.
                   1230:    ADDR can be effectively incremented by incrementing REG.  */
                   1231: 
                   1232: static rtx
                   1233: find_addr_reg (addr)
                   1234:      rtx addr;
                   1235: {
                   1236:   while (GET_CODE (addr) == PLUS)
                   1237:     {
                   1238:       if (GET_CODE (XEXP (addr, 0)) == REG)
                   1239:        addr = XEXP (addr, 0);
                   1240:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                   1241:        addr = XEXP (addr, 1);
                   1242:       else if (CONSTANT_P (XEXP (addr, 0)))
                   1243:        addr = XEXP (addr, 1);
                   1244:       else if (CONSTANT_P (XEXP (addr, 1)))
                   1245:        addr = XEXP (addr, 0);
                   1246:       else
                   1247:        abort ();
                   1248:     }
                   1249:   if (GET_CODE (addr) == REG)
                   1250:     return addr;
                   1251:   abort ();
                   1252: }
                   1253: 
                   1254: /* Store in cc_status the expressions that the condition codes will
                   1255:    describe after execution of an instruction whose pattern is EXP.
                   1256:    Do not alter them if the instruction would not alter the cc's.  */
                   1257: 
                   1258: /* On the 68000, all the insns to store in an address register fail to
                   1259:    set the cc's.  However, in some cases these instructions can make it
                   1260:    possibly invalid to use the saved cc's.  In those cases we clear out
                   1261:    some or all of the saved cc's so they won't be used.  */
                   1262: 
                   1263: notice_update_cc (exp, insn)
                   1264:      rtx exp;
                   1265:      rtx insn;
                   1266: {
                   1267:   /* If the cc is being set from the fpa and the expression is not an
                   1268:      explicit floating point test instruction (which has code to deal with
                   1269:      this), reinit the CC.  */
                   1270:   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
                   1271:        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
                   1272:       && !(GET_CODE (exp) == PARALLEL
                   1273:           && GET_CODE (XVECEXP (exp, 0, 0)) == SET
                   1274:           && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
                   1275:     {
                   1276:       CC_STATUS_INIT; 
                   1277:     }
                   1278:   else if (GET_CODE (exp) == SET)
                   1279:     {
                   1280:       if (GET_CODE (SET_SRC (exp)) == CALL)
                   1281:        {
                   1282:          CC_STATUS_INIT; 
                   1283:        }
                   1284:       else if (ADDRESS_REG_P (SET_DEST (exp)))
                   1285:        {
                   1286:          if (cc_status.value1
                   1287:              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
                   1288:            cc_status.value1 = 0;
                   1289:          if (cc_status.value2
                   1290:              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
                   1291:            cc_status.value2 = 0; 
                   1292:        }
                   1293:       else if (!FP_REG_P (SET_DEST (exp))
                   1294:               && SET_DEST (exp) != cc0_rtx
                   1295:               && (FP_REG_P (SET_SRC (exp))
                   1296:                   || GET_CODE (SET_SRC (exp)) == FIX
                   1297:                   || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
                   1298:                   || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
                   1299:        {
                   1300:          CC_STATUS_INIT; 
                   1301:        }
                   1302:       /* A pair of move insns doesn't produce a useful overall cc.  */
                   1303:       else if (!FP_REG_P (SET_DEST (exp))
                   1304:               && !FP_REG_P (SET_SRC (exp))
                   1305:               && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
                   1306:               && (GET_CODE (SET_SRC (exp)) == REG
                   1307:                   || GET_CODE (SET_SRC (exp)) == MEM
                   1308:                   || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
                   1309:        {
                   1310:          CC_STATUS_INIT; 
                   1311:        }
                   1312:       else if (GET_CODE (SET_SRC (exp)) == CALL)
                   1313:        {
                   1314:          CC_STATUS_INIT; 
                   1315:        }
                   1316:       else if (XEXP (exp, 0) != pc_rtx)
                   1317:        {
                   1318:          cc_status.flags = 0;
                   1319:          cc_status.value1 = XEXP (exp, 0);
                   1320:          cc_status.value2 = XEXP (exp, 1);
                   1321:        }
                   1322:     }
                   1323:   else if (GET_CODE (exp) == PARALLEL
                   1324:           && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
                   1325:     {
                   1326:       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
                   1327:        CC_STATUS_INIT;
                   1328:       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
                   1329:        {
                   1330:          cc_status.flags = 0;
                   1331:          cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
                   1332:          cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
                   1333:        }
                   1334:     }
                   1335:   else
                   1336:     CC_STATUS_INIT;
                   1337:   if (cc_status.value2 != 0
                   1338:       && ADDRESS_REG_P (cc_status.value2)
                   1339:       && GET_MODE (cc_status.value2) == QImode)
                   1340:     CC_STATUS_INIT;
                   1341:   if (cc_status.value2 != 0
                   1342:       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
                   1343:     switch (GET_CODE (cc_status.value2))
                   1344:       {
                   1345:       case PLUS: case MINUS: case MULT:
                   1346:       case DIV: case UDIV: case MOD: case UMOD: case NEG:
                   1347:       case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT:
                   1348:       case ROTATE: case ROTATERT:
                   1349:        if (GET_MODE (cc_status.value2) != VOIDmode)
                   1350:          cc_status.flags |= CC_NO_OVERFLOW;
                   1351:        break;
                   1352:       case ZERO_EXTEND:
                   1353:        /* (SET r1 (ZERO_EXTEND r2)) on this machine
                   1354:           ends with a move insn moving r2 in r2's mode.
                   1355:           Thus, the cc's are set for r2.
                   1356:           This can set N bit spuriously. */
                   1357:        cc_status.flags |= CC_NOT_NEGATIVE; 
                   1358:       }
                   1359:   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
                   1360:       && cc_status.value2
                   1361:       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
                   1362:     cc_status.value2 = 0;
                   1363:   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
                   1364:        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
                   1365:       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
                   1366:           || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
                   1367:     cc_status.flags = CC_IN_68881;
                   1368: }
                   1369: 
                   1370: char *
                   1371: output_move_const_double (operands)
                   1372:      rtx *operands;
                   1373: {
                   1374: #ifdef SUPPORT_SUN_FPA
                   1375:   if (TARGET_FPA && FPA_REG_P (operands[0]))
                   1376:     {
                   1377:       int code = standard_sun_fpa_constant_p (operands[1]);
                   1378: 
                   1379:       if (code != 0)
                   1380:        {
                   1381:          static char buf[40];
                   1382: 
                   1383:          sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
                   1384:          return buf;
                   1385:        }
                   1386:       return "fpmove%.d %1,%0";
                   1387:     }
                   1388:   else
                   1389: #endif
                   1390:     {
                   1391:       int code = standard_68881_constant_p (operands[1]);
                   1392: 
                   1393:       if (code != 0)
                   1394:        {
                   1395:          static char buf[40];
                   1396: 
                   1397:          sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
                   1398:          return buf;
                   1399:        }
                   1400:       return "fmove%.d %1,%0";
                   1401:     }
                   1402: }
                   1403: 
                   1404: char *
                   1405: output_move_const_single (operands)
                   1406:      rtx *operands;
                   1407: {
                   1408: #ifdef SUPPORT_SUN_FPA
                   1409:   if (TARGET_FPA)
                   1410:     {
                   1411:       int code = standard_sun_fpa_constant_p (operands[1]);
                   1412: 
                   1413:       if (code != 0)
                   1414:        {
                   1415:          static char buf[40];
                   1416: 
                   1417:          sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
                   1418:          return buf;
                   1419:        }
                   1420:       return "fpmove%.s %1,%0";
                   1421:     }
                   1422:   else
                   1423: #endif /* defined SUPPORT_SUN_FPA */
                   1424:     {
                   1425:       int code = standard_68881_constant_p (operands[1]);
                   1426: 
                   1427:       if (code != 0)
                   1428:        {
                   1429:          static char buf[40];
                   1430: 
                   1431:          sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
                   1432:          return buf;
                   1433:        }
                   1434:       return "fmove%.s %f1,%0";
                   1435:     }
                   1436: }
                   1437: 
                   1438: /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
                   1439:    from the "fmovecr" instruction.
                   1440:    The value, anded with 0xff, gives the code to use in fmovecr
                   1441:    to get the desired constant.  */
                   1442: 
                   1443: /* This code has been fixed for cross-compilation. */
                   1444:   
                   1445: static int inited_68881_table = 0;
                   1446: 
                   1447: char *strings_68881[7] = {
                   1448:   "0.0",
                   1449:   "1.0",
                   1450:   "10.0",
                   1451:   "100.0",
                   1452:   "10000.0",
                   1453:   "1e8",
                   1454:   "1e16"
                   1455:   };
                   1456: 
                   1457: int codes_68881[7] = {
                   1458:   0x0f,
                   1459:   0x32,
                   1460:   0x33,
                   1461:   0x34,
                   1462:   0x35,
                   1463:   0x36,
                   1464:   0x37
                   1465:   };
                   1466: 
                   1467: REAL_VALUE_TYPE values_68881[7];
                   1468: 
                   1469: /* Set up values_68881 array by converting the decimal values
                   1470:    strings_68881 to binary.   */
                   1471: 
                   1472: void
                   1473: init_68881_table ()
                   1474: {
                   1475:   int i;
                   1476:   REAL_VALUE_TYPE r;
                   1477:   enum machine_mode mode;
                   1478: 
                   1479:   mode = DFmode;
                   1480:   for (i = 0; i < 7; i++)
                   1481:     {
                   1482:       if (i == 6)
                   1483:         mode = SFmode;
                   1484:       r = REAL_VALUE_ATOF (strings_68881[i], mode);
                   1485:       values_68881[i] = r;
                   1486:     }
                   1487:   inited_68881_table = 1;
                   1488: }
                   1489: 
                   1490: int
                   1491: standard_68881_constant_p (x)
                   1492:      rtx x;
                   1493: {
                   1494:   REAL_VALUE_TYPE r;
                   1495:   int i;
                   1496:   enum machine_mode mode;
                   1497: 
                   1498:   /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
                   1499:   if (TARGET_68040)
                   1500:     return 0;
                   1501: 
                   1502: #ifndef REAL_ARITHMETIC
                   1503: #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
                   1504:   if (! flag_pretend_float)
                   1505:     return 0;
                   1506: #endif
                   1507: #endif
                   1508: 
                   1509:   if (! inited_68881_table)
                   1510:     init_68881_table ();
                   1511: 
                   1512:   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   1513: 
                   1514:   for (i = 0; i < 6; i++)
                   1515:     {
                   1516:       if (REAL_VALUES_EQUAL (r, values_68881[i]))
                   1517:         return (codes_68881[i]);
                   1518:     }
                   1519:   
                   1520:   if (GET_MODE (x) == SFmode)
                   1521:     return 0;
                   1522: 
                   1523:   if (REAL_VALUES_EQUAL (r, values_68881[6]))
                   1524:     return (codes_68881[6]);
                   1525: 
                   1526:   /* larger powers of ten in the constants ram are not used
                   1527:      because they are not equal to a `double' C constant.  */
                   1528:   return 0;
                   1529: }
                   1530: 
                   1531: /* If X is a floating-point constant, return the logarithm of X base 2,
                   1532:    or 0 if X is not a power of 2.  */
                   1533: 
                   1534: int
                   1535: floating_exact_log2 (x)
                   1536:      rtx x;
                   1537: {
                   1538:   REAL_VALUE_TYPE r, r1;
                   1539:   int i;
                   1540: 
                   1541: #ifndef REAL_ARITHMETIC
                   1542: #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
                   1543:   if (! flag_pretend_float)
                   1544:     return 0;
                   1545: #endif
                   1546: #endif
                   1547: 
                   1548:   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   1549: 
                   1550:   if (REAL_VALUES_LESS (r, dconst0))
                   1551:     return 0;
                   1552: 
                   1553:   r1 = dconst1;
                   1554:   i = 0;
                   1555:   while (REAL_VALUES_LESS (r1, r))
                   1556:     {
                   1557:       r1 = REAL_VALUE_LDEXP (dconst1, i);
                   1558:       if (REAL_VALUES_EQUAL (r1, r))
                   1559:         return i;
                   1560:       i = i + 1;
                   1561:     }
                   1562:   return 0;
                   1563: }
                   1564: 
                   1565: #ifdef SUPPORT_SUN_FPA
                   1566: /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
                   1567:    from the Sun FPA's constant RAM.
                   1568:    The value returned, anded with 0x1ff, gives the code to use in fpmove
                   1569:    to get the desired constant. */
                   1570: 
                   1571: static int inited_FPA_table = 0;
                   1572: 
                   1573: char *strings_FPA[38] = {
                   1574: /* small rationals */
                   1575:   "0.0",
                   1576:   "1.0",
                   1577:   "0.5",
                   1578:   "-1.0",
                   1579:   "2.0",
                   1580:   "3.0",
                   1581:   "4.0",
                   1582:   "8.0",
                   1583:   "0.25",
                   1584:   "0.125",
                   1585:   "10.0",
                   1586:   "-0.5",
                   1587: /* Decimal equivalents of double precision values */
                   1588:   "2.718281828459045091", /* D_E */
                   1589:   "6.283185307179586477", /* 2 pi */
                   1590:   "3.141592653589793116", /* D_PI */
                   1591:   "1.570796326794896619", /* pi/2 */
                   1592:   "1.414213562373095145", /* D_SQRT2 */
                   1593:   "0.7071067811865475244", /* 1/sqrt(2) */
                   1594:   "-1.570796326794896619", /* -pi/2 */
                   1595:   "1.442695040888963387", /* D_LOG2ofE */
                   1596:   "3.321928024887362182", /* D_LOG2of10 */
                   1597:   "0.6931471805599452862", /* D_LOGEof2 */
                   1598:   "2.302585092994045901", /* D_LOGEof10 */
                   1599:   "0.3010299956639811980", /* D_LOG10of2 */
                   1600:   "0.4342944819032518167", /* D_LOG10ofE */
                   1601: /* Decimal equivalents of single precision values */
                   1602:   "2.718281745910644531", /* S_E */
                   1603:   "6.283185307179586477", /* 2 pi */
                   1604:   "3.141592741012573242", /* S_PI */
                   1605:   "1.570796326794896619", /* pi/2 */
                   1606:   "1.414213538169860840", /* S_SQRT2 */
                   1607:   "0.7071067811865475244", /* 1/sqrt(2) */
                   1608:   "-1.570796326794896619", /* -pi/2 */
                   1609:   "1.442695021629333496", /* S_LOG2ofE */
                   1610:   "3.321928024291992188", /* S_LOG2of10 */
                   1611:   "0.6931471824645996094", /* S_LOGEof2 */
                   1612:   "2.302585124969482442", /* S_LOGEof10 */
                   1613:   "0.3010300099849700928", /* S_LOG10of2 */
                   1614:   "0.4342944920063018799", /* S_LOG10ofE */
                   1615: };
                   1616: 
                   1617: 
                   1618: int codes_FPA[38] = {
                   1619: /* small rationals */
                   1620:   0x200,
                   1621:   0xe,
                   1622:   0xf,
                   1623:   0x10,
                   1624:   0x11,
                   1625:   0xb1,
                   1626:   0x12,
                   1627:   0x13,
                   1628:   0x15,
                   1629:   0x16,
                   1630:   0x17,
                   1631:   0x2e,
                   1632: /* double precision */
                   1633:   0x8,
                   1634:   0x9,
                   1635:   0xa,
                   1636:   0xb,
                   1637:   0xc,
                   1638:   0xd,
                   1639:   0x27,
                   1640:   0x28,
                   1641:   0x29,
                   1642:   0x2a,
                   1643:   0x2b,
                   1644:   0x2c,
                   1645:   0x2d,
                   1646: /* single precision */
                   1647:   0x8,
                   1648:   0x9,
                   1649:   0xa,
                   1650:   0xb,
                   1651:   0xc,
                   1652:   0xd,
                   1653:   0x27,
                   1654:   0x28,
                   1655:   0x29,
                   1656:   0x2a,
                   1657:   0x2b,
                   1658:   0x2c,
                   1659:   0x2d
                   1660:   };
                   1661: 
                   1662: REAL_VALUE_TYPE values_FPA[38];
                   1663: 
                   1664: /* This code has been fixed for cross-compilation. */
                   1665: 
                   1666: void
                   1667: init_FPA_table ()
                   1668: {
                   1669:   enum machine_mode mode;
                   1670:   int i;
                   1671:   REAL_VALUE_TYPE r;
                   1672: 
                   1673:   mode = DFmode;
                   1674:   for (i = 0; i < 38; i++)
                   1675:     {
                   1676:       if (i == 25)
                   1677:         mode = SFmode;
                   1678:       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
                   1679:       values_FPA[i] = r;
                   1680:     }
                   1681:   inited_FPA_table = 1;
                   1682: }
                   1683: 
                   1684: 
                   1685: int
                   1686: standard_sun_fpa_constant_p (x)
                   1687:      rtx x;
                   1688: {
                   1689:   REAL_VALUE_TYPE r;
                   1690:   int i;
                   1691: 
                   1692: #ifndef REAL_ARITHMETIC
                   1693: #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
                   1694:   if (! flag_pretend_float)
                   1695:     return 0;
                   1696: #endif
                   1697: #endif
                   1698: 
                   1699:   if (! inited_FPA_table)
                   1700:     init_FPA_table ();
                   1701: 
                   1702:   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   1703: 
                   1704:   for (i=0; i<12; i++)
                   1705:     {
                   1706:       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
                   1707:         return (codes_FPA[i]);
                   1708:     }
                   1709: 
                   1710:   if (GET_MODE (x) == SFmode)
                   1711:     {
                   1712:       for (i=25; i<38; i++)
                   1713:         {
                   1714:           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
                   1715:             return (codes_FPA[i]);
                   1716:         }
                   1717:     }
                   1718:   else
                   1719:     {
                   1720:       for (i=12; i<25; i++)
                   1721:         {
                   1722:           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
                   1723:             return (codes_FPA[i]);
                   1724:         }
                   1725:     }
                   1726:   return 0x0;
                   1727: }
                   1728: #endif /* define SUPPORT_SUN_FPA */
                   1729: 
                   1730: /* A C compound statement to output to stdio stream STREAM the
                   1731:    assembler syntax for an instruction operand X.  X is an RTL
                   1732:    expression.
                   1733: 
                   1734:    CODE is a value that can be used to specify one of several ways
                   1735:    of printing the operand.  It is used when identical operands
                   1736:    must be printed differently depending on the context.  CODE
                   1737:    comes from the `%' specification that was used to request
                   1738:    printing of the operand.  If the specification was just `%DIGIT'
                   1739:    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
                   1740:    is the ASCII code for LTR.
                   1741: 
                   1742:    If X is a register, this macro should print the register's name.
                   1743:    The names can be found in an array `reg_names' whose type is
                   1744:    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
                   1745: 
                   1746:    When the machine description has a specification `%PUNCT' (a `%'
                   1747:    followed by a punctuation character), this macro is called with
                   1748:    a null pointer for X and the punctuation character for CODE.
                   1749: 
                   1750:    The m68k specific codes are:
                   1751: 
                   1752:    '.' for dot needed in Motorola-style opcode names.
                   1753:    '-' for an operand pushing on the stack:
                   1754:        sp@-, -(sp) or -(%sp) depending on the style of syntax.
                   1755:    '+' for an operand pushing on the stack:
                   1756:        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
                   1757:    '@' for a reference to the top word on the stack:
                   1758:        sp@, (sp) or (%sp) depending on the style of syntax.
                   1759:    '#' for an immediate operand prefix (# in MIT and Motorola syntax
                   1760:        but & in SGS syntax).
                   1761:    '!' for the cc register (used in an `and to cc' insn).
                   1762:    '$' for the letter `s' in an op code, but only on the 68040.
                   1763:    '&' for the letter `d' in an op code, but only on the 68040.
                   1764:    '/' for register prefix needed by longlong.h.
                   1765: 
                   1766:    'b' for byte insn (no effect, on the Sun; this is for the ISI).
                   1767:    'd' to force memory addressing to be absolute, not relative.
                   1768:    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
                   1769:    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
                   1770:        than directly).  Second part of 'y' below.
                   1771:    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
                   1772:        or print pair of registers as rx:ry.
                   1773:    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
                   1774:        CONST_DOUBLE's as SunFPA constant RAM registers if
                   1775:        possible, so it should not be used except for the SunFPA.
                   1776: 
                   1777:    */
                   1778: 
                   1779: void
                   1780: print_operand (file, op, letter)
                   1781:      FILE *file;               /* file to write to */
                   1782:      rtx op;                   /* operand to print */
                   1783:      int letter;               /* %<letter> or 0 */
                   1784: {
                   1785:   int i;
                   1786: 
                   1787:   if (letter == '.')
                   1788:     {
                   1789: #ifdef MOTOROLA
                   1790:       asm_fprintf (file, ".");
                   1791: #endif
                   1792:     }
                   1793:   else if (letter == '#')
                   1794:     {
                   1795:       asm_fprintf (file, "%0I");
                   1796:     }
                   1797:   else if (letter == '-')
                   1798:     {
                   1799: #ifdef MOTOROLA
                   1800:       asm_fprintf (file, "-(%Rsp)");
                   1801: #else
                   1802:       asm_fprintf (file, "%Rsp@-");
                   1803: #endif
                   1804:     }
                   1805:   else if (letter == '+')
                   1806:     {
                   1807: #ifdef MOTOROLA
                   1808:       asm_fprintf (file, "(%Rsp)+");
                   1809: #else
                   1810:       asm_fprintf (file, "%Rsp@+");
                   1811: #endif
                   1812:     }
                   1813:   else if (letter == '@')
                   1814:     {
                   1815: #ifdef MOTOROLA
                   1816:       asm_fprintf (file, "(%Rsp)");
                   1817: #else
                   1818:       asm_fprintf (file, "%Rsp@");
                   1819: #endif
                   1820:     }
                   1821:   else if (letter == '!')
                   1822:     {
                   1823:       asm_fprintf (file, "%Rfpcr");
                   1824:     }
                   1825:   else if (letter == '$')
                   1826:     {
                   1827:       if (TARGET_68040_ONLY)
                   1828:        {
                   1829:          fprintf (file, "s");
                   1830:        }
                   1831:     }
                   1832:   else if (letter == '&')
                   1833:     {
                   1834:       if (TARGET_68040_ONLY)
                   1835:        {
                   1836:          fprintf (file, "d");
                   1837:        }
                   1838:     }
                   1839:   else if (letter == '/')
                   1840:     {
                   1841:       asm_fprintf (file, "%R");
                   1842:     }
                   1843:   else if (GET_CODE (op) == REG)
                   1844:     {
                   1845:       if (REGNO (op) < 16
                   1846:          && (letter == 'y' || letter == 'x')
                   1847:          && GET_MODE (op) == DFmode)
                   1848:        {
                   1849:          fprintf (file, "%s:%s", reg_names[REGNO (op)],
                   1850:                   reg_names[REGNO (op)+1]);
                   1851:        }
                   1852:       else
                   1853:        {
                   1854:          fprintf (file, "%s", reg_names[REGNO (op)]);
                   1855:        }
                   1856:     }
                   1857:   else if (GET_CODE (op) == MEM)
                   1858:     {
                   1859:       output_address (XEXP (op, 0));
                   1860:       if (letter == 'd' && ! TARGET_68020
                   1861:          && CONSTANT_ADDRESS_P (XEXP (op, 0))
                   1862:          && !(GET_CODE (XEXP (op, 0)) == CONST_INT
                   1863:               && INTVAL (XEXP (op, 0)) < 0x8000
                   1864:               && INTVAL (XEXP (op, 0)) >= -0x8000))
                   1865:        {
                   1866:          fprintf (file, ":l");
                   1867:        }
                   1868:     }
                   1869: #ifdef SUPPORT_SUN_FPA
                   1870:   else if ((letter == 'y' || letter == 'w')
                   1871:           && GET_CODE (op) == CONST_DOUBLE
                   1872:           && (i = standard_sun_fpa_constant_p (op)))
                   1873:     {
                   1874:       fprintf (file, "%%%d", i & 0x1ff);
                   1875:     }
                   1876: #endif
                   1877:   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
                   1878:     {
                   1879:       REAL_VALUE_TYPE r;
                   1880:       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
                   1881:       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
                   1882:     }
                   1883:   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
                   1884:     {
                   1885:       REAL_VALUE_TYPE r;
                   1886:       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
                   1887:       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
                   1888:     }
                   1889:   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
                   1890:     {
                   1891:       REAL_VALUE_TYPE r;
                   1892:       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
                   1893:       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
                   1894:     }
                   1895:   else
                   1896:     {
                   1897:       asm_fprintf (file, "%0I"); output_addr_const (file, op);
                   1898:     }
                   1899: }
                   1900: 
                   1901: 
                   1902: /* A C compound statement to output to stdio stream STREAM the
                   1903:    assembler syntax for an instruction operand that is a memory
                   1904:    reference whose address is ADDR.  ADDR is an RTL expression.
                   1905: 
                   1906:    Note that this contains a kludge that knows that the only reason
                   1907:    we have an address (plus (label_ref...) (reg...)) when not generating
                   1908:    PIC code is in the insn before a tablejump, and we know that m68k.md
                   1909:    generates a label LInnn: on such an insn.
                   1910: 
                   1911:    It is possible for PIC to generate a (plus (label_ref...) (reg...))
                   1912:    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
                   1913: 
                   1914:    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
                   1915:    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
                   1916:    we want.  This difference can be accommodated by using an assembler
                   1917:    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
                   1918:    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
                   1919:    macro.  See m68k/sgs.h for an example; for versions without the bug.
                   1920: 
                   1921:    They also do not like things like "pea 1.w", so we simple leave off
                   1922:    the .w on small constants. 
                   1923: 
                   1924:    This routine is responsible for distinguishing between -fpic and -fPIC 
                   1925:    style relocations in an address.  When generating -fpic code the
                   1926:    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
                   1927:    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
                   1928: 
                   1929: void
                   1930: print_operand_address (file, addr)
                   1931:      FILE *file;
                   1932:      rtx addr;
                   1933: {
                   1934:   register rtx reg1, reg2, breg, ireg;
                   1935:   rtx offset;
                   1936: 
                   1937:   switch (GET_CODE (addr))
                   1938:     {
                   1939:       case REG:
                   1940: #ifdef MOTOROLA
                   1941:        fprintf (file, "(%s)", reg_names[REGNO (addr)]);
                   1942: #else
                   1943:        fprintf (file, "%s@", reg_names[REGNO (addr)]);
                   1944: #endif
                   1945:        break;
                   1946:       case PRE_DEC:
                   1947: #ifdef MOTOROLA
                   1948:        fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
                   1949: #else
                   1950:        fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
                   1951: #endif
                   1952:        break;
                   1953:       case POST_INC:
                   1954: #ifdef MOTOROLA
                   1955:        fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
                   1956: #else
                   1957:        fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
                   1958: #endif
                   1959:        break;
                   1960:       case PLUS:
                   1961:        reg1 = reg2 = ireg = breg = offset = 0;
                   1962:        if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
                   1963:          {
                   1964:            offset = XEXP (addr, 0);
                   1965:            addr = XEXP (addr, 1);
                   1966:          }
                   1967:        else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
                   1968:          {
                   1969:            offset = XEXP (addr, 1);
                   1970:            addr = XEXP (addr, 0);
                   1971:          }
                   1972:        if (GET_CODE (addr) != PLUS)
                   1973:          {
                   1974:            ;
                   1975:          }
                   1976:        else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
                   1977:          {
                   1978:            reg1 = XEXP (addr, 0);
                   1979:            addr = XEXP (addr, 1);
                   1980:          }
                   1981:        else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
                   1982:          {
                   1983:            reg1 = XEXP (addr, 1);
                   1984:            addr = XEXP (addr, 0);
                   1985:          }
                   1986:        else if (GET_CODE (XEXP (addr, 0)) == MULT)
                   1987:          {
                   1988:            reg1 = XEXP (addr, 0);
                   1989:            addr = XEXP (addr, 1);
                   1990:          }
                   1991:        else if (GET_CODE (XEXP (addr, 1)) == MULT)
                   1992:          {
                   1993:            reg1 = XEXP (addr, 1);
                   1994:            addr = XEXP (addr, 0);
                   1995:          }
                   1996:        else if (GET_CODE (XEXP (addr, 0)) == REG)
                   1997:          {
                   1998:            reg1 = XEXP (addr, 0);
                   1999:            addr = XEXP (addr, 1);
                   2000:          }
                   2001:        else if (GET_CODE (XEXP (addr, 1)) == REG)
                   2002:          {
                   2003:            reg1 = XEXP (addr, 1);
                   2004:            addr = XEXP (addr, 0);
                   2005:          }
                   2006:        if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
                   2007:            || GET_CODE (addr) == SIGN_EXTEND)
                   2008:          {
                   2009:            if (reg1 == 0)
                   2010:              {
                   2011:                reg1 = addr;
                   2012:              }
                   2013:            else
                   2014:              {
                   2015:                reg2 = addr;
                   2016:              }
                   2017:            addr = 0;
                   2018:          }
                   2019: #if 0  /* for OLD_INDEXING */
                   2020:        else if (GET_CODE (addr) == PLUS)
                   2021:          {
                   2022:            if (GET_CODE (XEXP (addr, 0)) == REG)
                   2023:              {
                   2024:                reg2 = XEXP (addr, 0);
                   2025:                addr = XEXP (addr, 1);
                   2026:              }
                   2027:            else if (GET_CODE (XEXP (addr, 1)) == REG)
                   2028:              {
                   2029:                reg2 = XEXP (addr, 1);
                   2030:                addr = XEXP (addr, 0);
                   2031:              }
                   2032:          }
                   2033: #endif
                   2034:        if (offset != 0)
                   2035:          {
                   2036:            if (addr != 0)
                   2037:              {
                   2038:                abort ();
                   2039:              }
                   2040:            addr = offset;
                   2041:          }
                   2042:        if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
                   2043:                      || GET_CODE (reg1) == MULT))
                   2044:            || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
                   2045:          {
                   2046:            breg = reg2;
                   2047:            ireg = reg1;
                   2048:          }
                   2049:        else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
                   2050:          {
                   2051:            breg = reg1;
                   2052:            ireg = reg2;
                   2053:          }
                   2054:        if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
                   2055:            && ! (flag_pic && ireg == pic_offset_table_rtx))
                   2056:          {
                   2057:            int scale = 1;
                   2058:            if (GET_CODE (ireg) == MULT)
                   2059:              {
                   2060:                scale = INTVAL (XEXP (ireg, 1));
                   2061:                ireg = XEXP (ireg, 0);
                   2062:              }
                   2063:            if (GET_CODE (ireg) == SIGN_EXTEND)
                   2064:              {
                   2065: #ifdef MOTOROLA
                   2066: #ifdef SGS
                   2067:                asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
                   2068:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2069:                             reg_names[REGNO (XEXP (ireg, 0))]);
                   2070: #else
                   2071:                asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w",
                   2072:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2073:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2074:                             reg_names[REGNO (XEXP (ireg, 0))]);
                   2075: #endif
                   2076: #else
                   2077:                asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
                   2078:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2079:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2080:                             reg_names[REGNO (XEXP (ireg, 0))]);
                   2081: #endif
                   2082:              }
                   2083:            else
                   2084:              {
                   2085: #ifdef MOTOROLA
                   2086: #ifdef SGS
                   2087:                asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
                   2088:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2089:                             reg_names[REGNO (ireg)]);
                   2090: #else
                   2091:                asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
                   2092:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2093:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2094:                             reg_names[REGNO (ireg)]);
                   2095: #endif
                   2096: #else
                   2097:                asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
                   2098:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2099:                             CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2100:                             reg_names[REGNO (ireg)]);
                   2101: #endif
                   2102:              }
                   2103:            if (scale != 1)
                   2104:              {
                   2105: #ifdef MOTOROLA
                   2106:                fprintf (file, "*%d", scale);
                   2107: #else
                   2108:                fprintf (file, ":%d", scale);
                   2109: #endif
                   2110:              }
                   2111:            putc (')', file);
                   2112:            break;
                   2113:          }
                   2114:        if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
                   2115:            && ! (flag_pic && breg == pic_offset_table_rtx))
                   2116:          {
                   2117: #ifdef MOTOROLA
                   2118: #ifdef SGS
                   2119:            asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
                   2120:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2121:                         reg_names[REGNO (breg)]);
                   2122: #else
                   2123:            asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
                   2124:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2125:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2126:                         reg_names[REGNO (breg)]);
                   2127: #endif
                   2128: #else
                   2129:            asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
                   2130:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2131:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2132:                         reg_names[REGNO (breg)]);
                   2133: #endif
                   2134:            putc (')', file);
                   2135:            break;
                   2136:          }
                   2137:        if (ireg != 0 || breg != 0)
                   2138:          {
                   2139:            int scale = 1;
                   2140:            if (breg == 0)
                   2141:              {
                   2142:                abort ();
                   2143:              }
                   2144:            if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
                   2145:              {
                   2146:                abort ();
                   2147:              }
                   2148: #ifdef MOTOROLA
                   2149:            if (addr != 0)
                   2150:              {
                   2151:                output_addr_const (file, addr);
                   2152:                if (flag_pic && (breg == pic_offset_table_rtx))
                   2153:                  fprintf (file, "@GOT");
                   2154:              }
                   2155:            fprintf (file, "(%s", reg_names[REGNO (breg)]);
                   2156:            if (ireg != 0)
                   2157:              {
                   2158:                putc (',', file);
                   2159:              }
                   2160: #else
                   2161:            fprintf (file, "%s@(", reg_names[REGNO (breg)]);
                   2162:            if (addr != 0)
                   2163:              {
                   2164:                output_addr_const (file, addr);
                   2165:                if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
                   2166:                  fprintf (file, ":w");
                   2167:                if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
                   2168:                  fprintf (file, ":l");
                   2169:              }
                   2170:            if (addr != 0 && ireg != 0)
                   2171:              {
                   2172:                putc (',', file);
                   2173:              }
                   2174: #endif
                   2175:            if (ireg != 0 && GET_CODE (ireg) == MULT)
                   2176:              {
                   2177:                scale = INTVAL (XEXP (ireg, 1));
                   2178:                ireg = XEXP (ireg, 0);
                   2179:              }
                   2180:            if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
                   2181:              {
                   2182: #ifdef MOTOROLA
                   2183:                fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
                   2184: #else
                   2185:                fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
                   2186: #endif
                   2187:              }
                   2188:            else if (ireg != 0)
                   2189:              {
                   2190: #ifdef MOTOROLA
                   2191:                fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
                   2192: #else
                   2193:                fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
                   2194: #endif
                   2195:              }
                   2196:            if (scale != 1)
                   2197:              {
                   2198: #ifdef MOTOROLA
                   2199:                fprintf (file, "*%d", scale);
                   2200: #else
                   2201:                fprintf (file, ":%d", scale);
                   2202: #endif
                   2203:              }
                   2204:            putc (')', file);
                   2205:            break;
                   2206:          }
                   2207:        else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
                   2208:                 && ! (flag_pic && reg1 == pic_offset_table_rtx))       
                   2209:          {
                   2210: #ifdef MOTOROLA
                   2211: #ifdef SGS
                   2212:            asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
                   2213:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2214:                         reg_names[REGNO (reg1)]);
                   2215: #else
                   2216:            asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)",
                   2217:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2218:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2219:                         reg_names[REGNO (reg1)]);
                   2220: #endif
                   2221: #else
                   2222:            asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
                   2223:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2224:                         CODE_LABEL_NUMBER (XEXP (addr, 0)),
                   2225:                         reg_names[REGNO (reg1)]);
                   2226: #endif
                   2227:            break;
                   2228:          }
                   2229:        /* FALL-THROUGH (is this really what we want? */
                   2230:       default:
                   2231:         if (GET_CODE (addr) == CONST_INT
                   2232:            && INTVAL (addr) < 0x8000
                   2233:            && INTVAL (addr) >= -0x8000)
                   2234:          {
                   2235: #ifdef MOTOROLA
                   2236: #ifdef SGS
                   2237:            /* Many SGS assemblers croak on size specifiers for constants. */
                   2238:            fprintf (file, "%d", INTVAL (addr));
                   2239: #else
                   2240:            fprintf (file, "%d.w", INTVAL (addr));
                   2241: #endif
                   2242: #else
                   2243:            fprintf (file, "%d:w", INTVAL (addr));
                   2244: #endif
                   2245:          }
                   2246:        else
                   2247:          {
                   2248:            output_addr_const (file, addr);
                   2249:          }
                   2250:        break;
                   2251:     }
                   2252: }
                   2253: 
                   2254: /* Check for cases where a clr insns can be omitted from code using
                   2255:    strict_low_part sets.  For example, the second clrl here is not needed:
                   2256:    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
                   2257: 
                   2258:    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
                   2259:    insn we are checking for redundancy.  TARGET is the register set by the
                   2260:    clear insn.  */
                   2261: 
                   2262: int
                   2263: strict_low_part_peephole_ok (mode, first_insn, target)
                   2264:      enum machine_mode mode;
                   2265:      rtx first_insn;
                   2266:      rtx target;
                   2267: {
                   2268:   rtx p;
                   2269: 
                   2270:   p = prev_nonnote_insn (first_insn);
                   2271: 
                   2272:   while (p)
                   2273:     {
                   2274:       /* If it isn't an insn, then give up.  */
                   2275:       if (GET_CODE (p) != INSN)
                   2276:        return 0;
                   2277: 
                   2278:       if (reg_set_p (target, p))
                   2279:        {
                   2280:          rtx set = single_set (p);
                   2281:          rtx dest;
                   2282: 
                   2283:          /* If it isn't an easy to recognize insn, then give up.  */
                   2284:          if (! set)
                   2285:            return 0;
                   2286: 
                   2287:          dest = SET_DEST (set);
                   2288: 
                   2289:          /* If this sets the entire target register to zero, then our
                   2290:             first_insn is redundant.  */
                   2291:          if (rtx_equal_p (dest, target)
                   2292:              && SET_SRC (set) == const0_rtx)
                   2293:            return 1;
                   2294:          else if (GET_CODE (dest) == STRICT_LOW_PART
                   2295:                   && GET_CODE (XEXP (dest, 0)) == REG
                   2296:                   && REGNO (XEXP (dest, 0)) == REGNO (target)
                   2297:                   && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
                   2298:                       <= GET_MODE_SIZE (mode)))
                   2299:            /* This is a strict low part set which modifies less than
                   2300:               we are using, so it is safe.  */
                   2301:            ;
                   2302:          else
                   2303:            return 0;
                   2304:        }
                   2305: 
                   2306:       p = prev_nonnote_insn (p);
                   2307: 
                   2308:     }
                   2309: 
                   2310:   return 0;
                   2311: }

unix.superglobalmegacorp.com

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