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

1.1       root        1: /* Subroutines used for code generation on ROMP.
                      2:    Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
                      3:    Contributed by Richard Kenner ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.3 ! root       19: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
1.1       root       21: 
                     22: 
                     23: #include <stdio.h>
                     24: #include "config.h"
                     25: #include "rtl.h"
                     26: #include "regs.h"
                     27: #include "hard-reg-set.h"
                     28: #include "real.h"
                     29: #include "insn-config.h"
                     30: #include "conditions.h"
                     31: #include "insn-flags.h"
                     32: #include "output.h"
                     33: #include "insn-attr.h"
                     34: #include "flags.h"
                     35: #include "recog.h"
                     36: #include "expr.h"
                     37: #include "obstack.h"
                     38: #include "tree.h"
                     39: 
                     40: #define min(A,B)       ((A) < (B) ? (A) : (B))
                     41: #define max(A,B)       ((A) > (B) ? (A) : (B))
                     42: 
                     43: static int unsigned_comparisons_p ();
                     44: static void output_loadsave_fpregs ();
                     45: static void output_fpops ();
                     46: static void init_fpops ();
                     47: 
                     48: /* Return 1 if the insn using CC0 set by INSN does not contain
                     49:    any unsigned tests applied to the condition codes.
                     50: 
                     51:    Based on `next_insn_tests_no_inequality' in recog.c.  */
                     52: 
                     53: int
                     54: next_insn_tests_no_unsigned (insn)
                     55:      rtx insn;
                     56: {
                     57:   register rtx next = next_cc0_user (insn);
                     58: 
                     59:   if (next == 0)
                     60:     {
                     61:       if (find_reg_note (insn, REG_UNUSED, cc0_rtx))
                     62:        return 1;
                     63:       else
                     64:        abort ();
                     65:     }
                     66: 
                     67:   return ((GET_CODE (next) == JUMP_INSN
                     68:           || GET_CODE (next) == INSN
                     69:           || GET_CODE (next) == CALL_INSN)
                     70:          && ! unsigned_comparisons_p (PATTERN (next)));
                     71: }
                     72: 
                     73: static int
                     74: unsigned_comparisons_p (x)
                     75:      rtx x;
                     76: {
                     77:   register char *fmt;
                     78:   register int len, i;
                     79:   register enum rtx_code code = GET_CODE (x);
                     80: 
                     81:   switch (code)
                     82:     {
                     83:     case REG:
                     84:     case PC:
                     85:     case CC0:
                     86:     case CONST_INT:
                     87:     case CONST_DOUBLE:
                     88:     case CONST:
                     89:     case LABEL_REF:
                     90:     case SYMBOL_REF:
                     91:       return 0;
                     92: 
                     93:     case LTU:
                     94:     case GTU:
                     95:     case LEU:
                     96:     case GEU:
                     97:       return (XEXP (x, 0) == cc0_rtx || XEXP (x, 1) == cc0_rtx);
                     98:     }
                     99: 
                    100:   len = GET_RTX_LENGTH (code);
                    101:   fmt = GET_RTX_FORMAT (code);
                    102: 
                    103:   for (i = 0; i < len; i++)
                    104:     {
                    105:       if (fmt[i] == 'e')
                    106:        {
                    107:          if (unsigned_comparisons_p (XEXP (x, i)))
                    108:            return 1;
                    109:        }
                    110:       else if (fmt[i] == 'E')
                    111:        {
                    112:          register int j;
                    113:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                    114:            if (unsigned_comparisons_p (XVECEXP (x, i, j)))
                    115:              return 1;
                    116:        }
                    117:     }
                    118:            
                    119:   return 0;
                    120: }
                    121: 
                    122: /* Update the condition code from the insn.  Look mostly at the first
                    123:    byte of the machine-specific insn description information.
                    124: 
                    125:    cc_state.value[12] refer to two possible values that might correspond
                    126:    to the CC.  We only store register values.  */
                    127: 
                    128: update_cc (body, insn)
                    129:     rtx body;
                    130:     rtx insn;
                    131: {
                    132:   switch (get_attr_cc (insn))
                    133:     {
                    134:     case CC_NONE:
                    135:       /* Insn does not affect the CC at all.  */
                    136:       break;
                    137: 
                    138:     case CC_CHANGE0:
                    139:       /* Insn doesn't affect the CC but does modify operand[0], known to be
                    140:         a register.  */
                    141:       if (cc_status.value1 != 0
                    142:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
                    143:        cc_status.value1 = 0;
                    144: 
                    145:       if (cc_status.value2 != 0
                    146:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
                    147:        cc_status.value2 = 0;
                    148: 
                    149:       break;
                    150: 
                    151:     case CC_COPY1TO0:
                    152:       /* Insn copies operand[1] to operand[0], both registers, but doesn't
                    153:          affect the CC.  */
                    154:       if (cc_status.value1 != 0
                    155:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
                    156:        cc_status.value1 = 0;
                    157: 
                    158:       if (cc_status.value2 != 0
                    159:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
                    160:        cc_status.value2 = 0;
                    161: 
                    162:       if (cc_status.value1 != 0
                    163:          && rtx_equal_p (cc_status.value1, recog_operand[1]))
                    164:        cc_status.value2 = recog_operand[0];
                    165: 
                    166:       if (cc_status.value2 != 0
                    167:          && rtx_equal_p (cc_status.value2, recog_operand[1]))
                    168:        cc_status.value1 = recog_operand[0];
                    169: 
                    170:       break;
                    171: 
                    172:     case CC_CLOBBER:
                    173:       /* Insn clobbers CC. */
                    174:       CC_STATUS_INIT;
                    175:       break;
                    176: 
                    177:     case CC_SETS:
                    178:       /* Insn sets CC to recog_operand[0], but overflow is impossible.  */
                    179:       CC_STATUS_INIT;
                    180:       cc_status.flags |= CC_NO_OVERFLOW;
                    181:       cc_status.value1 = recog_operand[0];
                    182:       break;
                    183: 
                    184:    case CC_COMPARE:
                    185:       /* Insn is a compare which sets the CC fully.  Update CC_STATUS for this
                    186:         compare and mark whether the test will be signed or unsigned.  */
                    187:       {
                    188:        register rtx p = PATTERN (insn);
                    189: 
                    190:        CC_STATUS_INIT;
                    191: 
                    192:        if (GET_CODE (p) == PARALLEL)
                    193:          p = XVECEXP (p, 0, 0);
                    194:        cc_status.value1 = SET_SRC (p);
                    195: 
                    196:        if (GET_CODE (SET_SRC (p)) == REG)
                    197:          cc_status.flags |= CC_NO_OVERFLOW;
                    198:        if (! next_insn_tests_no_unsigned (insn))
                    199:          cc_status.flags |= CC_UNSIGNED;
                    200:       }
                    201:       break;
                    202: 
                    203:     case CC_TBIT:
                    204:       /* Insn sets T bit if result is non-zero.  Next insn must be branch. */
                    205:       CC_STATUS_INIT;
                    206:       cc_status.flags = CC_IN_TB | CC_NOT_NEGATIVE;
                    207:       break;
                    208: 
                    209:     default:
                    210:       abort ();
                    211:    }
                    212: }
                    213: 
                    214: /* Return 1 if a previous compare needs to be re-issued.  This will happen
                    215:    if two compares tested the same objects, but one was signed and the
                    216:    other unsigned.  OP is the comparison operation being performed.  */
                    217: 
                    218: int
                    219: restore_compare_p (op)
                    220:      rtx op;
                    221: {
                    222:   enum rtx_code code = GET_CODE (op);
                    223: 
                    224:   return (((code == GEU || code == LEU || code == GTU || code == LTU)
                    225:           && ! (cc_status.flags & CC_UNSIGNED))
                    226:          || ((code == GE || code == LE || code == GT || code == LT)
                    227:              && (cc_status.flags & CC_UNSIGNED)));
                    228: }
                    229: 
                    230: /*  Generate the (long) string corresponding to an inline multiply insn.
                    231:     Note that `r10' does not refer to the register r10, but rather to the
                    232:     SCR used as the MQ.  */
                    233: char *
                    234: output_in_line_mul ()
                    235: {
                    236:   static char insns[200];
                    237:   int i;
                    238: 
                    239:   strcpy (insns, "s %0,%0\n");
                    240:   strcat (insns, "\tmts r10,%1\n");
                    241:   for (i = 0; i < 16; i++)
                    242:     strcat (insns, "\tm %0,%2\n");
                    243:   strcat (insns, "\tmfs r10,%0");
                    244: 
                    245:   return insns;
                    246: }
                    247: 
                    248: /* Returns 1 if OP is a memory reference with an offset from a register within
                    249:    the range specified.  The offset must also be a multiple of the size of the
                    250:    mode.  */
                    251: 
                    252: static int
                    253: memory_offset_in_range_p (op, mode, low, high)
                    254:      register rtx op;
                    255:      enum machine_mode mode;
                    256:      int low, high;
                    257: {
                    258:   int offset = 0;
                    259: 
                    260:   if (! memory_operand (op, mode))
                    261:     return 0;
                    262: 
                    263:   while (GET_CODE (op) == SUBREG)
                    264:     {
                    265:       offset += SUBREG_WORD (op) * UNITS_PER_WORD;
                    266: #if BYTES_BIG_ENDIAN
                    267:       offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
                    268:                 - min (UNITS_PER_WORD,
                    269:                        GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))));
                    270: #endif
                    271:       op = SUBREG_REG (op);
                    272:     }
                    273: 
                    274:   /* We must now have either (mem (reg (x)), (mem (plus (reg (x)) (c))),
                    275:      or a constant pool address.  */
                    276:   if (GET_CODE (op) != MEM)
                    277:     abort ();
                    278: 
                    279:   /* Now use the actual mode and get the address.  */
                    280:   mode = GET_MODE (op);
                    281:   op = XEXP (op, 0);
                    282:   if (GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
                    283:     offset = get_pool_offset (op) + 12;
                    284:   else if (GET_CODE (op) == PLUS)
                    285:     {
                    286:       if (GET_CODE (XEXP (op, 1)) != CONST_INT
                    287:          || ! register_operand (XEXP (op, 0), Pmode))
                    288:        return 0;
                    289: 
                    290:       offset += INTVAL (XEXP (op, 1));
                    291:     }
                    292: 
                    293:   else if (! register_operand (op, Pmode))
                    294:     return 0;
                    295: 
                    296:   return (offset >= low && offset <= high
                    297:          && (offset % GET_MODE_SIZE (mode) == 0));
                    298: }
                    299: 
                    300: /* Return 1 if OP is a valid operand for a memory reference insn that can
                    301:    only reference indirect through a register.   */
                    302: 
                    303: int
                    304: zero_memory_operand (op, mode)
                    305:      rtx op;
                    306:      enum machine_mode mode;
                    307: {
                    308:   return memory_offset_in_range_p (op, mode, 0, 0);
                    309: }
                    310: 
                    311: /* Return 1 if OP is a valid operand for a `short' memory reference insn. */
                    312: 
                    313: int
                    314: short_memory_operand (op, mode)
                    315:      rtx op;
                    316:      enum machine_mode mode;
                    317: {
                    318:   if (mode == VOIDmode)
                    319:     mode = GET_MODE (op);
                    320: 
                    321:   return memory_offset_in_range_p (op, mode, 0,
                    322:                                   15 * min (UNITS_PER_WORD,
                    323:                                             GET_MODE_SIZE (mode)));
                    324: }
                    325: 
                    326: /* Returns 1 if OP is a memory reference involving a symbolic constant
                    327:    that is not in the constant pool. */
                    328: 
                    329: int
                    330: symbolic_memory_operand (op, mode)
                    331:      register rtx op;
                    332:      enum machine_mode mode;
                    333: {
                    334:   if (! memory_operand (op, mode))
                    335:     return 0;
                    336: 
                    337:   while (GET_CODE (op) == SUBREG)
                    338:     op = SUBREG_REG (op);
                    339: 
                    340:   if (GET_CODE (op) != MEM)
                    341:     abort ();
                    342: 
                    343:   op = XEXP (op, 0);
                    344:   if (constant_pool_address_operand (op, VOIDmode))
                    345:     return 0;
                    346:   else
                    347:     return romp_symbolic_operand (op, Pmode)
                    348:       || (GET_CODE (op) == PLUS && register_operand (XEXP (op, 0), Pmode)
                    349:          && romp_symbolic_operand (XEXP (op, 1), Pmode));
                    350: }
                    351: 
                    352: 
                    353: /* Returns 1 if OP is a constant pool reference to the current function.  */
                    354: 
                    355: int
                    356: current_function_operand (op, mode)
                    357:      rtx op;
                    358:      enum machine_mode mode;
                    359: {
                    360:   if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
                    361:       ||  ! CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
                    362:     return 0;
                    363: 
                    364:   op = get_pool_constant (XEXP (op, 0));
                    365:   return (GET_CODE (op) == SYMBOL_REF
                    366:          && ! strcmp (current_function_name, XSTR (op, 0)));
                    367: }
                    368: 
                    369: /* Return non-zero if this function is known to have a null epilogue.  */
                    370: 
                    371: int
                    372: null_epilogue ()
                    373: {
                    374:   return (reload_completed
                    375:          && first_reg_to_save () == 16
                    376:          && ! romp_pushes_stack ());
                    377: }
                    378: 
                    379: /* Returns 1 if OP is the address of a location in the constant pool.  */
                    380: 
                    381: int
                    382: constant_pool_address_operand (op, mode)
                    383:      rtx op;
                    384:      enum machine_mode mode;
                    385: {
                    386:   return ((GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
                    387:          || (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS
                    388:              && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
                    389:              && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
                    390:              && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (op, 0), 0))));
                    391: }
                    392: 
                    393: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
                    394:    reference and a constant.  */
                    395: 
                    396: int
                    397: romp_symbolic_operand (op, mode)
                    398:      register rtx op;
                    399:      enum machine_mode mode;
                    400: {
                    401:   switch (GET_CODE (op))
                    402:     {
                    403:     case SYMBOL_REF:
                    404:     case LABEL_REF:
                    405:       return ! op->integrated;
                    406: 
                    407:     case CONST:
                    408:       op = XEXP (op, 0);
                    409:       return (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
                    410:              || GET_CODE (XEXP (op, 0)) == LABEL_REF)
                    411:             && GET_CODE (XEXP (op, 1)) == CONST_INT;
                    412: 
                    413:     default:
                    414:       return 0;
                    415:     }
                    416: }
                    417: 
                    418: /* Returns 1 if OP is a valid constant for the ROMP.  */
                    419: 
                    420: int
                    421: constant_operand (op, mode)
                    422:     register rtx op;
                    423:     enum machine_mode mode;
                    424: {
                    425:   switch (GET_CODE (op))
                    426:     {
                    427:     case LABEL_REF:
                    428:     case SYMBOL_REF:
                    429:     case PLUS:
                    430:     case CONST:
                    431:       return romp_symbolic_operand (op,mode);
                    432: 
                    433:     case CONST_INT:
                    434:       return (unsigned int) (INTVAL (op) + 0x8000) < 0x10000
                    435:             || (INTVAL (op) & 0xffff) == 0 || (INTVAL (op) & 0xffff0000) == 0;
                    436: 
                    437:     default:
                    438:       return 0;
                    439:     }
                    440: }
                    441: 
                    442: /* Returns 1 if OP is either a constant integer valid for the ROMP or a
                    443:    register.  If a register, it must be in the proper mode unless MODE is
                    444:    VOIDmode.  */
                    445: 
                    446: int
                    447: reg_or_cint_operand (op, mode)
                    448:       register rtx op;
                    449:       enum machine_mode mode;
                    450: {
                    451:   if (GET_CODE (op) == CONST_INT)
                    452:     return constant_operand (op, mode);
                    453: 
                    454:   return register_operand (op, mode);
                    455: }
                    456: 
                    457: /* Return 1 is the operand is either a register or ANY constant integer.  */
                    458: 
                    459: int
                    460: reg_or_any_cint_operand (op, mode)
                    461:     register rtx op;
                    462:     enum machine_mode mode;
                    463: {
                    464:      return GET_CODE (op) == CONST_INT || register_operand (op, mode);
                    465: }
                    466: 
                    467: /* Return 1 if the operand is either a register or a valid D-type operand. */
                    468: 
                    469: int
                    470: reg_or_D_operand (op, mode)
                    471:     register rtx op;
                    472:     enum machine_mode mode;
                    473: {
                    474:   if (GET_CODE (op) == CONST_INT)
                    475:     return (unsigned) (INTVAL (op) + 0x8000) < 0x10000;
                    476: 
                    477:   return register_operand (op, mode);
                    478: }
                    479: 
                    480: /* Return 1 if the operand is either a register or an item that can be
                    481:    used as the operand of an SI add insn.  */
                    482: 
                    483: int
                    484: reg_or_add_operand (op, mode)
                    485:     register rtx op;
                    486:     enum machine_mode mode;
                    487: {
                    488:   return reg_or_D_operand (op, mode) || romp_symbolic_operand (op, mode)
                    489:         || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0);
                    490: }
                    491: 
                    492: /* Return 1 if the operand is either a register or an item that can be
                    493:    used as the operand of a ROMP logical AND insn.  */
                    494: 
                    495: int
                    496: reg_or_and_operand (op, mode)
                    497:     register rtx op;
                    498:     enum machine_mode mode;
                    499: {
                    500:   if (reg_or_cint_operand (op, mode))
                    501:     return 1;
                    502: 
                    503:   if (GET_CODE (op) != CONST_INT)
                    504:     return 0;
                    505: 
                    506:   return (INTVAL (op) & 0xffff) == 0xffff
                    507:         || (INTVAL (op) & 0xffff0000) == 0xffff0000;
                    508: }
                    509: 
                    510: /* Return 1 if the operand is a register or memory operand.  */
                    511: 
                    512: int
                    513: reg_or_mem_operand (op, mode)
                    514:      register rtx op;
                    515:      register enum machine_mode mode;
                    516: {
                    517:   return register_operand (op, mode) || memory_operand (op, mode);
                    518: }
                    519: 
                    520: /* Return 1 if the operand is either a register or a memory operand that is
                    521:    not symbolic.  */
                    522: 
                    523: int
                    524: reg_or_nonsymb_mem_operand (op, mode)
                    525:     register rtx op;
                    526:     enum machine_mode mode;
                    527: {
                    528:   if (register_operand (op, mode))
                    529:     return 1;
                    530: 
                    531:   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
                    532:     return 1;
                    533: 
                    534:   return 0;
                    535: }
                    536: 
                    537: /* Return 1 if this operand is valid for the ROMP.  This is any operand except
                    538:    certain constant integers.  */
                    539: 
                    540: int
                    541: romp_operand (op, mode)
                    542:     register rtx op;
                    543:     enum machine_mode mode;
                    544: {
                    545:   if (GET_CODE (op) == CONST_INT)
                    546:     return constant_operand (op, mode);
                    547: 
                    548:   return general_operand (op, mode);
                    549: }
                    550: 
                    551: /* Return 1 if the operand is (reg:mode 0).  */
                    552: 
                    553: int
                    554: reg_0_operand (op, mode)
                    555:      rtx op;
                    556:      enum machine_mode mode;
                    557: {
                    558:   return ((mode == VOIDmode || mode == GET_MODE (op))
                    559:          && GET_CODE (op) == REG && REGNO (op) == 0);
                    560: }
                    561: 
                    562: /* Return 1 if the operand is (reg:mode 15).  */
                    563: 
                    564: int
                    565: reg_15_operand (op, mode)
                    566:      rtx op;
                    567:      enum machine_mode mode;
                    568: {
                    569:   return ((mode == VOIDmode || mode == GET_MODE (op))
                    570:          && GET_CODE (op) == REG && REGNO (op) == 15);
                    571: }
                    572: 
                    573: /* Return 1 if this is a binary floating-point operation.  */
                    574: 
                    575: int
                    576: float_binary (op, mode)
                    577:     register rtx op;
                    578:     enum machine_mode mode;
                    579: {
                    580:   if (mode != VOIDmode && mode != GET_MODE (op))
                    581:     return 0;
                    582: 
                    583:   if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
                    584:     return 0;
                    585: 
                    586:   switch (GET_CODE (op))
                    587:     {
                    588:     case PLUS:
                    589:     case MINUS:
                    590:     case MULT:
                    591:     case DIV:
                    592:       return GET_MODE (XEXP (op, 0)) == GET_MODE (op)
                    593:             && GET_MODE (XEXP (op, 1)) == GET_MODE (op);
                    594: 
                    595:     default:
                    596:       return 0;
                    597:     }
                    598: }
                    599: 
                    600: /* Return 1 if this is a unary floating-point operation.  */
                    601: 
                    602: int
                    603: float_unary (op, mode)
                    604:     register rtx op;
                    605:     enum machine_mode mode;
                    606: {
                    607:   if (mode != VOIDmode && mode != GET_MODE (op))
                    608:     return 0;
                    609: 
                    610:   if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
                    611:     return 0;
                    612: 
                    613:   return (GET_CODE (op) == NEG || GET_CODE (op) == ABS)
                    614:         && GET_MODE (XEXP (op, 0)) == GET_MODE (op);
                    615: }
                    616: 
                    617: /* Return 1 if this is a valid floating-point conversion that can be done
                    618:    as part of an operation by the RT floating-point routines.  */
                    619: 
                    620: int
                    621: float_conversion (op, mode)
                    622:     register rtx op;
                    623:     enum machine_mode mode;
                    624: {
                    625:   if (mode != VOIDmode && mode != GET_MODE (op))
                    626:     return 0;
                    627: 
                    628:   switch (GET_CODE (op))
                    629:     {
                    630:     case FLOAT_TRUNCATE:
                    631:       return GET_MODE (op) == SFmode && GET_MODE (XEXP (op, 0)) == DFmode;
                    632: 
                    633:     case FLOAT_EXTEND:
                    634:       return GET_MODE (op) == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;
                    635: 
                    636:     case FLOAT:
                    637:       return ((GET_MODE (XEXP (op, 0)) == SImode
                    638:               || GET_CODE (XEXP (op, 0)) == CONST_INT)
                    639:              && (GET_MODE (op) == SFmode || GET_MODE (op) == DFmode));
                    640: 
                    641:     case FIX:
                    642:       return ((GET_MODE (op) == SImode
                    643:               || GET_CODE (XEXP (op, 0)) == CONST_INT)
                    644:              && (GET_MODE (XEXP (op, 0)) == SFmode
                    645:                  || GET_MODE (XEXP (op, 0)) == DFmode));
                    646: 
                    647:     default:
                    648:       return 0;
                    649:     }
                    650: }
                    651: 
                    652: /* Print an operand.  Recognize special options, documented below.  */
                    653: 
                    654: void
                    655: print_operand (file, x, code)
                    656:     FILE *file;
                    657:     rtx x;
                    658:     char code;
                    659: {
                    660:   int i;
                    661: 
                    662:   switch (code)
                    663:     {
                    664:     case 'B':
                    665:       /* Byte number (const/8) */
                    666:       if (GET_CODE (x) != CONST_INT)
                    667:        output_operand_lossage ("invalid %%B value");
                    668: 
                    669:       fprintf (file, "%d", INTVAL (x) / 8);
                    670:       break;
                    671: 
                    672:     case 'L':
                    673:       /* Low order 16 bits of constant.  */
                    674:       if (GET_CODE (x) != CONST_INT)
                    675:        output_operand_lossage ("invalid %%L value");
                    676: 
                    677:       fprintf (file, "%d", INTVAL (x) & 0xffff);
                    678:       break;
                    679: 
                    680:     case 's':
                    681:       /* Null or "16" depending on whether the constant is greater than 16. */
                    682:       if (GET_CODE (x) != CONST_INT)
                    683:        output_operand_lossage ("invalid %%s value");
                    684: 
                    685:       if (INTVAL (x) >= 16)
                    686:        fprintf (file, "16");
                    687: 
                    688:       break;
                    689: 
                    690:     case 'S':
                    691:       /* For shifts: 's' will have given the half.  Just give the amount
                    692:         within 16.  */
                    693:       if (GET_CODE (x) != CONST_INT)
                    694:        output_operand_lossage ("invalid %%S value");
                    695: 
                    696:       fprintf (file, "%d", INTVAL (x) & 15);
                    697:       break;
                    698: 
                    699:     case 'b':
                    700:       /* The number of a single bit set or cleared, mod 16.  Note that the ROMP
                    701:         numbers bits with the high-order bit 31.  */
                    702:       if (GET_CODE (x) != CONST_INT)
                    703:        output_operand_lossage ("invalid %%b value");
                    704: 
                    705:       if ((i = exact_log2 (INTVAL (x))) >= 0)
                    706:        fprintf (file, "%d", (31 - i) % 16);
                    707:       else if ((i = exact_log2 (~ INTVAL (x))) >= 0)
                    708:        fprintf (file, "%d", (31 - i) % 16);
                    709:       else
                    710:        output_operand_lossage ("invalid %%b value");
                    711: 
                    712:       break;
                    713: 
                    714:     case 'h':
                    715:       /* "l" or "u" depending on which half of the constant is zero.  */
                    716:       if (GET_CODE (x) != CONST_INT)
                    717:        output_operand_lossage ("invalid %%h value");
                    718: 
                    719:       if ((INTVAL (x) & 0xffff0000) == 0)
                    720:        fprintf (file, "l");
                    721:       else if ((INTVAL (x) & 0xffff) == 0)
                    722:        fprintf (file, "u");
                    723:       else
                    724:        output_operand_lossage ("invalid %%h value");
                    725: 
                    726:       break;
                    727: 
                    728:     case 'H':
                    729:       /* Upper or lower half, depending on which half is zero.  */
                    730:       if (GET_CODE (x) != CONST_INT)
                    731:        output_operand_lossage ("invalid %%H value");
                    732: 
                    733:       if ((INTVAL (x) & 0xffff0000) == 0)
                    734:        fprintf (file, "%d", INTVAL (x) & 0xffff);
                    735:       else if ((INTVAL (x) & 0xffff) == 0)
                    736:        fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
                    737:       else
                    738:        output_operand_lossage ("invalid %%H value");
                    739: 
                    740:       break;
                    741: 
                    742:     case 'z':
                    743:       /* Write two characters:
                    744:                'lo'    if the high order part is all ones
                    745:                'lz'    if the high order part is all zeros
                    746:                'uo'    if the low order part is all ones
                    747:                'uz'    if the low order part is all zeros 
                    748:        */
                    749:       if (GET_CODE (x) != CONST_INT)
                    750:        output_operand_lossage ("invalid %%z value");
                    751: 
                    752:       if ((INTVAL (x) & 0xffff0000) == 0)
                    753:        fprintf (file, "lz");
                    754:       else if ((INTVAL (x) & 0xffff0000) == 0xffff0000)
                    755:        fprintf (file, "lo");
                    756:       else if ((INTVAL (x) & 0xffff) == 0)
                    757:        fprintf (file, "uz");
                    758:       else if ((INTVAL (x) & 0xffff) == 0xffff)
                    759:        fprintf (file, "uo");
                    760:       else
                    761:        output_operand_lossage ("invalid %%z value");
                    762: 
                    763:       break;
                    764: 
                    765:     case 'Z':
                    766:       /* Upper or lower half, depending on which is non-zero or not
                    767:         all ones.  Must be consistent with 'z' above.  */
                    768:       if (GET_CODE (x) != CONST_INT)
                    769:        output_operand_lossage ("invalid %%Z value");
                    770: 
                    771:       if ((INTVAL (x) & 0xffff0000) == 0
                    772:          || (INTVAL (x) & 0xffff0000) == 0xffff0000)
                    773:        fprintf (file, "%d", INTVAL (x) & 0xffff);
                    774:       else if ((INTVAL (x) & 0xffff) == 0 || (INTVAL (x) & 0xffff) == 0xffff)
                    775:        fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
                    776:       else
                    777:        output_operand_lossage ("invalid %%Z value");
                    778: 
                    779:       break;
                    780: 
                    781:     case 'k':
                    782:       /* Same as 'z', except the trailing 'o' or 'z' is not written.  */
                    783:       if (GET_CODE (x) != CONST_INT)
                    784:        output_operand_lossage ("invalid %%k value");
                    785: 
                    786:       if ((INTVAL (x) & 0xffff0000) == 0
                    787:          || (INTVAL (x) & 0xffff0000) == 0xffff0000)
                    788:        fprintf (file, "l");
                    789:       else if ((INTVAL (x) & 0xffff) == 0
                    790:               || (INTVAL (x) & 0xffff) == 0xffff)
                    791:        fprintf (file, "u");
                    792:       else
                    793:        output_operand_lossage ("invalid %%k value");
                    794: 
                    795:       break;
                    796: 
                    797:     case 't':
                    798:       /* Similar to 's', except that we write 'h' or 'u'.  */
                    799:       if (GET_CODE (x) != CONST_INT)
                    800:        output_operand_lossage ("invalid %%k value");
                    801: 
                    802:       if (INTVAL (x) < 16)
                    803:        fprintf (file, "u");
                    804:       else
                    805:        fprintf (file, "l");
                    806:       break;
                    807: 
                    808:     case 'M':
                    809:       /* For memory operations, write 's' if the operand is a short
                    810:         memory operand.  */
                    811:       if (short_memory_operand (x, VOIDmode))
                    812:        fprintf (file, "s");
                    813:       break;
                    814: 
                    815:     case 'N':
                    816:       /* Like 'M', but check for zero memory offset.  */
                    817:       if (zero_memory_operand (x, VOIDmode))
                    818:        fprintf (file, "s");
                    819:       break;
                    820: 
                    821:     case 'O':
                    822:       /* Write low-order part of DImode or DFmode.  Supported for MEM
                    823:         and REG only.  */
                    824:       if (GET_CODE (x) == REG)
                    825:        fprintf (file, "%s", reg_names[REGNO (x) + 1]);
                    826:       else if (GET_CODE (x) == MEM)
                    827:        print_operand (file, gen_rtx (MEM, GET_MODE (x),
                    828:                                      plus_constant (XEXP (x, 0), 4)), 0);
                    829:       else
                    830:        abort ();
                    831:       break;
                    832: 
                    833:     case 'C':
                    834:       /* Offset in constant pool for constant pool address.  */
                    835:       if (! constant_pool_address_operand (x, VOIDmode))
                    836:        abort ();
                    837:       if (GET_CODE (x) == SYMBOL_REF)
                    838:        fprintf (file, "%d", get_pool_offset (x) + 12);
                    839:       else 
                    840:        /* Must be (const (plus (symbol_ref) (const_int))) */
                    841:        fprintf (file, "%d",
                    842:                 (get_pool_offset (XEXP (XEXP (x, 0), 0)) + 12
                    843:                  + INTVAL (XEXP (XEXP (x, 0), 1))));
                    844:       break;
                    845: 
                    846:     case 'j':
                    847:       /* Branch opcode.  Check for condition in test bit for eq/ne.  */
                    848:       switch (GET_CODE (x))
                    849:        {
                    850:        case EQ:
                    851:          if (cc_status.flags & CC_IN_TB)
                    852:            fprintf (file, "ntb");
                    853:          else
                    854:            fprintf (file, "eq");
                    855:          break;
                    856: 
                    857:        case NE:
                    858:          if (cc_status.flags & CC_IN_TB)
                    859:            fprintf (file, "tb");
                    860:          else
                    861:            fprintf (file, "ne");
                    862:          break;
                    863: 
                    864:        case GT:
                    865:        case GTU:
                    866:          fprintf (file, "h");
                    867:          break;
                    868: 
                    869:        case LT:
                    870:        case LTU:
                    871:          fprintf (file, "l");
                    872:          break;
                    873: 
                    874:        case GE:
                    875:        case GEU:
                    876:          fprintf (file, "he");
                    877:          break;
                    878: 
                    879:        case LE:
                    880:        case LEU:
                    881:          fprintf (file, "le");
                    882:          break;
                    883: 
                    884:        default:
                    885:          output_operand_lossage ("invalid %%j value");
                    886:        }
                    887:       break;
                    888: 
                    889:     case 'J':
                    890:       /* Reversed branch opcode.  */
                    891:       switch (GET_CODE (x))
                    892:        {
                    893:        case EQ:
                    894:          if (cc_status.flags & CC_IN_TB)
                    895:            fprintf (file, "tb");
                    896:          else
                    897:            fprintf (file, "ne");
                    898:          break;
                    899: 
                    900:        case NE:
                    901:          if (cc_status.flags & CC_IN_TB)
                    902:            fprintf (file, "ntb");
                    903:          else
                    904:            fprintf (file, "eq");
                    905:          break;
                    906: 
                    907:        case GT:
                    908:        case GTU:
                    909:          fprintf (file, "le");
                    910:          break;
                    911: 
                    912:        case LT:
                    913:        case LTU:
                    914:          fprintf (file, "he");
                    915:          break;
                    916: 
                    917:        case GE:
                    918:        case GEU:
                    919:          fprintf (file, "l");
                    920:          break;
                    921: 
                    922:        case LE:
                    923:        case LEU:
                    924:          fprintf (file, "h");
                    925:          break;
                    926: 
                    927:        default:
                    928:          output_operand_lossage ("invalid %%j value");
                    929:        }
                    930:       break;
                    931: 
                    932:     case '.':
                    933:       /* Output nothing.  Used as delimiter in, e.g., "mc%B1%.3 " */
                    934:       break;
                    935: 
                    936:     case '#':
                    937:       /* Output 'x' if this insn has a delay slot, else nothing.  */
                    938:       if (dbr_sequence_length ())
                    939:        fprintf (file, "x");
                    940:       break;
                    941: 
                    942:     case 0:
                    943:       if (GET_CODE (x) == REG)
                    944:        fprintf (file, "%s", reg_names[REGNO (x)]);
                    945:       else if (GET_CODE (x) == MEM)
                    946:        {
                    947:          if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
                    948:              && current_function_operand (x, Pmode))
                    949:            fprintf (file, "r14");
                    950:          else
                    951:            output_address (XEXP (x, 0));
                    952:        }
                    953:       else
                    954:        output_addr_const (file, x);
                    955:       break;
                    956: 
                    957:     default:
                    958:       output_operand_lossage ("invalid %%xn code");
                    959:     }
                    960: }
                    961: 
                    962: /* This page contains routines that are used to determine what the function
                    963:    prologue and epilogue code will do and write them out.  */
                    964: 
                    965: /*  Return the first register that is required to be saved. 16 if none.  */
                    966: 
                    967: int
                    968: first_reg_to_save()
                    969: {
                    970:   int first_reg;
                    971: 
                    972:   /* Find lowest numbered live register.  */
                    973:   for (first_reg = 6; first_reg <= 15; first_reg++)
                    974:     if (regs_ever_live[first_reg])
                    975:       break;
                    976: 
                    977:   /* If we think that we do not have to save r14, see if it will be used
                    978:      to be sure.  */
                    979:   if (first_reg > 14 && romp_using_r14 ())
                    980:     first_reg = 14;
                    981: 
                    982:   return first_reg;
                    983: }
                    984: 
                    985: /* Compute the size of the save area in the stack, including the space for
                    986:    the first four incoming arguments.  */
                    987: 
                    988: int
                    989: romp_sa_size ()
                    990: {
                    991:   int size;
                    992:   int i;
                    993: 
                    994:   /* We have the 4 words corresponding to the arguments passed in registers,
                    995:      4 reserved words, space for static chain, general register save area,
                    996:      and floating-point save area.  */
                    997:   size = 4 + 4 + 1 + (16 - first_reg_to_save ());
                    998: 
                    999:   /* The documentation says we have to leave 18 words in the save area if
                   1000:      any floating-point registers at all are saved, not the three words
                   1001:      per register you might otherwise expect.  */
                   1002:   for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
                   1003:     if (regs_ever_live[i + 17])
                   1004:       {
                   1005:        size += 18;
                   1006:        break;
                   1007:       }
                   1008: 
                   1009:   return size * 4;
                   1010: }
                   1011: 
                   1012: /* Return non-zero if this function makes calls or has fp operations
                   1013:    (which are really calls).  */
                   1014: 
                   1015: int
                   1016: romp_makes_calls ()
                   1017: {
                   1018:   rtx insn;
                   1019: 
                   1020:   for (insn = get_insns (); insn; insn = next_insn (insn))
                   1021:     {
                   1022:       if (GET_CODE (insn) == CALL_INSN)
                   1023:        return 1;
                   1024:       else if (GET_CODE (insn) == INSN)
                   1025:        {
                   1026:          rtx body = PATTERN (insn);
                   1027: 
                   1028:          if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER
                   1029:              && GET_CODE (body) != ADDR_VEC
                   1030:              && GET_CODE (body) != ADDR_DIFF_VEC
                   1031:              && get_attr_type (insn) == TYPE_FP)
                   1032:            return 1;
                   1033:        }
                   1034:     }
                   1035: 
                   1036:   return 0;
                   1037: }
                   1038: 
                   1039: /* Return non-zero if this function will use r14 as a pointer to its
                   1040:    constant pool.  */
                   1041: 
                   1042: int
                   1043: romp_using_r14 ()
                   1044: {
                   1045:   /* If we are debugging, profiling, have a non-empty constant pool, or
                   1046:      call a function, we need r14.  */
                   1047:   return (write_symbols != NO_DEBUG || profile_flag || get_pool_size () != 0
                   1048:          || romp_makes_calls ());
                   1049: }
                   1050: 
                   1051: /* Return non-zero if this function needs to push space on the stack.  */
                   1052: 
                   1053: int
                   1054: romp_pushes_stack ()
                   1055: {
                   1056:   /* We need to push the stack if a frame pointer is needed (because the
                   1057:      stack might be dynamically adjusted), if we are debugging, if the
                   1058:      total required size is more than 100 bytes, or if we make calls.  */
                   1059: 
                   1060:   return (frame_pointer_needed || write_symbols != NO_DEBUG
                   1061:          || (romp_sa_size () + get_frame_size ()) > 100
                   1062:          || romp_makes_calls ());
                   1063: }
                   1064: 
                   1065: /* Write function prologue.
                   1066: 
                   1067:    We compute the size of the fixed area required as follows:
                   1068: 
                   1069:    We always allocate 4 words for incoming arguments, 4 word reserved, 1
                   1070:    word for static link, as many words as required for general register
                   1071:    save area, plus 2 words for each FP reg 2-7 that must be saved.  */
                   1072: 
                   1073: void
                   1074: output_prolog (file, size)
                   1075:      FILE *file;
                   1076:      int size;
                   1077: {
                   1078:   int first_reg;
                   1079:   int reg_save_offset;
                   1080:   int fp_save = size + current_function_outgoing_args_size;
                   1081: 
                   1082:   init_fpops ();
                   1083: 
                   1084:   /* Add in fixed size plus output argument area.  */
                   1085:   size += romp_sa_size () + current_function_outgoing_args_size;
                   1086: 
                   1087:   /* Compute first register to save and perform the save operation if anything
                   1088:      needs to be saved.  */
                   1089:   first_reg = first_reg_to_save();
                   1090:   reg_save_offset = - (4 + 4 + 1 + (16 - first_reg)) * 4;
                   1091:   if (first_reg == 15)
                   1092:     fprintf (file, "\tst r15,%d(r1)\n", reg_save_offset);
                   1093:   else if (first_reg < 16)
                   1094:     fprintf (file, "\tstm r%d,%d(r1)\n", first_reg, reg_save_offset);
                   1095: 
                   1096:   /* Set up pointer to data area if it is needed.  */
                   1097:   if (romp_using_r14 ())
                   1098:     fprintf (file, "\tcas r14,r0,r0\n");
                   1099: 
                   1100:   /* Set up frame pointer if needed.  */
                   1101:   if (frame_pointer_needed)
                   1102:     fprintf (file, "\tcal r13,-%d(r1)\n", romp_sa_size () + 64);
                   1103: 
                   1104:   /* Push stack if neeeded.  There are a couple of ways of doing this.  */
                   1105:   if (romp_pushes_stack ())
                   1106:     {
                   1107:       if (size >= 32768)
                   1108:        {
                   1109:          if (size >= 65536)
                   1110:            {
                   1111:              fprintf (file, "\tcau r0,%d(r0)\n", size >> 16);
                   1112:              fprintf (file, "\toil r0,r0,%d\n", size & 0xffff);
                   1113:            }
                   1114:          else
                   1115:            fprintf (file, "\tcal16 r0,%d(r0)\n", size);
                   1116:          fprintf (file, "\ts r1,r0\n");
                   1117:        }
                   1118:       else
                   1119:        fprintf (file, "\tcal r1,-%d(r1)\n", size);
                   1120:     }
                   1121: 
                   1122:   /* Save floating-point registers.  */
                   1123:   output_loadsave_fpregs (file, USE,
                   1124:                          plus_constant (stack_pointer_rtx, fp_save));
                   1125: }
