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

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

unix.superglobalmegacorp.com

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