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

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

unix.superglobalmegacorp.com

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