1.1.1.2   root     1126: 
                   1127: /* Output the offset information used by debuggers.
                   1128:    This is the exactly the total_size value of output_epilog
                   1129:    which is added to the frame pointer. However the value in the debug
                   1130:    table is encoded in a space-saving way as follows:
                   1131: 
                   1132:    The first byte contains two fields: a 2-bit size field and the first
                   1133:    6 bits of an offset value. The 2-bit size field is in the high-order
                   1134:    position and specifies how many subsequent bytes follow after
                   1135:    this one. An offset value is at most 4-bytes long.
                   1136: 
                   1137:    The last 6 bits of the first byte initialize the offset value. In many
                   1138:    cases where procedures have small local storage, this is enough and, in
                   1139:    this case, the high-order size field is zero so the byte can (almost) be
                   1140:    used as is (see below). Thus, the byte value of 0x0d is encodes a offset
                   1141:    size of 13 words, or 52 bytes.
                   1142: 
                   1143:    For procedures with a local space larger than 60 bytes, the 6 bits
                   1144:    are the high-order 6 bits.  The remaining bytes follow as necessary,
                   1145:    in Big Endian order.  Thus, the short value of 16907 (= 16384+523)
                   1146:    encodes an offset of 2092 bytes (523 words).
                   1147: 
                   1148:    The total offset value is in words (not bytes), so the final value has to
                   1149:    be multiplied by 4 before it can be used in address computations by a
                   1150:    debugger.   */
                   1151: 
                   1152: void
                   1153: output_encoded_offset (file, reg_offset)
                   1154:      FILE *file;
                   1155:      unsigned reg_offset;
                   1156: {
                   1157:   /* Convert the offset value to 4-byte words rather than bytes. */
                   1158:   reg_offset = (reg_offset + 3) / 4;
1.1       root     1159: 
1.1.1.2   root     1160:   /* Now output 1-4 bytes in encoded form. */
                   1161:   if (reg_offset < (1 << 6))
                   1162:     /* Fits into one byte */
                   1163:     fprintf (file, "\t.byte %d\n", reg_offset);
                   1164:   else if (reg_offset < (1 << (6 + 8)))
                   1165:     /* Fits into two bytes */
                   1166:     fprintf (file, "\t.short %d\n", (1 << (6 + 8)) + reg_offset);
                   1167:   else if (reg_offset < (1 << (6 + 8 + 8)))
                   1168:     {
                   1169:       /* Fits in three bytes */
                   1170:       fprintf (file, "\t.byte %d\n", (2 << 6) + (reg_offset >> ( 6+ 8)));
                   1171:       fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
                   1172:     }
                   1173:   else
                   1174:     {
                   1175:       /* Use 4 bytes.  */
                   1176:       fprintf (file, "\t.short %d", (3 << (6 + 8)) + (reg_offset >> (6 + 8)));
                   1177:       fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
                   1178:     }
                   1179: }
                   1180: 
1.1       root     1181: /* Write function epilogue.  */
                   1182: 
                   1183: void
                   1184: output_epilog (file, size)
                   1185:      FILE *file;
                   1186:      int size;
                   1187: {
                   1188:   int first_reg = first_reg_to_save();
                   1189:   int pushes_stack = romp_pushes_stack ();
                   1190:   int reg_save_offset = - ((16 - first_reg) + 1 + 4 + 4) * 4;
                   1191:   int total_size = (size + romp_sa_size ()
                   1192:                    + current_function_outgoing_args_size);
                   1193:   int fp_save = size + current_function_outgoing_args_size;
                   1194:   int long_frame = total_size >= 32768;
                   1195:   rtx insn = get_last_insn ();
                   1196:   int write_code = 1;
                   1197: 
                   1198:   int nargs = 0;               /* words of arguments */
                   1199:   tree argptr;
                   1200: 
                   1201:   /* Compute the number of words of arguments.  Since this is just for
                   1202:      the traceback table, we ignore arguments that don't have a size or
                   1203:      don't have a fixed size.  */
                   1204: 
                   1205:   for (argptr = DECL_ARGUMENTS (current_function_decl);
                   1206:        argptr; argptr = TREE_CHAIN (argptr))
                   1207:     {
                   1208:       int this_size = int_size_in_bytes (TREE_TYPE (argptr));
                   1209: 
                   1210:       if (this_size > 0)
                   1211:        nargs += (this_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
                   1212:     }
                   1213:   
                   1214:   /* If the last insn was a BARRIER, we don't have to write anything except
                   1215:      the trace table.  */
                   1216:   if (GET_CODE (insn) == NOTE)
                   1217:     insn = prev_nonnote_insn (insn);
                   1218:   if (insn && GET_CODE (insn) == BARRIER)
                   1219:     write_code = 0;
                   1220: 
                   1221:   /* Restore floating-point registers.  */
                   1222:   if (write_code)
                   1223:     output_loadsave_fpregs (file, CLOBBER,
                   1224:                            gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, 1),
                   1225:                                     gen_rtx (CONST_INT, VOIDmode, fp_save)));
                   1226: 
                   1227:   /* If we push the stack and do not have size > 32K, adjust the register
                   1228:      save location to the current position of sp.  Otherwise, if long frame,
                   1229:      restore sp from fp.  */
                   1230:   if (pushes_stack && ! long_frame)
                   1231:     reg_save_offset += total_size;
                   1232:   else if (long_frame && write_code)
                   1233:     fprintf (file, "\tcal r1,%d(r13)\n", romp_sa_size () + 64);
                   1234: 
                   1235:   /* Restore registers.  */
                   1236:   if (first_reg == 15 && write_code)
                   1237:     fprintf (file, "\tl r15,%d(r1)\n", reg_save_offset);
                   1238:   else if (first_reg < 16 && write_code)
                   1239:     fprintf (file, "\tlm r%d,%d(r1)\n", first_reg, reg_save_offset);
                   1240:   if (first_reg == 16) first_reg = 0;
                   1241: 
                   1242:   /* Handle popping stack, if needed and write debug table entry.  */
                   1243:   if (pushes_stack)
                   1244:     {
                   1245:       if (write_code)
                   1246:        {
                   1247:          if (long_frame)
                   1248:            fprintf (file, "\tbr r15\n");
                   1249:          else
                   1250:            fprintf (file, "\tbrx r15\n\tcal r1,%d(r1)\n", total_size);
                   1251:        }
1.1.1.2   root     1252: 
                   1253:       /* Table header (0xdf), usual-type stack frame (0x07),
                   1254:         table header (0xdf), and first register saved.
                   1255: 
                   1256:         The final 0x08 means that there is a byte following this one
                   1257:         describing the number of parameter words and the register used as
                   1258:         stack pointer.
                   1259: 
                   1260:         If GCC passed floating-point parameters in floating-point registers,
                   1261:         it would be necessary to change the final byte from 0x08 to 0x0c.
                   1262:         Also an additional entry byte would be need to be emitted to specify
                   1263:         the first floating-point register.
                   1264: 
                   1265:         (See also Section 11 (Trace Tables) in ``IBM/4.3 Linkage Convention,''
                   1266:         pages IBM/4.3-PSD:5-7 of Volume III of the IBM Academic Operating
                   1267:         System Manual dated July 1987.)  */
                   1268: 
1.1       root     1269:       fprintf (file, "\t.long 0x%x\n", 0xdf07df08 + first_reg * 0x10);
                   1270: 
                   1271:       if (nargs > 15) nargs = 15;
1.1.1.2   root     1272: 
                   1273:       /* The number of parameter words and the register used as the stack
                   1274:         pointer (encoded here as r1).
                   1275: 
                   1276:         Note: The MetWare Hich C Compiler R2.1y actually gets this wrong;
                   1277:         it erroneously lists r13 but uses r1 as the stack too. But a bug in
                   1278:         dbx 1.5 nullifies this mistake---most of the time.
                   1279:          (Dbx retrieves the value of r13 saved on the stack which is often
                   1280:         the value of r1 before the call.)  */
                   1281: 
                   1282:       fprintf (file, "\t.byte 0x%x1\n", nargs);
                   1283:       output_encoded_offset (file, total_size);
1.1       root     1284:     }
                   1285:   else
                   1286:     {
                   1287:       if (write_code)
                   1288:        fprintf (file, "\tbr r15\n");
1.1.1.2   root     1289: 
                   1290:       /* Table header (0xdf), no stack frame (0x02),
                   1291:         table header (0xdf) and no parameters saved (0x00).
                   1292: 
                   1293:         If GCC passed floating-point parameters in floating-point registers,
                   1294:         it might be necessary to change the final byte from 0x00 to 0x04.
                   1295:         Also a byte would be needed to specify the first floating-point
                   1296:         register.  */
1.1       root     1297:       fprintf (file, "\t.long 0xdf02df00\n");
                   1298:     }
                   1299: 
                   1300:   /* Output any pending floating-point operations.  */
                   1301:   output_fpops (file);
                   1302: }
                   1303: 
                   1304: /* For the ROMP we need to make new SYMBOL_REFs for the actual name of a
                   1305:    called routine.  To keep them unique we maintain a hash table of all
                   1306:    that have been created so far.  */
                   1307: 
                   1308: struct symref_hashent {
                   1309:   rtx symref;                  /* Created SYMBOL_REF rtx.  */
                   1310:   struct symref_hashent *next; /* Next with same hash code.  */
                   1311: };
                   1312: 
                   1313: #define SYMHASHSIZE 151
                   1314: #define HASHBITS 65535
                   1315: 
                   1316: /* Define the hash table itself.  */
                   1317: 
                   1318: static struct symref_hashent *symref_hash_table[SYMHASHSIZE];
                   1319: 
                   1320: /* Given a name (allocatable in temporary storage), return a SYMBOL_REF
                   1321:    for the name.  The rtx is allocated from the current rtl_obstack, while
                   1322:    the name string is allocated from the permanent obstack.  */
                   1323: rtx
                   1324: get_symref (name)
                   1325:      register char *name;
                   1326: {
                   1327:   extern struct obstack permanent_obstack;
                   1328:   register char *sp = name;
                   1329:   unsigned int hash = 0;
                   1330:   struct symref_hashent *p, **last_p;
                   1331: 
                   1332:   /* Compute the hash code for the string.  */
                   1333:   while (*sp)
                   1334:     hash = (hash << 4) + *sp++;
                   1335: 
                   1336:   /* Search for a matching entry in the hash table, keeping track of the
                   1337:      insertion location as we do so.  */
                   1338:   hash = (hash & HASHBITS) % SYMHASHSIZE;
                   1339:   for (last_p = &symref_hash_table[hash], p = *last_p;
                   1340:        p; last_p = &p->next, p = *last_p)
                   1341:     if (strcmp (name, XSTR (p->symref, 0)) == 0)
                   1342:       break;
                   1343: 
                   1344:   /* If couldn't find matching SYMBOL_REF, make a new one.  */
                   1345:   if (p == 0)
                   1346:     {
                   1347:       /* Ensure SYMBOL_REF will stay around.  */
                   1348:       end_temporary_allocation ();
                   1349:       p = *last_p = (struct symref_hashent *)
                   1350:                        permalloc (sizeof (struct symref_hashent));
                   1351:       p->symref = gen_rtx (SYMBOL_REF, Pmode,
                   1352:                           obstack_copy0 (&permanent_obstack,
                   1353:                                          name, strlen (name)));
                   1354:       p->next = 0;
                   1355:       resume_temporary_allocation ();
                   1356:     }
                   1357: 
                   1358:   return p->symref;
                   1359: }
                   1360: 
                   1361: /* Validate the precision of a floating-point operation.
                   1362: 
                   1363:    We merge conversions from integers and between floating-point modes into
                   1364:    the insn.  However, this must not effect the desired precision of the
                   1365:    insn.  The RT floating-point system uses the widest of the operand modes.
                   1366:    If this should be a double-precision insn, ensure that one operand
                   1367:    passed to the floating-point processor has double mode.
                   1368: 
                   1369:    Note that since we don't check anything if the mode is single precision,
                   1370:    it, strictly speaking, isn't necessary to call this for those insns.
                   1371:    However, we do so in case something else needs to be checked in the
                   1372:    future.
                   1373: 
                   1374:    This routine returns 1 if the operation is OK.  */
                   1375: 
                   1376: int
                   1377: check_precision (opmode, op1, op2)
                   1378:      enum machine_mode opmode;
                   1379:      rtx op1, op2;
                   1380: {
                   1381:   if (opmode == SFmode)
                   1382:     return 1;
                   1383: 
                   1384:   /* If operand is not a conversion from an integer mode or an extension from
                   1385:      single-precision, it must be a double-precision value.  */
                   1386:   if (GET_CODE (op1) != FLOAT && GET_CODE (op1) != FLOAT_EXTEND)
                   1387:     return 1;
                   1388: 
                   1389:   if (op2 && GET_CODE (op2) != FLOAT && GET_CODE (op2) != FLOAT_EXTEND)
                   1390:     return 1;
                   1391: 
                   1392:   return 0;
                   1393: }
                   1394: 
                   1395: /* Floating-point on the RT is done by creating an operation block in the data
                   1396:    area that describes the operation.  If two floating-point operations are the
                   1397:    same in a single function, they can use the same block.
                   1398: 
                   1399:    These routines are responsible for managing these blocks.  */
                   1400: 
                   1401: /* Structure to describe a floating-point operation.  */
                   1402: 
                   1403: struct fp_op {
                   1404:   struct fp_op *next_same_hash;                /* Next op with same hash code. */
                   1405:   struct fp_op *next_in_mem;           /* Next op in memory. */
                   1406:   int mem_offset;                      /* Offset from data area.  */
                   1407:   short size;                          /* Size of block in bytes.  */
                   1408:   short noperands;                     /* Number of operands in block.  */
                   1409:   rtx ops[3];                          /* RTL for operands. */
                   1410:   enum rtx_code opcode;                        /* Operation being performed.  */
                   1411: };
                   1412: 
                   1413: /* Size of hash table.  */
                   1414: #define FP_HASH_SIZE 101
                   1415: 
                   1416: /* Hash table of floating-point operation blocks.  */
                   1417: static struct fp_op *fp_hash_table[FP_HASH_SIZE];
                   1418: 
                   1419: /* First floating-point block in data area.  */
                   1420: static struct fp_op *first_fpop;
                   1421: 
                   1422: /* Last block in data area so far.  */
                   1423: static struct fp_op *last_fpop_in_mem;
                   1424: 
                   1425: /* Subroutine number in file, to get unique "LF" labels.  */
                   1426: static int subr_number = 0;
                   1427: 
                   1428: /* Current word offset in data area (includes header and any constant pool). */
                   1429: int data_offset;
                   1430: 
                   1431: /* Compute hash code for an RTX used in floating-point.  */
                   1432: 
                   1433: static unsigned int
                   1434: hash_rtx (x)
                   1435:      register rtx x;
                   1436: {
                   1437:   register unsigned int hash = (((int) GET_CODE (x) << 10)
                   1438:                                + ((int) GET_MODE (x) << 20));
                   1439:   register int i;
                   1440:   register char *fmt = GET_RTX_FORMAT (GET_CODE (x));
                   1441: 
                   1442:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
                   1443:     if (fmt[i] == 'e')
                   1444:       hash += hash_rtx (XEXP (x, i));
                   1445:     else if (fmt[i] == 'u')
1.1.1.3 ! root     1446:       hash += (unsigned HOST_WIDE_INT) XEXP (x, i);
1.1       root     1447:     else if (fmt[i] == 'i')
                   1448:       hash += XINT (x, i);
                   1449:     else if (fmt[i] == 's')
1.1.1.3 ! root     1450:       hash += (unsigned HOST_WIDE_INT) XSTR (x, i);
1.1       root     1451: 
                   1452:   return hash;
                   1453: }
                   1454: 
                   1455: /* Given an operation code and up to three operands, return a character string
                   1456:    corresponding to the code to emit to branch to a floating-point operation
                   1457:    block.  INSN is provided to see if the delay slot has been filled or not.
                   1458: 
                   1459:    A new floating-point operation block is created if this operation has not
                   1460:    been seen before.  */
                   1461: 
                   1462: char *
                   1463: output_fpop (code, op0, op1, op2, insn)
                   1464:      enum rtx_code code;
                   1465:      rtx op0, op1, op2;
                   1466:      rtx insn;
                   1467: {
                   1468:   static char outbuf[40];
                   1469:   unsigned int hash, hash0, hash1, hash2;
                   1470:   int size, i;
                   1471:   register struct fp_op *fpop, *last_fpop;
                   1472:   int dyadic = (op2 != 0);
                   1473:   enum machine_mode opmode;
                   1474:   int noperands;
                   1475:   rtx tem;
                   1476:   unsigned int tem_hash;
                   1477:   int fr0_avail = 0;
                   1478: 
                   1479:   /* Compute hash code for each operand.  If the operation is commutative,
                   1480:      put the one with the smaller hash code first.  This will make us see
                   1481:      more operations as identical.  */
                   1482:   hash0 = op0 ? hash_rtx (op0) : 0;
                   1483:   hash1 = op1 ? hash_rtx (op1) : 0;
                   1484:   hash2 = op2 ? hash_rtx (op2) : 0;
                   1485: 
                   1486:   if (hash0 > hash1 && code == EQ)
                   1487:     {
                   1488:       tem = op0; op0 = op1; op1 = tem;
                   1489:       tem_hash = hash0; hash0 = hash1; hash1 = tem_hash;
                   1490:     }
                   1491:   else if (hash1 > hash2 && (code == PLUS || code == MULT))
                   1492:     {
                   1493:       tem = op1; op1 = op2; op2 = tem;
                   1494:       tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
                   1495:     }
                   1496: 
                   1497:   /* If operation is commutative and the first and third operands are equal,
                   1498:      swap the second and third operands.  Note that we must consider two
                   1499:      operands equal if they are the same register even if different modes.  */
                   1500:   if (op2 && (code == PLUS || code == MULT)
                   1501:       && (rtx_equal_p (op0, op2)
                   1502:          || (GET_CODE (op0) == REG && GET_CODE (op2) == REG
                   1503:              && REGNO (op0) == REGNO (op2))))
                   1504:     {
                   1505:       tem = op1; op1 = op2; op2 = tem;
                   1506:       tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
                   1507:     }
                   1508: 
                   1509:   /* If the first and second operands are the same, merge them.  Don't do this
                   1510:      for SFmode or SImode in general registers because this triggers a bug in
                   1511:      the RT fp code.  */
                   1512:   if (op1 && rtx_equal_p (op0, op1)
                   1513:       && code != EQ && code != GE && code != SET
                   1514:       && ((GET_MODE (op1) != SFmode && GET_MODE (op1) != SImode)
                   1515:          || GET_CODE (op0) != REG || FP_REGNO_P (REGNO (op0))))
                   1516:     {
                   1517:       op1 = op2;
                   1518:       op2 = 0;
                   1519:     }
                   1520: 
                   1521:   noperands = 1 + (op1 != 0) + (op2 != 0);
                   1522: 
                   1523:   /* Compute hash code for entire expression and see if operation block
                   1524:      already exists.  */
                   1525:   hash = ((int) code << 13) + (hash0 << 2) + (hash1 << 1) + hash2;
                   1526: 
                   1527:   hash %= FP_HASH_SIZE;
                   1528:   for (fpop = fp_hash_table[hash], last_fpop = 0;
                   1529:        fpop;
                   1530:        last_fpop = fpop, fpop = fpop->next_same_hash)
                   1531:     if (fpop->opcode == code && noperands == fpop->noperands
                   1532:        && (op0 == 0 || rtx_equal_p (op0, fpop->ops[0]))
                   1533:        && (op1 == 0 || rtx_equal_p (op1, fpop->ops[1]))
                   1534:        && (op2 == 0 || rtx_equal_p (op2, fpop->ops[2])))
                   1535:       goto win;
                   1536: 
                   1537:   /* We have never seen this operation before.  */
                   1538:   fpop = (struct fp_op *) oballoc (sizeof (struct fp_op));
                   1539:   fpop->mem_offset = data_offset;
                   1540:   fpop->opcode = code;
                   1541:   fpop->noperands = noperands;
                   1542:   fpop->ops[0] = op0;
                   1543:   fpop->ops[1] = op1;
                   1544:   fpop->ops[2] = op2;
                   1545: 
                   1546:   /* Compute the size using the rules in Appendix A of the RT Linkage
                   1547:      Convention (4.3/RT-PSD:5) manual.  These rules are a bit ambiguous,
                   1548:      but if we guess wrong, it will effect only efficiency, not correctness. */
                   1549: 
                   1550:   /* Size = 24 + 32 for each non-fp (or fr7) */
                   1551:   size = 24;
                   1552:   if (op0 && (GET_CODE (op0) != REG
                   1553:              || ! FP_REGNO_P (REGNO (op0)) || REGNO (op0) == 23))
                   1554:     size += 32;
                   1555: 
                   1556:   if (op1 && (GET_CODE (op1) != REG
                   1557:              || ! FP_REGNO_P (REGNO (op1)) || REGNO (op1) == 23))
                   1558:     size += 32;
                   1559: 
                   1560:   if (op2 && (GET_CODE (op2) != REG
                   1561:              || ! FP_REGNO_P (REGNO (op2)) || REGNO (op2) == 23))
                   1562:     size += 32;
                   1563: 
                   1564:   /* Size + 12 for each conversion.  First get operation mode.  */
                   1565:   if ((op0 && GET_MODE (op0) == DFmode)
                   1566:       || (op1 && GET_MODE (op1) == DFmode)
                   1567:       || (op2 && GET_MODE (op2) == DFmode))
                   1568:     opmode = DFmode;
                   1569:   else
                   1570:     opmode = SFmode;
                   1571: 
                   1572:   if (op0 && GET_MODE (op0) != opmode)
                   1573:     size += 12;
                   1574:   if (op1 && GET_MODE (op1) != opmode)
                   1575:     size += 12;
                   1576:   if (op2 && GET_MODE (op2) != opmode)
                   1577:     size += 12;
                   1578: 
                   1579:   /* 12 more if first and third operand types not the same. */
                   1580:   if (op2 && GET_MODE (op0) != GET_MODE (op2))
                   1581:     size += 12;
                   1582: 
                   1583:   /* CMP and CMPT need additional.  Also, compute size of save/restore here. */
                   1584:   if (code == EQ)
                   1585:     size += 32;
                   1586:   else if (code == GE)
                   1587:     size += 64;
                   1588:   else if (code == USE || code == CLOBBER)
                   1589:     {
                   1590:       /* 34 + 24 for each additional register plus 8 if fr7 saved.  (We
                   1591:          call it 36 because we need to keep the block length a multiple
                   1592:         of four.  */
                   1593:       size = 36 - 24;
                   1594:       for (i = 0; i <= 7; i++)
                   1595:        if (INTVAL (op0) & (1 << (7-i)))
                   1596:          size += 24 + 8 * (i == 7);
                   1597:     }
                   1598: 
                   1599:   /* We provide no general-purpose scratch registers.  */
                   1600:   size +=16;
                   1601: 
                   1602:   /* No floating-point scratch registers are provided.  Compute extra
                   1603:      length due to this.  This logic is that shown in the referenced
                   1604:      appendix.  */
                   1605: 
                   1606:   i = 0;
                   1607:   if (op0 && GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
                   1608:     i++;
                   1609:   if (op1 && GET_CODE (op1) == REG && FP_REGNO_P (REGNO (op1)))
                   1610:     i++;
                   1611:   if (op2 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
                   1612:     i++;
                   1613: 
                   1614:   if ((op0 == 0 || GET_CODE (op0) != REG || REGNO(op0) != 17)
                   1615:       && (op1 == 0 || GET_CODE (op1) != REG || REGNO(op1) != 17)
                   1616:       && (op2 == 0 || GET_CODE (op2) != REG || REGNO(op2) != 17))
                   1617:     fr0_avail = 1;
                   1618: 
                   1619:   if (dyadic)
                   1620:     {
                   1621:       if (i == 0)
                   1622:        size += fr0_avail ? 64 : 112;
                   1623:       else if (fpop->noperands == 2 && i == 1)
                   1624:        size += fr0_avail ? 0 : 64;
                   1625:       else if (fpop->noperands == 3)
                   1626:        {
                   1627:          if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0))
                   1628:              && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
                   1629:            {
                   1630:              if (REGNO (op0) == REGNO (op2))
                   1631: #if 1
                   1632:                /* This triggers a bug on the RT. */
                   1633:                abort ();
                   1634: #else
                   1635:                size += fr0_avail ? 0 : 64;
                   1636: #endif
                   1637:            }
                   1638:          else
                   1639:            {
                   1640:              i = 0;
                   1641:              if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
                   1642:                i++;
                   1643:              if (GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
                   1644:                i++;
                   1645:              if (i == 0)
                   1646:                size += fr0_avail ? 64 : 112;
                   1647:              else if (i == 1)
                   1648:                size += fr0_avail ? 0 : 64;
                   1649:            }
                   1650:        }
                   1651:     }
                   1652:   else if (code != USE && code != CLOBBER
                   1653:           && (GET_CODE (op0) != REG || ! FP_REGNO_P (REGNO (op0))))
                   1654:     size += 64;
                   1655:     
                   1656:   if (! TARGET_FULL_FP_BLOCKS)
                   1657:     {
                   1658:       /* If we are not to pad the blocks, just compute its actual length.  */
                   1659:       size = 12;       /* Header + opcode */
                   1660:       if (code == USE || code == CLOBBER)
                   1661:         size += 2;
                   1662:       else
                   1663:         {
                   1664:          if (op0) size += 2;
                   1665:          if (op1) size += 2;
                   1666:          if (op2) size += 2;
                   1667:        }
                   1668: 
                   1669:       /* If in the middle of a word, round.  */
                   1670:       if (size % UNITS_PER_WORD)
                   1671:        size += 2;
                   1672:        
                   1673:       /* Handle any immediates.  */
                   1674:       if (code != USE && code != CLOBBER && op0 && GET_CODE (op0) != REG)
                   1675:         size += 4;
                   1676:       if (op1 && GET_CODE (op1) != REG)
                   1677:         size += 4;
                   1678:       if (op2 && GET_CODE (op2) != REG)
                   1679:         size += 4;
                   1680: 
                   1681:       if (code != USE && code != CLOBBER && 
                   1682:          op0 && GET_CODE (op0) == CONST_DOUBLE && GET_MODE (op0) == DFmode)
                   1683:         size += 4;
                   1684:       if (op1 && GET_CODE (op1) == CONST_DOUBLE && GET_MODE (op1) == DFmode)
                   1685:         size += 4;
                   1686:       if (op2 && GET_CODE (op2) == CONST_DOUBLE && GET_MODE (op2) == DFmode)
                   1687:         size += 4;
                   1688:     }
                   1689: 
                   1690:   /* Done with size computation!  Chain this in. */
                   1691:   fpop->size = size;
                   1692:   data_offset += size / UNITS_PER_WORD;
                   1693:   fpop->next_in_mem = 0;
                   1694:   fpop->next_same_hash = 0;
                   1695: 
                   1696:   if (last_fpop_in_mem)
                   1697:     last_fpop_in_mem->next_in_mem = fpop;
                   1698:   else
                   1699:     first_fpop = fpop;
                   1700:   last_fpop_in_mem = fpop;
                   1701: 
                   1702:   if (last_fpop)
                   1703:     last_fpop->next_same_hash = fpop;
                   1704:   else
                   1705:     fp_hash_table[hash] = fpop;
                   1706: 
                   1707: win:
                   1708:   /* FPOP describes the operation to be performed.  Return a string to branch
                   1709:      to it.  */
                   1710:   if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
                   1711:     sprintf (outbuf, "cal r15,%d(r14)\n\tbalr%s r15,r15",
                   1712:             fpop->mem_offset * UNITS_PER_WORD,
                   1713:             dbr_sequence_length () ? "x" : "");
                   1714:   else
                   1715:     sprintf (outbuf, "get r15,$L%dF%d\n\tbalr%s r15,r15",
                   1716:             subr_number, fpop->mem_offset * UNITS_PER_WORD,
                   1717:             dbr_sequence_length () ? "x" : "");
                   1718:   return outbuf;
                   1719: }
                   1720: 
                   1721: /* If necessary, output a floating-point operation to save or restore all
                   1722:    floating-point registers.
                   1723: 
                   1724:    file is the file to write the operation to, CODE is USE for save, CLOBBER
                   1725:    for restore, and ADDR is the address of the same area, as RTL.  */
                   1726: 
                   1727: static void
                   1728: output_loadsave_fpregs (file, code, addr)
                   1729:      FILE *file;
                   1730:      enum rtx_code code;
                   1731:      rtx addr;
                   1732: {
                   1733:   register int i;
                   1734:   register int mask = 0;
                   1735: 
                   1736:   for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
                   1737:     if (regs_ever_live[i + 17])
                   1738:       mask |= 1 << (7 - i);
                   1739: 
                   1740:   if (mask)
                   1741:     fprintf (file, "\t%s\n",
                   1742:             output_fpop (code, gen_rtx (CONST_INT, VOIDmode, mask),
                   1743:                                gen_rtx (MEM, Pmode, addr),
                   1744:                                0, const0_rtx));
                   1745: 
                   1746: }
                   1747: 
                   1748: /* Output any floating-point operations at the end of the routine.  */
                   1749: 
                   1750: static void
                   1751: output_fpops (file)
                   1752:      FILE *file;
                   1753: {
                   1754:   register struct fp_op *fpop;
                   1755:   register int size_so_far;
                   1756:   register int i;
                   1757:   rtx immed[3];
                   1758: 
                   1759:   if (first_fpop == 0)
                   1760:     return;
                   1761: 
                   1762:   data_section ();
                   1763: 
                   1764:   ASM_OUTPUT_ALIGN (file, 2);
                   1765: 
                   1766:   for (fpop = first_fpop; fpop; fpop = fpop->next_in_mem)
                   1767:     {
                   1768:       if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
                   1769:        fprintf (file, "# data area offset = %d\n",
                   1770:                 fpop->mem_offset * UNITS_PER_WORD);
                   1771:       else
                   1772:        fprintf (file, "L%dF%d:\n",
                   1773:                 subr_number, fpop->mem_offset * UNITS_PER_WORD);
                   1774: 
                   1775:       fprintf (file, "\tcas r0,r15,r0\n");
                   1776:       fprintf (file, "\t.long FPGLUE\n");
                   1777:       switch (fpop->opcode)
                   1778:        {
                   1779:        case USE:
                   1780:          fprintf (file, "\t.byte 0x1d\t# STOREM\n");
                   1781:          break;
                   1782:        case CLOBBER:
                   1783:          fprintf (file, "\t.byte 0x0f\t# LOADM\n");
                   1784:          break;
                   1785:        case ABS:
                   1786:          fprintf (file, "\t.byte 0x00\t# ABS\n");
                   1787:          break;
                   1788:        case PLUS:
                   1789:          fprintf (file, "\t.byte 0x02\t# ADD\n");
                   1790:          break;
                   1791:        case EQ:
                   1792:          fprintf (file, "\t.byte 0x07\t# CMP\n");
                   1793:          break;
                   1794:        case GE:
                   1795:          fprintf (file, "\t.byte 0x08\t# CMPT\n");
                   1796:          break;
                   1797:        case DIV:
                   1798:          fprintf (file, "\t.byte 0x0c\t# DIV\n");
                   1799:          break;
                   1800:        case SET:
                   1801:          fprintf (file, "\t.byte 0x14\t# MOVE\n");
                   1802:          break;
                   1803:        case MULT:
                   1804:          fprintf (file, "\t.byte 0x15\t# MUL\n");
                   1805:          break;
                   1806:        case NEG:
                   1807:          fprintf (file, "\t.byte 0x16\t# NEG\n");
                   1808:          break;
                   1809:        case SQRT:
                   1810:          fprintf (file, "\t.byte 0x1c\t# SQRT\n");
                   1811:          break;
                   1812:        case MINUS:
                   1813:          fprintf (file, "\t.byte 0x1e\t# SUB\n");
                   1814:          break;
                   1815:        default:
                   1816:          abort ();
                   1817:        }
                   1818: 
                   1819:       fprintf (file, "\t.byte %d\n", fpop->noperands);
                   1820:       fprintf (file, "\t.short 0x8001\n");
                   1821:       
                   1822:       if ((fpop->ops[0] == 0
                   1823:           || GET_CODE (fpop->ops[0]) != REG || REGNO(fpop->ops[0]) != 17)
                   1824:          && (fpop->ops[1] == 0 || GET_CODE (fpop->ops[1]) != REG
                   1825:              || REGNO(fpop->ops[1]) != 17)
                   1826:          && (fpop->ops[2] == 0 || GET_CODE (fpop->ops[2]) != REG
                   1827:              || REGNO(fpop->ops[2]) != 17))
                   1828:        fprintf (file, "\t.byte %d, 0x80\n", fpop->size);
                   1829:       else
                   1830:        fprintf (file, "\t.byte %d, 0\n", fpop->size);
                   1831:       size_so_far = 12;
                   1832:       for (i = 0; i < fpop->noperands; i++)
                   1833:        {
                   1834:          register int type;
                   1835:          register int opbyte;
                   1836:          register char *desc0;
                   1837:          char desc1[50];
                   1838: 
                   1839:          immed[i] = 0;
                   1840:          switch (GET_MODE (fpop->ops[i]))
                   1841:            {
                   1842:            case SImode:
                   1843:            case VOIDmode:
                   1844:              desc0 = "int";
                   1845:              type = 0;
                   1846:              break;
                   1847:            case SFmode:
                   1848:              desc0 = "float";
                   1849:              type = 2;
                   1850:              break;
                   1851:            case DFmode:
                   1852:              desc0 = "double";
                   1853:              type = 3;
                   1854:              break;
                   1855:            default:
                   1856:              abort ();
                   1857:            }
                   1858: 
                   1859:          switch (GET_CODE (fpop->ops[i]))
                   1860:            {
                   1861:            case REG:
                   1862:              strcpy(desc1, reg_names[REGNO (fpop->ops[i])]);
                   1863:              if (FP_REGNO_P (REGNO (fpop->ops[i])))
                   1864:                {
                   1865:                  type += 0x10;
                   1866:                  opbyte = REGNO (fpop->ops[i]) - 17;
                   1867:                }
                   1868:              else
                   1869:                {
                   1870:                  type += 0x00;
                   1871:                  opbyte = REGNO (fpop->ops[i]);
                   1872:                  if (type == 3)
                   1873:                    opbyte = (opbyte << 4) + opbyte + 1;
                   1874:                }
                   1875:              break;
                   1876: 
                   1877:            case MEM:
                   1878:              type += 0x30;
                   1879:              if (GET_CODE (XEXP (fpop->ops[i], 0)) == PLUS)
                   1880:                {
                   1881:                  immed[i] = XEXP (XEXP (fpop->ops[i], 0), 1);
                   1882:                  opbyte = REGNO (XEXP (XEXP (fpop->ops[i], 0), 0));
                   1883:                  if (GET_CODE (immed[i]) == CONST_INT)
                   1884:                    sprintf (desc1, "%d(%s)", INTVAL (immed[i]),
                   1885:                             reg_names[opbyte]);
                   1886:                  else
                   1887:                    sprintf (desc1, "<memory> (%s)", reg_names[opbyte]);
                   1888:                }
                   1889:              else if (GET_CODE (XEXP (fpop->ops[i], 0)) == REG)
                   1890:                {
                   1891:                  opbyte = REGNO (XEXP (fpop->ops[i], 0));
                   1892:                  immed[i] = const0_rtx;
                   1893:                  sprintf (desc1, "(%s)", reg_names[opbyte]);
                   1894:                }
                   1895:              else
                   1896:                {
                   1897:                  immed[i] = XEXP (fpop->ops[i], 0);
                   1898:                  opbyte = 0;
                   1899:                  sprintf(desc1, "<memory>");
                   1900:                }
                   1901:              break;
                   1902: 
                   1903:            case CONST_INT:
                   1904:            case CONST_DOUBLE:
                   1905:            case CONST:
                   1906:            case SYMBOL_REF:
                   1907:            case LABEL_REF:
                   1908:              type += 0x20;
                   1909:              opbyte = 0;
                   1910:              immed[i] = fpop->ops[i];
                   1911:              desc1[0] = '$';
                   1912:              desc1[1] = '\0';
                   1913:              break;
                   1914: 
                   1915:            default:
                   1916:              abort ();
                   1917:            }
                   1918: 
                   1919:          /* Save/restore is special.  */
                   1920:          if (i == 0 && (fpop->opcode == USE || fpop->opcode == CLOBBER))
                   1921:            type = 0xff, opbyte = INTVAL (fpop->ops[0]), immed[i] = 0;
                   1922: 
                   1923:          fprintf (file, "\t.byte 0x%x,0x%x # (%s) %s\n",
                   1924:                   type, opbyte, desc0, desc1);
                   1925: 
                   1926:          size_so_far += 2;
                   1927:        }
                   1928: 
                   1929:       /* If in the middle of a word, round.  */
                   1930:       if (size_so_far % UNITS_PER_WORD)
                   1931:        {
                   1932:          fprintf (file, "\t.space 2\n");
                   1933:          size_so_far += 2;
                   1934:        }
                   1935: 
                   1936:       for (i = 0; i < fpop->noperands; i++)
                   1937:        if (immed[i])
                   1938:          switch (GET_MODE (immed[i]))
                   1939:            {
                   1940:            case SImode:
                   1941:            case VOIDmode:
                   1942:              size_so_far += 4;
                   1943:              fprintf (file, "\t.long ");
                   1944:              output_addr_const (file, immed[i]);
                   1945:              fprintf (file, "\n");
                   1946:              break;
                   1947: 
                   1948:            case DFmode:
                   1949:              size_so_far += 4;
                   1950:            case SFmode:
                   1951:              size_so_far += 4;
                   1952:              if (GET_CODE (immed[i]) == CONST_DOUBLE)
                   1953:                {
                   1954:                  union real_extract u;
                   1955: 
1.1.1.3 ! root     1956:                  bcopy ((char *) &CONST_DOUBLE_LOW (immed[i]),
        !          1957:                         (char *) &u, sizeof u);
1.1       root     1958:                  if (GET_MODE (immed[i]) == DFmode)
                   1959:                    ASM_OUTPUT_DOUBLE (file, u.d);
                   1960:                  else
                   1961:                    ASM_OUTPUT_FLOAT (file, u.d);
                   1962:                }
                   1963:              else
                   1964:                abort ();
                   1965:              break;
                   1966: 
                   1967:            default:
                   1968:              abort ();
                   1969:            }
                   1970:        
                   1971:       if (size_so_far != fpop->size)
                   1972:         {
                   1973:           if (TARGET_FULL_FP_BLOCKS)
                   1974:            fprintf (file, "\t.space %d\n", fpop->size - size_so_far);
                   1975:          else
                   1976:            abort ();
                   1977:        }
                   1978:     }
                   1979: 
                   1980:   /* Update for next subroutine.  */
                   1981:   subr_number++;
                   1982:   text_section ();
                   1983: }
                   1984: 
                   1985:  /* Initialize floating-point operation table.  */
                   1986: 
                   1987: static void
                   1988: init_fpops()
                   1989: {
                   1990:   register int i;
                   1991: 
                   1992:   first_fpop = last_fpop_in_mem = 0;
                   1993:   for (i = 0; i < FP_HASH_SIZE; i++)
                   1994:     fp_hash_table[i] = 0;
                   1995: }
1.1.1.2   root     1996: 
                   1997: /* Return the offset value of an automatic variable (N_LSYM) having
                   1998:    the given offset. Basically, we correct by going from a frame pointer to
                   1999:    stack pointer value.
                   2000: */
                   2001: 
                   2002: int
                   2003: romp_debugger_auto_correction(offset)
                   2004:      int offset;
                   2005: {
                   2006:   int fp_to_sp;
                   2007: 
                   2008:   /* We really want to go from STACK_POINTER_REGNUM to
                   2009:      FRAME_POINTER_REGNUM, but this isn't defined. So go the other
                   2010:      direction and negate. */
                   2011:   INITIAL_ELIMINATION_OFFSET (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM,
                   2012:                              fp_to_sp);
                   2013: 
                   2014:   /* The offset value points somewhere between the frame pointer and
                   2015:      the stack pointer. What is up from the frame pointer is down from the
                   2016:      stack pointer. Therefore the negation in the offset value too. */
                   2017: 
                   2018:   return -(offset+fp_to_sp+4);
                   2019: }
                   2020: 
                   2021: /* Return the offset value of an argument having
                   2022:    the given offset. Basically, we correct by going from a arg pointer to
                   2023:    stack pointer value. */
                   2024: 
                   2025: int
                   2026: romp_debugger_arg_correction (offset)
                   2027:      int offset;
                   2028: {
                   2029:   int fp_to_argp;
                   2030: 
                   2031:   INITIAL_ELIMINATION_OFFSET (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM,
                   2032:                              fp_to_argp);
                   2033: 
                   2034:   /* Actually, something different happens if offset is from a floating-point
                   2035:      register argument, but we don't handle it here.  */
                   2036: 
                   2037:   return (offset - fp_to_argp);
                   2038: }

unix.superglobalmegacorp.com

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