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

1.1       root        1: /* Subroutines for assembler code output on the DSP1610.
1.1.1.2 ! root        2:    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
1.1       root        3:    Contributed by Michael Collison ([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.2 ! root       19: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
1.1       root       21: 
                     22: /* Some output-actions in dsp1600.md need these.  */
                     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 "tree.h"
                     35: #include "expr.h"
                     36: #include "flags.h"
                     37: 
                     38: char *text_seg_name;
                     39: char *rsect_text;
                     40: char *data_seg_name;
                     41: char *rsect_data;
                     42: char *bss_seg_name;
                     43: char *rsect_bss;
                     44: char *const_seg_name;
                     45: char *rsect_const;
                     46: 
                     47: char *chip_name;
                     48: char *save_chip_name;
                     49: 
                     50: /* Save the operands of a compare. The 16xx has not lt or gt, so
                     51:    in these cases we swap the operands and reverse the condition */
                     52: 
                     53: rtx dsp16xx_compare_op0;
                     54: rtx dsp16xx_compare_op1;
                     55: struct rtx_def *(*dsp16xx_compare_gen)();
                     56: 
                     57: static char *fp;
                     58: static char *sp;
                     59: static char *rr;
                     60: static char *a1h;
                     61: 
                     62: struct dsp16xx_frame_info current_frame_info;
                     63: struct dsp16xx_frame_info zero_frame_info;
                     64: 
                     65: rtx dsp16xx_addhf3_libcall = (rtx) 0;
                     66: rtx dsp16xx_subhf3_libcall = (rtx) 0;
                     67: rtx dsp16xx_mulhf3_libcall = (rtx) 0;
                     68: rtx dsp16xx_divhf3_libcall = (rtx) 0;
                     69: rtx dsp16xx_cmphf3_libcall = (rtx) 0;
                     70: rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;
                     71: rtx dsp16xx_floathihf2_libcall = (rtx) 0;
                     72: rtx dsp16xx_neghf2_libcall = (rtx) 0;
                     73: 
                     74: rtx dsp16xx_mulhi3_libcall = (rtx) 0;
                     75: rtx dsp16xx_udivqi3_libcall = (rtx) 0;
                     76: rtx dsp16xx_udivhi3_libcall = (rtx) 0;
                     77: rtx dsp16xx_divqi3_libcall = (rtx) 0;
                     78: rtx dsp16xx_divhi3_libcall = (rtx) 0;
                     79: rtx dsp16xx_modqi3_libcall = (rtx) 0;
                     80: rtx dsp16xx_modhi3_libcall = (rtx) 0;
                     81: rtx dsp16xx_umodqi3_libcall = (rtx) 0;
                     82: rtx dsp16xx_umodhi3_libcall = (rtx) 0;
                     83: rtx dsp16xx_ashrhi3_libcall = (rtx) 0;
                     84: rtx dsp16xx_ashlhi3_libcall = (rtx) 0;
                     85: rtx dsp16xx_ucmphi2_libcall = (rtx) 0;
                     86: rtx dsp16xx_lshrhi3_libcall = (rtx) 0;
                     87: 
                     88: char *himode_reg_name[] = HIMODE_REGISTER_NAMES;
                     89: 
                     90: #define SHIFT_INDEX_1   0
                     91: #define SHIFT_INDEX_4   1
                     92: #define SHIFT_INDEX_8   2
                     93: #define SHIFT_INDEX_16  3
                     94: 
                     95: static char *ashift_right_asm[] = 
                     96: {
                     97:   "%0=%0>>1",
                     98:   "%0=%0>>4",
                     99:   "%0=%0>>8",
                    100:   "%0=%0>>16"
                    101: };
                    102: 
                    103: static char *ashift_right_asm_first[] = 
                    104: {
                    105:   "%0=%1>>1",
                    106:   "%0=%1>>4",
                    107:   "%0=%1>>8",
                    108:   "%0=%1>>16"
                    109: };
                    110: 
                    111: static char *ashift_left_asm[] = 
                    112: {
                    113:   "%0=%0<<1",
                    114:   "%0=%0<<4",
                    115:   "%0=%0<<8",
                    116:   "%0=%0<<16"
                    117: };
                    118: 
                    119: static char *ashift_left_asm_first[] = 
                    120: {
                    121:   "%0=%1<<1",
                    122:   "%0=%1<<4",
                    123:   "%0=%1<<8",
                    124:   "%0=%1<<16"
                    125: };
                    126: 
                    127: static char *lshift_right_asm[] = 
                    128: {
                    129:   "%0=%0>>1\n\t%0=%b0&0x7fff",
                    130:   "%0=%0>>4\n\t%0=%b0&0x0fff",
                    131:   "%0=%0>>8\n\t%0=%b0&0x00ff",
                    132:   "%0=%0>>16\n\t%0=%b0&0x0000"
                    133: };
                    134: 
                    135: static char *lshift_right_asm_first[] = 
                    136: {
                    137:   "%0=%1>>1\n\t%0=%b0&0x7fff",
                    138:   "%0=%1>>4\n\t%0=%b0&0x0fff",
                    139:   "%0=%1>>8\n\t%0=%b0&0x00ff",
                    140:   "%0=%1>>16\n\t%0=%b0&0x0000"
                    141: };
                    142: 
                    143: int 
                    144: hard_regno_mode_ok (regno, mode)
                    145: int regno;
                    146: enum machine_mode mode;
                    147: {
                    148:   switch ((int) mode)
                    149:     {
                    150:     case VOIDmode:
                    151:       return 1;
                    152:       
                    153:       /* 
                    154:        We can't use the c0-c2 for QImode, since they are only
                    155:        8 bits in length */
                    156: 
                    157:     case QImode:
                    158:       if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2)
                    159:        return 1;
                    160:       else
                    161:        return 0;
                    162:       
                    163:       /* We only allow a0, a1, y, and p to be allocated for 32-bit modes.
                    164:          Additionally we allow the virtual ybase registers to be used for 32-bit
                    165:         modes. */
                    166:       
                    167:     case HFmode:
                    168:     case SFmode:
                    169:     case DFmode:
                    170:     case XFmode:
                    171:     case HImode:
                    172:     case SImode:
                    173:     case DImode:
                    174:       if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD
                    175:          || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0)))
                    176:        return 1;
                    177:       else
                    178:        return 0;
                    179:       
                    180:     default:
                    181:       return 0;
                    182:     }
                    183: }
                    184: 
                    185: enum reg_class
                    186: dsp16xx_reg_class_from_letter (c)
                    187: int c;
                    188: {
                    189:   switch (c)
                    190:     {
                    191:     case 'A':
                    192:       return ACCUM_REGS;
                    193:       
                    194:     case 'h':
                    195:       return ACCUM_HIGH_REGS;
                    196:       
                    197:     case 'j':
                    198:       return A0H_REG;
                    199:       
                    200:     case 'k':
                    201:       return A0L_REG;
                    202:       
                    203:     case 'q':
                    204:       return A1H_REG;
                    205:       
                    206:     case 'u':
                    207:       return A1L_REG;
                    208:       
                    209:     case 'x':
                    210:       return X_REG;
                    211: 
                    212:     case 'y':
                    213:       return YH_REG;
                    214: 
                    215:     case 'z':
                    216:       return YL_REG;
                    217: 
                    218:     case 't':
                    219:       return P_REG;
                    220: 
                    221:     case 'Z':
                    222:       return Y_OR_P_REGS;
                    223: 
                    224:     case 'd':
                    225:       return ACCUM_Y_OR_P_REGS;
                    226: 
                    227:     case 'C':
                    228:       return NO_FRAME_Y_ADDR_REGS;
                    229: 
                    230:     case 'a':
                    231:       return Y_ADDR_REGS;
                    232: 
                    233:     case 'B':
                    234:       return (TARGET_BMU ? BMU_REGS : NO_REGS);
                    235: 
                    236:     case 'Y':
                    237:       return YBASE_VIRT_REGS;
                    238: 
                    239:     case 'v':
                    240:       return PH_REG;
                    241: 
                    242:     case 'w':
                    243:       return PL_REG;
                    244: 
                    245:     case 'W':
                    246:       return J_REG;
                    247: 
                    248:     case 'e':
                    249:       return YBASE_ELIGIBLE_REGS;
                    250: 
                    251:     case 'b':
                    252:       return ACCUM_LOW_REGS;
                    253: 
                    254:     case 'c':
                    255:       return NON_YBASE_REGS;
                    256: 
                    257:     case 'f':
                    258:       return Y_REG;
                    259: 
                    260:     case 'D':
                    261:       return SLOW_MEM_LOAD_REGS;
                    262: 
                    263:     default:
1.1.1.2 ! root      264:       fatal ("Invalid register class letter %c", c);
1.1       root      265:       return NO_REGS;
                    266:     }
                    267: }
                    268: /* Return the class number of the smallest class containing
                    269:    reg number REGNO. */
                    270: 
                    271: int 
                    272: regno_reg_class(regno)
                    273: int regno;
                    274: {
                    275:   switch (regno)
                    276:     {
                    277:     case REG_A0L:
                    278:       return (int) A0L_REG;
                    279:     case REG_A1L:
                    280:       return (int) A1L_REG;
                    281:       
                    282:     case REG_A0:
                    283:       return (int) A0H_REG;
                    284:     case REG_A1:
                    285:       return (int) A1H_REG;
                    286:       
                    287:     case REG_X:
                    288:       return (int) X_REG;
                    289:       
                    290:     case REG_Y:
                    291:       return (int) YH_REG;
                    292:     case REG_YL:
                    293:       return (int) YL_REG;
                    294:       
                    295:     case REG_PROD:
                    296:       return (int) PH_REG;
                    297:     case REG_PRODL:
                    298:       return (int) PL_REG;
                    299:       
                    300:     case REG_R0: case REG_R1: case REG_R2: case REG_R3:
                    301:       return (int) Y_ADDR_REGS;
                    302:       
                    303:     case REG_J:
                    304:       return (int) J_REG;
                    305:     case REG_K:
                    306:       return (int) GENERAL_REGS;
                    307:       
                    308:     case REG_YBASE:
                    309:       return (int) GENERAL_REGS;
                    310:       
                    311:     case REG_PT:
                    312:       return (int) GENERAL_REGS;
                    313:       
                    314:     case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3:
                    315:       return (int) BMU_REGS;
                    316:       
                    317:     case REG_C0: case REG_C1: case REG_C2:
                    318:       return (int) GENERAL_REGS;
                    319:       
                    320:     case REG_PR:
                    321:       return (int) GENERAL_REGS;
                    322:       
                    323:     case REG_RB:
                    324:       return (int) GENERAL_REGS;
                    325:       
                    326:     case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3:
                    327:     case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7:
                    328:     case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11:
                    329:     case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15:
                    330:     case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19:
                    331:     case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23:
                    332:     case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27:
                    333:     case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31:
                    334:       return (int) YBASE_VIRT_REGS;
                    335:       
                    336:     default:
                    337:       return (int) NO_REGS;
                    338:     }
                    339: }
                    340: 
                    341: /* A C expression for the maximum number of consecutive registers of class CLASS
                    342:    needed to hold a value of mode MODE */
                    343: 
                    344: int
                    345: class_max_nregs(class, mode)
                    346: enum reg_class class;
                    347: enum machine_mode mode;
                    348: {
                    349:     return (GET_MODE_SIZE(mode));
                    350: }
                    351: 
                    352: enum reg_class
                    353: limit_reload_class (mode, class)
                    354: enum machine_mode mode;
                    355: enum reg_class class;
                    356: {
                    357:   switch ((int) class)
                    358:     {
                    359:     case NO_REGS:
                    360:     case A0H_REG:
                    361:     case A0L_REG:
                    362:     case A0_REG:
                    363:     case A1H_REG:
                    364:       return class;
                    365: 
                    366:     case ACCUM_HIGH_REGS:
                    367:       fatal ("ACCUM_HIGH_REGS class in limit_reload_class");
                    368: 
                    369:     case A1L_REG:
                    370:     case ACCUM_LOW_REGS:
                    371:     case A1_REG:
                    372:       return class;
                    373: 
                    374:     case ACCUM_REGS:
                    375:       if (GET_MODE_SIZE(mode) == 1)
                    376:        return ACCUM_LOW_REGS;
                    377:       else
                    378:        return class;
                    379: 
                    380:     case X_REG:
                    381:     case X_OR_ACCUM_LOW_REGS:
                    382:       return class;
                    383: 
                    384:     case X_OR_ACCUM_REGS:
                    385:       if (GET_MODE_SIZE(mode) == 1)
                    386:        return X_OR_ACCUM_LOW_REGS;
                    387:       else
                    388:        return class;
                    389: 
                    390:     case YH_REG:
                    391:       return class;
                    392: 
                    393:     case YH_OR_ACCUM_HIGH_REGS:
                    394:       fatal ("YH_OR_ACCUM_HIGH_REGS found in limit_reload_class");
                    395: 
                    396:     case X_OR_YH_REGS:
                    397:       return class;
                    398: 
                    399:     case YL_REG:
1.1.1.2 ! root      400:       /* Register 'yl' is invalid for QImode, so we should never
1.1       root      401:         see it. */
                    402: 
                    403:       fatal ("YL found in limit_reload_class");
                    404: 
                    405:     case YL_OR_ACCUM_LOW_REGS:
                    406:     case X_OR_YL_REGS:
                    407:       return class;
                    408: 
                    409:     case Y_REG:
                    410:       if (GET_MODE_SIZE(mode) > 1)
                    411:        return class;
                    412:       else
                    413:        return YH_REG;
                    414: 
                    415:     case ACCUM_OR_Y_REGS:
                    416:       if (GET_MODE_SIZE(mode) > 1)
                    417:        return class;
                    418:       else
                    419:        return YL_OR_ACCUM_LOW_REGS;
                    420: 
                    421:     case PH_REG:
                    422:     case X_OR_PH_REGS:
                    423:     case PL_REG:
                    424:     case PL_OR_ACCUM_LOW_REGS:
                    425:     case X_OR_PL_REGS:
                    426:       return class;
                    427: 
                    428:     case P_REG:
                    429:       if (GET_MODE_SIZE(mode) > 1)
                    430:        return class;
                    431:       else
                    432:        return PL_REG;
                    433: 
                    434:     case ACCUM_OR_P_REGS:
                    435:       if (GET_MODE_SIZE(mode) > 1)
                    436:        return class;
                    437:       else
                    438:        return PL_OR_ACCUM_LOW_REGS;
                    439: 
                    440:     case YL_OR_P_REGS:
                    441:     case ACCUM_LOW_OR_YL_OR_P_REGS:
                    442:       return class;
                    443: 
                    444:     case Y_OR_P_REGS:
                    445:       return class;
                    446: 
                    447:     case ACCUM_Y_OR_P_REGS:
                    448:       if (GET_MODE_SIZE(mode) > 1)
                    449:        return class;
                    450:       else
                    451:        return ACCUM_LOW_OR_YL_OR_P_REGS;
                    452: 
                    453:     case NO_FRAME_Y_ADDR_REGS:
                    454:     case Y_ADDR_REGS: 
                    455:     case ACCUM_LOW_OR_Y_ADDR_REGS:
                    456:       return class;
                    457: 
                    458:     case ACCUM_OR_Y_ADDR_REGS:
                    459:       if (GET_MODE_SIZE(mode) > 1)
                    460:        return ACCUM_REGS;
                    461:       else
                    462:        return ACCUM_LOW_OR_Y_ADDR_REGS;
                    463: 
                    464:     case X_OR_Y_ADDR_REGS:
                    465:       return class;
                    466: 
                    467:     case Y_OR_Y_ADDR_REGS:
                    468:     case P_OR_Y_ADDR_REGS:
                    469:     case NON_HIGH_YBASE_ELIGIBLE_REGS:
                    470: 
                    471:     case J_REG:
                    472:       return class;
                    473: 
                    474:     case YBASE_ELIGIBLE_REGS:
                    475:       if (GET_MODE_SIZE(mode) > 1)
                    476:        return ACCUM_Y_P_OR_YBASE_REGS;
                    477:       else
                    478:        return NON_HIGH_YBASE_ELIGIBLE_REGS;
                    479: 
                    480:     case J_OR_DAU_16_BIT_REGS:
                    481:       if (GET_MODE_SIZE(mode) == 1)
                    482:        return J_REG;
                    483:       else
                    484:        return class;
                    485: 
                    486:     case BMU_REGS:
                    487:     case NOHIGH_NON_ADDR_REGS:
                    488:       return class;
                    489: 
                    490:     case NON_ADDR_REGS:
                    491:       if (GET_MODE_SIZE(mode) > 1)
                    492:        return class;
                    493:       else
                    494:        return NOHIGH_NON_ADDR_REGS;
                    495: 
                    496:     case NOHIGH_NON_YBASE_REGS:
                    497:       return class;
                    498: 
                    499:     case NON_YBASE_REGS:
                    500:       if (GET_MODE_SIZE(mode) > 1)
                    501:        return class;
                    502:       else
                    503:        return NOHIGH_NON_YBASE_REGS;
                    504: 
                    505:     case YBASE_VIRT_REGS:
                    506:     case ACCUM_LOW_OR_YBASE_REGS:
                    507:       return class;
                    508:       
                    509:     case ACCUM_OR_YBASE_REGS:
                    510:       if (GET_MODE_SIZE(mode) > 1)
                    511:        return class;
                    512:       else
                    513:        return ACCUM_LOW_OR_YBASE_REGS;
                    514: 
                    515:     case X_OR_YBASE_REGS:
                    516:       return class;
                    517: 
                    518:     case Y_OR_YBASE_REGS:
                    519:     case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
                    520:     case P_OR_YBASE_REGS:
                    521:       return class;
                    522: 
                    523:     case ACCUM_Y_P_OR_YBASE_REGS:
                    524:       return ACCUM_LOW_YL_PL_OR_YBASE_REGS;
                    525: 
                    526:     case Y_ADDR_OR_YBASE_REGS:
                    527:     case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
                    528:       return class;
                    529: 
                    530:     case YBASE_OR_YBASE_ELIGIBLE_REGS:
                    531:       if (GET_MODE_SIZE(mode) > 1)
                    532:        return class;
                    533:       else
                    534:        return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS;
                    535: 
                    536:     case NO_HIGH_ALL_REGS:
                    537:       return class;
                    538: 
                    539:     case ALL_REGS:
                    540:       if (GET_MODE_SIZE(mode) > 1)
                    541:        return class;
                    542:       else
                    543:        return NO_HIGH_ALL_REGS;
                    544: 
                    545:     default:
                    546:       return class;
                    547:     }
                    548: }
                    549: 
                    550: int
                    551: dsp16xx_register_move_cost (from, to)
                    552: enum reg_class from, to;
                    553: {
                    554: #if 0
                    555:   if (from == NO_REGS || to == NO_REGS || (from == to))
                    556:     return 2;
                    557: #endif
                    558: 
                    559:   if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
                    560:       from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
                    561:       from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
                    562:     {
                    563:       if (to == Y_REG || to == P_REG)
                    564:        return 4;
                    565:       else
                    566:        return 2;
                    567:     }
                    568: 
                    569:   if (to == A0H_REG || to == A0L_REG || to == A0_REG ||
                    570:       to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG ||
                    571:       to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS)
                    572:     {
                    573:       return 2;
                    574:     }
                    575: 
                    576: #if 0
                    577:   if (from == YBASE_VIRT_REGS)
                    578:     {
                    579:       if (to == X_REG || to == YH_REG || to == YL_REG ||
                    580:          to == Y_REG || to == PL_REG || to == PH_REG ||
                    581:          to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
                    582:          to == Y_OR_P_REGS)
                    583:        {
                    584:          return 2;
                    585:        }
                    586:       else
                    587:        return 4;
                    588:     }
                    589: 
                    590:   if (to == YBASE_VIRT_REGS)
                    591:     {
                    592:       if (from == X_REG || from == YH_REG || from == YL_REG ||
                    593:          from == Y_REG || from == PL_REG || from == PH_REG ||
                    594:          from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
                    595:          from == Y_OR_P_REGS)
                    596:        {
                    597:          return 2;
                    598:        }
                    599:       else
                    600:        return 4;
                    601:     }
                    602: #endif
                    603:   return 4;
                    604: }
                    605: 
                    606: /* Given an rtx X being reloaded into a reg required to be
                    607:    in class CLASS, return the class of reg to actually use.
                    608:    In general this is just CLASS; but on some machines
                    609:    in some cases it is preferable to use a more restrictive class.
                    610:    Also, we must ensure that a PLUS is reloaded either
                    611:    into an accumulator or an address register.  */
                    612: 
                    613: enum reg_class
                    614: preferred_reload_class (x, class)
                    615:      rtx x;
                    616:      enum reg_class class;
                    617: {
                    618:   /* The ybase registers cannot have constants copied directly
                    619:      to them. */
                    620: 
                    621:   if (CONSTANT_P (x))
                    622:     {
                    623:       if (class == ALL_REGS)
                    624:        return NON_YBASE_REGS;
                    625:     }
                    626: 
                    627:   if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE
                    628:       && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
                    629:     return YBASE_ELIGIBLE_REGS;
                    630: 
                    631:   if (GET_CODE (x) == PLUS)
                    632:     {
                    633:       if (GET_MODE (x) == QImode
                    634:          && REG_P (XEXP (x,0))
                    635:          && (XEXP (x,0) == frame_pointer_rtx
                    636:              || XEXP (x,0) == stack_pointer_rtx)
                    637:          && (GET_CODE (XEXP (x,1)) == CONST_INT))
                    638:        {
                    639:          if (class == ACCUM_HIGH_REGS)
                    640:            return class;
                    641: 
                    642:          if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
                    643:            return ACCUM_HIGH_REGS;
                    644: 
                    645:          /* We will use accumulator 'a1l' for reloading a
                    646:             PLUS. We can only use one accumulator because
                    647:             'reload_inqi' only allows one alternative to be
                    648:             used. */
                    649: 
                    650:          else if (class == ACCUM_LOW_REGS)
                    651:            return A1L_REG;
                    652:          else if (class == A0L_REG)
                    653:            return NO_REGS;
                    654:          else
                    655:            return class;
                    656:        }
                    657: 
                    658:       if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS)
                    659:        return Y_ADDR_REGS;
                    660:       else
                    661:        return class;
                    662:     }
                    663:   else if (GET_CODE (x) == MEM)
                    664:     {
                    665:       if (class == ALL_REGS)
                    666:        {
                    667: #if 0
                    668:          if (GET_MODE(x) == HImode)
                    669:            return NO_ACCUM_NON_YBASE_REGS;
                    670:          else
                    671: #endif
                    672:            return NON_YBASE_REGS;
                    673:        }
                    674:       else
                    675:        return class;
                    676:     }
                    677:   else
                    678:     return class;
                    679: }
                    680:        
                    681: /* Return the register class of a scratch register needed to copy IN into
                    682:    or out of a register in CLASS in MODE.  If it can be done directly,
                    683:    NO_REGS is returned.  */
                    684: 
                    685: enum reg_class
                    686: secondary_reload_class (class, mode, in)
                    687:      enum reg_class class;
                    688:      enum machine_mode mode;
                    689:      rtx in;
                    690: {
                    691:   int regno = -1;
                    692: 
                    693:   if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
                    694:     regno = true_regnum (in);
                    695: 
                    696:   if (class == ACCUM_HIGH_REGS 
                    697:       || class == ACCUM_LOW_REGS
                    698:       || class == A1L_REG
                    699:       || class == A0L_REG
                    700:       || class == A1H_REG
                    701:       || class == A0H_REG)
                    702:     {
                    703:       if (GET_CODE (in) == PLUS && mode == QImode)
                    704:        {
                    705:          rtx addr0 = XEXP (in, 0);
                    706:          rtx addr1 = XEXP (in, 1);
                    707:          
                    708:          /* If we are reloading a plus (reg:QI) (reg:QI)
                    709:             we need an additional register. */ 
                    710:          if (REG_P (addr0) && REG_P (addr1))
                    711:            return NO_REGS;
                    712:        }
                    713:     }
                    714: 
                    715:   /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
                    716:      into anything.  */
                    717: 
                    718:   if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS ||
                    719:        class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG ||
                    720:        class == A1H_REG || class == A1_REG) || 
                    721:       (regno >= REG_A0 && regno < REG_A1L + 1))
                    722:     return NO_REGS;
                    723: 
                    724:   /* We can copy the ybase registers into:
                    725:      r0-r3, a0-a1, y, p, & x or the union of
                    726:      any of these. */
                    727: 
                    728:   if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno))
                    729:     {
                    730:       switch ((int) class)
                    731:        {
                    732:        case (int) X_REG:
                    733:        case (int) X_OR_ACCUM_LOW_REGS:
                    734:        case (int) X_OR_ACCUM_REGS:
                    735:        case (int) YH_REG:
                    736:        case (int) YH_OR_ACCUM_HIGH_REGS:
                    737:        case (int) X_OR_YH_REGS:
                    738:        case (int) YL_REG:
                    739:        case (int) YL_OR_ACCUM_LOW_REGS:
                    740:        case (int) X_OR_Y_REGS:
                    741:        case (int) X_OR_YL_REGS:
                    742:        case (int) Y_REG:
                    743:        case (int) ACCUM_OR_Y_REGS:
                    744:        case (int) PH_REG:
                    745:        case (int) X_OR_PH_REGS:
                    746:        case (int) PL_REG:
                    747:        case (int) PL_OR_ACCUM_LOW_REGS:
                    748:        case (int) X_OR_PL_REGS:
                    749:        case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
                    750:        case (int) P_REG:
                    751:        case (int) ACCUM_OR_P_REGS:
                    752:        case (int) YL_OR_P_REGS:
                    753:        case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
                    754:        case (int) Y_OR_P_REGS:
                    755:        case (int) ACCUM_Y_OR_P_REGS:
                    756:        case (int) Y_ADDR_REGS:
                    757:        case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
                    758:        case (int) ACCUM_OR_Y_ADDR_REGS:
                    759:        case (int) X_OR_Y_ADDR_REGS:
                    760:        case (int) Y_OR_Y_ADDR_REGS:
                    761:        case (int) P_OR_Y_ADDR_REGS:
                    762:        case (int) YBASE_ELIGIBLE_REGS:
                    763:          return NO_REGS;
                    764: 
                    765:        default:
                    766:          return ACCUM_HIGH_REGS;
                    767:        }
                    768:     }
                    769: 
                    770:   /* We can copy r0-r3, a0-a1, y, & p
                    771:      directly to the ybase registers. In addition
                    772:      we can use any of the ybase virtual registers
                    773:      as the secondary reload registers when copying
                    774:      between any of these registers. */
                    775: 
                    776:   if (!TARGET_RESERVE_YBASE && regno != -1)
                    777:     {
                    778:       switch (regno)
                    779:        {
                    780:        case REG_A0:
                    781:        case REG_A0L:
                    782:        case REG_A1:
                    783:        case REG_A1L:
                    784:        case REG_X:
                    785:        case REG_Y:
                    786:        case REG_YL:
                    787:        case REG_PROD:
                    788:        case REG_PRODL:
                    789:        case REG_R0:
                    790:        case REG_R1:
                    791:        case REG_R2:
                    792:        case REG_R3:
                    793:          if (class == YBASE_VIRT_REGS)
                    794:            return NO_REGS;
                    795:          else
                    796:            {
                    797:              switch ((int) class)
                    798:                {
                    799:                case (int) X_REG:
                    800:                case (int) X_OR_ACCUM_LOW_REGS:
                    801:                case (int) X_OR_ACCUM_REGS:
                    802:                case (int) YH_REG:
                    803:                case (int) YH_OR_ACCUM_HIGH_REGS:
                    804:                case (int) X_OR_YH_REGS:
                    805:                case (int) YL_REG:
                    806:                case (int) YL_OR_ACCUM_LOW_REGS:
                    807:                case (int) X_OR_Y_REGS:
                    808:                case (int) X_OR_YL_REGS:
                    809:                case (int) Y_REG:
                    810:                case (int) ACCUM_OR_Y_REGS:
                    811:                case (int) PH_REG:
                    812:                case (int) X_OR_PH_REGS:
                    813:                case (int) PL_REG:
                    814:                case (int) PL_OR_ACCUM_LOW_REGS:
                    815:                case (int) X_OR_PL_REGS:
                    816:                case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
                    817:                case (int) P_REG:
                    818:                case (int) ACCUM_OR_P_REGS:
                    819:                case (int) YL_OR_P_REGS:
                    820:                case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
                    821:                case (int) Y_OR_P_REGS:
                    822:                case (int) ACCUM_Y_OR_P_REGS:
                    823:                case (int) Y_ADDR_REGS:
                    824:                case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
                    825:                case (int) ACCUM_OR_Y_ADDR_REGS:
                    826:                case (int) X_OR_Y_ADDR_REGS:
                    827:                case (int) Y_OR_Y_ADDR_REGS:
                    828:                case (int) P_OR_Y_ADDR_REGS:
                    829:                case (int) YBASE_ELIGIBLE_REGS:
                    830:                  return YBASE_VIRT_REGS;
                    831: 
                    832:                default:
                    833:                  break;
                    834:                }
                    835:            }
                    836:        }
                    837:     }
                    838: 
                    839:   /* Memory or constants can be moved from or to any register
                    840:      except the ybase virtual registers */
                    841:   if (regno == -1 && GET_CODE(in) != PLUS)
                    842:     {
                    843:       if (class == YBASE_VIRT_REGS)
                    844:        return NON_YBASE_REGS;
                    845:       else
                    846:         return NO_REGS;
                    847:     }
                    848: 
                    849:   if (GET_CODE (in) == PLUS && mode == QImode)
                    850:     {
                    851:       rtx addr0 = XEXP (in, 0);
                    852:       rtx addr1 = XEXP (in, 1);
                    853: 
                    854:       /* If we are reloading a plus (reg:QI) (reg:QI)
                    855:         we need a low accumulator, not a high one. */
                    856:       if (REG_P (addr0) && REG_P (addr1))
                    857:        return ACCUM_LOW_REGS;
                    858:     }
                    859: 
                    860: #if 0
                    861:   if (REG_P(in))
                    862:     return ACCUM_REGS;
                    863: #endif
                    864: 
                    865:   /* Otherwise, we need a high accumulator(s).  */
                    866:   return ACCUM_HIGH_REGS;
                    867: }
                    868: 
                    869: int
                    870: symbolic_address_operand (op, mode)
                    871: rtx op;
                    872: enum machine_mode mode;
                    873: {
                    874:     return (symbolic_address_p (op));
                    875: 
                    876: }
                    877: 
                    878: int symbolic_address_p (op)
                    879: rtx op;
                    880: {
                    881:   switch (GET_CODE (op))
                    882:     {
                    883:     case SYMBOL_REF:
                    884:     case LABEL_REF:
                    885:       return 1;
                    886: 
                    887:     case CONST:
                    888:       op = XEXP (op, 0);
                    889:       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
                    890:               || GET_CODE (XEXP (op, 0)) == LABEL_REF)
                    891:              && GET_CODE (XEXP (op, 1)) == CONST_INT
                    892:               && INTVAL (XEXP (op,1)) < 0x20);
                    893: 
                    894:     default:
                    895:       return 0;
                    896:     }
                    897: }
                    898: 
                    899: /* For a Y address space operand we allow only *rn, *rn++, *rn--.
                    900:    This routine only recognizes *rn, the '<>' constraints recognize
                    901:    *rn++, *rn-- */
                    902: 
                    903: int
                    904: Y_address_operand (op, mode)
                    905: rtx op;
                    906: enum machine_mode mode;
                    907: {
                    908:    return (memory_address_p (mode, op) && !symbolic_address_p (op));
                    909: }           
                    910: 
                    911: int
                    912: sp_operand (op, mode)
                    913: rtx op;
                    914: enum machine_mode mode;
                    915: {
                    916:     return (GET_CODE (op) == PLUS
                    917:            && (XEXP (op, 0) == stack_pointer_rtx
                    918:                || XEXP (op, 0) == frame_pointer_rtx)
                    919:            && GET_CODE (XEXP (op,1)) == CONST_INT);
                    920: }
                    921: 
                    922: int
                    923: sp_operand2 (op, mode)
                    924: rtx op;
                    925: enum machine_mode mode;
                    926: {
                    927:   if ((GET_CODE (op) == PLUS 
                    928:        && (XEXP (op, 0) == stack_pointer_rtx
                    929:           || XEXP (op, 0) == frame_pointer_rtx)
                    930:        && (REG_P (XEXP (op,1))
                    931:           && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
                    932:     return 1;
                    933:   else if ((GET_CODE (op) == PLUS
                    934:        && (XEXP (op, 1) == stack_pointer_rtx
                    935:           || XEXP (op, 1) == frame_pointer_rtx)
                    936:        && (REG_P (XEXP (op,0))
                    937:           && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
                    938:     return 1;
                    939:   else
                    940:     return 0;
                    941: }
                    942: 
                    943: int
                    944: nonmemory_arith_operand (op, mode)
                    945: rtx op;
                    946: enum machine_mode mode;
                    947: {
                    948:   return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
                    949: }
                    950: 
                    951: int
                    952: arith_reg_operand (op, mode)
                    953: rtx op;
                    954: enum machine_mode mode;
                    955: {
                    956:   return (register_operand (op, mode)
                    957:          && (GET_CODE (op) != REG
                    958:              || REGNO (op) >= FIRST_PSEUDO_REGISTER
                    959:              || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op)))
                    960:                  && REGNO (op) != FRAME_POINTER_REGNUM)));
                    961: }
                    962: 
                    963: int
                    964: call_address_operand (op, mode)
                    965: rtx op;
                    966: enum machine_mode mode;
                    967: {
                    968:     if (symbolic_address_p (op) || REG_P(op))
                    969:     {
                    970:        return 1;
                    971:     }
                    972: 
                    973:     return 0;
                    974: }
                    975: 
                    976: int
                    977: dsp16xx_comparison_operator (op, mode)
                    978:     register rtx op;
                    979:     enum machine_mode mode;
                    980: {
                    981:   return ((mode == VOIDmode || GET_MODE (op) == mode)
                    982:          && GET_RTX_CLASS (GET_CODE (op)) == '<'
                    983:          && (GET_CODE(op) != GE && GET_CODE (op) != LT &&
                    984:              GET_CODE (op) != GEU && GET_CODE (op) != LTU));
                    985: }
                    986: 
                    987: void
                    988: notice_update_cc(exp)
                    989: rtx exp;
                    990: {
                    991:     if (GET_CODE (exp) == SET)
                    992:     {
                    993:        /* Jumps do not alter the cc's.  */
                    994: 
                    995:        if (SET_DEST (exp) == pc_rtx)
                    996:            return;
                    997: 
                    998:        /* Moving register or memory into a register:
                    999:           it doesn't alter the cc's, but it might invalidate
                   1000:           the RTX's which we remember the cc's came from.
                   1001:           (Note that moving a constant 0 or 1 MAY set the cc's).  */
                   1002:        if (REG_P (SET_DEST (exp))
                   1003:            && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
                   1004:        {
                   1005:            if (cc_status.value1
                   1006:                && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
                   1007:                cc_status.value1 = 0;
                   1008:            if (cc_status.value2
                   1009:                && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
                   1010:                cc_status.value2 = 0;
                   1011:            return;
                   1012:        }
                   1013:        /* Moving register into memory doesn't alter the cc's.
                   1014:           It may invalidate the RTX's which we remember the cc's came from.  */
                   1015:        if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
                   1016:        {
                   1017:            if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
                   1018:                cc_status.value1 = 0;
                   1019:            if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
                   1020:                cc_status.value2 = 0;
                   1021:            return;
                   1022:        }
                   1023:        /* Function calls clobber the cc's.  */
                   1024:        else if (GET_CODE (SET_SRC (exp)) == CALL)
                   1025:        {
                   1026:            CC_STATUS_INIT;
                   1027:            return;
                   1028:        }
                   1029:        /* Tests and compares set the cc's in predictable ways.  */
                   1030:        else if (SET_DEST (exp) == cc0_rtx)
                   1031:        {
                   1032:            CC_STATUS_INIT;
                   1033:            cc_status.value1 = SET_SRC (exp);
                   1034:            return;
                   1035:        }
                   1036:        /* Certain instructions effect the condition codes. */
                   1037:        else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
                   1038:            switch( GET_CODE (SET_SRC (exp)) )
                   1039:            {
                   1040:            case PLUS: 
                   1041:            case MINUS:
                   1042:              if (REG_P (SET_DEST (exp)))
                   1043:                {
                   1044:                  /* Address registers don't set the condition codes */
                   1045:                  if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp))))
                   1046:                    {
                   1047:                      CC_STATUS_INIT;
                   1048:                      break;
                   1049:                    }
                   1050:                }
                   1051:            case ASHIFTRT: 
                   1052:            case LSHIFTRT:
                   1053:            case ASHIFT: 
                   1054:            case AND: 
                   1055:            case IOR: 
                   1056:            case XOR:
                   1057:            case MULT:
                   1058:            case NEG:
                   1059:            case NOT:
                   1060:              cc_status.value1 = SET_SRC (exp);
                   1061:              cc_status.value2 = SET_DEST (exp);
                   1062:              break;
                   1063:              
                   1064:            default:
                   1065:              CC_STATUS_INIT;
                   1066:            }
                   1067:        else
                   1068:        {
                   1069:            CC_STATUS_INIT;
                   1070:        }
                   1071:     }
                   1072:     else if (GET_CODE (exp) == PARALLEL
                   1073:             && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
                   1074:     {
                   1075:        if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
                   1076:            return;
                   1077: 
                   1078:        if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
                   1079:        {
                   1080:            CC_STATUS_INIT;
                   1081:            cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
                   1082:            return;
                   1083:        }
                   1084: 
                   1085:        CC_STATUS_INIT;
                   1086:     }
                   1087:     else
                   1088:     {
                   1089:        CC_STATUS_INIT;
                   1090:     }
                   1091: }
                   1092: 
                   1093: int
                   1094: dsp16xx_makes_calls ()
                   1095: {
                   1096:   rtx insn;
                   1097: 
                   1098:   for (insn = get_insns (); insn; insn = next_insn (insn))
                   1099:     if (GET_CODE (insn) == CALL_INSN)
                   1100:       return (1);
                   1101: 
                   1102:   return 0;
                   1103: }
                   1104: 
                   1105: long compute_frame_size (size)
                   1106: int size;
                   1107: {
                   1108:   long total_size;
                   1109:   long var_size;
                   1110:   long args_size;
                   1111:   long extra_size;
                   1112:   long reg_size;
                   1113: 
                   1114:   reg_size = 0;
                   1115:   extra_size = 0;
                   1116:   var_size = size;
                   1117:   args_size = current_function_outgoing_args_size;
                   1118:   reg_size = reg_save_size ();  
                   1119: 
                   1120:   total_size = var_size + args_size + extra_size + reg_size;
                   1121: 
                   1122: 
                   1123:   /* Save other computed information.  */
                   1124:   current_frame_info.total_size  = total_size;
                   1125:   current_frame_info.var_size    = var_size;
                   1126:   current_frame_info.args_size   = args_size;
                   1127:   current_frame_info.extra_size  = extra_size;
                   1128:   current_frame_info.reg_size    = reg_size;
                   1129:   current_frame_info.initialized = reload_completed;
                   1130:   current_frame_info.reg_size   = reg_size / UNITS_PER_WORD;
                   1131:   current_frame_info.function_makes_calls = dsp16xx_makes_calls ();
                   1132: 
                   1133:   if (reg_size)
                   1134:     {
                   1135:       unsigned long offset = args_size + var_size + reg_size;
                   1136:       current_frame_info.sp_save_offset = offset;
                   1137:       current_frame_info.fp_save_offset = offset - total_size;
                   1138:     }
                   1139: 
                   1140:   return total_size;
                   1141: }
                   1142: 
                   1143: int
                   1144: dsp16xx_call_saved_register (regno)
                   1145: int regno;
                   1146: {
                   1147:   return (regs_ever_live[regno] && !call_used_regs[regno] &&
                   1148:          !IS_YBASE_REGISTER_WINDOW(regno));
                   1149: 
                   1150: }
                   1151: 
                   1152: int
                   1153: ybase_regs_ever_used ()
                   1154: {
                   1155:   int regno;
                   1156:   int live = 0;
                   1157: 
                   1158:   for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++)
                   1159:     if (regs_ever_live[regno])
                   1160:       {
                   1161:        live = 1;
                   1162:        break;
                   1163:       }
                   1164: 
                   1165:   return live;
                   1166: }
                   1167: 
                   1168: void 
                   1169: function_prologue (file, size)
                   1170: FILE *file;
                   1171: int  size;
                   1172: {
                   1173:   int regno;
                   1174:   long total_size;
                   1175:   fp = reg_names[FRAME_POINTER_REGNUM];
                   1176:   sp = reg_names[STACK_POINTER_REGNUM];
                   1177:   rr = reg_names[RETURN_ADDRESS_REGNUM];   /* return address register */
                   1178:   a1h = reg_names[REG_A1];
                   1179:   
                   1180:   total_size = compute_frame_size (size);
                   1181:   
                   1182:   fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" );
                   1183:   fprintf (file, "\t/* total=%d, vars= %d, regs= %d, args=%d, extra= %d */\n",
                   1184:           current_frame_info.total_size,
                   1185:           current_frame_info.var_size,
                   1186:           current_frame_info.reg_size,
                   1187:           current_function_outgoing_args_size,
                   1188:           current_frame_info.extra_size);
                   1189:   
                   1190:   fprintf (file, "\t/* fp save offset= %d, sp save_offset= %d */\n\n",
                   1191:           current_frame_info.fp_save_offset,
                   1192:           current_frame_info.sp_save_offset);
                   1193:   /* Set up the 'ybase' register window. */
                   1194:   
                   1195:   if (ybase_regs_ever_used())
                   1196:     {
                   1197:       fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
                   1198:       if (TARGET_YBASE_HIGH)
                   1199:        fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
                   1200:       else
                   1201:        fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
                   1202:       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
                   1203:     }
                   1204:   
                   1205: #if 0
                   1206:   if (current_frame_info.function_makes_calls)
                   1207:     fprintf( file, "\t*%s++=%s\n", sp, rr );   /* Push return address */
                   1208: #endif
                   1209:   
                   1210:   
                   1211:   if (current_frame_info.var_size)
                   1212:     {
                   1213:       if (current_frame_info.var_size == 1)
                   1214:        fprintf (file, "\t*%s++\n", sp);
                   1215:       else
                   1216:         {
                   1217:          if(SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
                   1218:            fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]);
                   1219:          else
                   1220:            fatal ("Stack size > 32k");
                   1221:        }
                   1222:     }
                   1223:   
                   1224:   /* Save any registers this function uses, unless they are
                   1225:    * used in a call, in which case we don't need to
                   1226:    */
                   1227:   
                   1228:   for( regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno )
                   1229:     if (dsp16xx_call_saved_register (regno)) 
                   1230:       {
                   1231: #if OLD_REGISTER_SAVE
                   1232:        fprintf( file, "\t*%s++=%s\n", sp, reg_names[regno] );
                   1233: #else
                   1234:        fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[regno] );
                   1235: #endif
                   1236:       }
                   1237:   
                   1238:   if (current_frame_info.args_size)
                   1239:     {
                   1240:       if (current_frame_info.args_size == 1)
                   1241:        fprintf (file, "\t*%s++\n", sp);
                   1242:       else
                   1243:         {
                   1244:          if(SMALL_INTVAL(current_frame_info.args_size) && ((current_frame_info.args_size & 0x8000) == 0))
                   1245:            fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.args_size, sp, reg_names[REG_J]);
                   1246:          else
                   1247:            fatal ("Stack size > 32k");
                   1248:        }
                   1249:     }
                   1250:   
                   1251:   if (frame_pointer_needed)
                   1252:     {
                   1253:       fprintf( file, "\t%s=%s\n", a1h, sp );
                   1254:       fprintf( file, "\t%s=%s\n", fp, a1h );  /* Establish new base frame */
                   1255:       fprintf( file, "\t%s=%d\n", reg_names[REG_J], -total_size);
                   1256:       fprintf( file, "\t*%s++%s\n", fp, reg_names[REG_J]);
                   1257:     }
                   1258:   
                   1259:   fprintf( file, "\t/* END FUNCTION PROLOGUE: */\n\n" );
                   1260: }
                   1261: 
                   1262: void
                   1263: init_emulation_routines ()
                   1264: {
                   1265:  dsp16xx_addhf3_libcall = (rtx) 0;
                   1266:  dsp16xx_subhf3_libcall = (rtx) 0;
                   1267:  dsp16xx_mulhf3_libcall = (rtx) 0;
                   1268:  dsp16xx_divhf3_libcall = (rtx) 0;
                   1269:  dsp16xx_cmphf3_libcall = (rtx) 0;
                   1270:  dsp16xx_fixhfhi2_libcall = (rtx) 0;
                   1271:  dsp16xx_floathihf2_libcall = (rtx) 0;
                   1272:  dsp16xx_neghf2_libcall = (rtx) 0;
                   1273: 
                   1274:  dsp16xx_mulhi3_libcall = (rtx) 0;
                   1275:  dsp16xx_udivqi3_libcall = (rtx) 0;
                   1276:  dsp16xx_udivhi3_libcall = (rtx) 0;
                   1277:  dsp16xx_divqi3_libcall = (rtx) 0;
                   1278:  dsp16xx_divhi3_libcall = (rtx) 0;
                   1279:  dsp16xx_modqi3_libcall = (rtx) 0;
                   1280:  dsp16xx_modhi3_libcall = (rtx) 0;
                   1281:  dsp16xx_umodqi3_libcall = (rtx) 0;
                   1282:  dsp16xx_umodhi3_libcall = (rtx) 0;
                   1283:  dsp16xx_ashrhi3_libcall = (rtx) 0;
                   1284:  dsp16xx_ashlhi3_libcall = (rtx) 0;
                   1285:  dsp16xx_ucmphi2_libcall = (rtx) 0;
                   1286:  dsp16xx_lshrhi3_libcall = (rtx) 0;
                   1287: 
                   1288: }
                   1289: void
                   1290: function_epilogue (file, size)
                   1291: FILE *file;
                   1292: int   size;
                   1293: {
                   1294:   int regno;
                   1295:   int initial_stack_dec = 0;
                   1296:   
                   1297:   fp = reg_names[FRAME_POINTER_REGNUM];
                   1298:   sp = reg_names[STACK_POINTER_REGNUM];
                   1299:   rr = reg_names[RETURN_ADDRESS_REGNUM];   /* return address register */
                   1300:   a1h = reg_names[REG_A1];
                   1301:   
                   1302:   fprintf( file, "\n\t/* FUNCTION EPILOGUE: */\n" );
                   1303:   
                   1304:   if (current_frame_info.args_size)
                   1305:     {
                   1306:       if (current_frame_info.args_size == 1)
                   1307:        fprintf (file, "\t*%s--\n", sp);
                   1308:       else
                   1309:        {
                   1310:          fprintf (file, "\t%s=%d\n\t*%s++%s\n", 
                   1311:                   reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
                   1312:        }
                   1313:     }
                   1314:   
                   1315:   if (ybase_regs_ever_used())
                   1316:     {
                   1317:       fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
                   1318:       if (TARGET_YBASE_HIGH)
                   1319:        fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
                   1320:       else
                   1321:        fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
                   1322:       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
                   1323:     }
                   1324:   
                   1325:   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
                   1326:     if (dsp16xx_call_saved_register(regno))
                   1327:       {
                   1328: #if OLD_REGISTER_SAVE
                   1329:        if (!initial_stack_dec)
                   1330:          {
                   1331:            initial_stack_dec = 1;
                   1332:            fprintf (file, "\t*%s--\n", sp);
                   1333:          }
                   1334: #endif
                   1335: 
                   1336: #if OLD_REGISTER_SAVE
                   1337:        fprintf( file, "\t%s=*%s--\n", reg_names[regno], sp );
                   1338: #else
                   1339:        fprintf( file, "\t%s=pop(*%s)\n", reg_names[regno], sp );
                   1340: #endif
                   1341:       }
                   1342:   
                   1343:   /* If we restored any registers we have to account for the
                   1344:      initial pre-decrement. But only if we had any local variables
                   1345:      or spills. */
                   1346: #if OLD_REGISTER_SAVE  
                   1347:   if (initial_stack_dec) 
                   1348:     fprintf (file, "\t*%s++\n", sp);
                   1349: #endif
                   1350:   
                   1351:   if (current_frame_info.var_size)
                   1352:     {
                   1353:       if (current_frame_info.var_size == 1)
                   1354:        fprintf (file, "\t*%s--\n", sp);
                   1355:       else
                   1356:        {
                   1357:          fprintf (file, "\t%s=%d\n\t*%s++%s\n", 
                   1358:                   reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
                   1359:        }
                   1360:     }
                   1361:   
                   1362:   fprintf (file, "\treturn\n");
                   1363:   /* Reset the frame info for the next function */
                   1364:   current_frame_info = zero_frame_info;
                   1365:   init_emulation_routines ();
                   1366: }
                   1367: 
                   1368: /* Emit insns to move operands[1] into operands[0].
                   1369: 
                   1370:    Return 1 if we have written out everything that needs to be done to
                   1371:    do the move.  Otherwise, return 0 and the caller will emit the move
                   1372:    normally.  */
                   1373: 
                   1374: int
                   1375: emit_move_sequence (operands, mode)
                   1376:      rtx *operands;
                   1377:      enum machine_mode mode;
                   1378: {
                   1379:   register rtx operand0 = operands[0];
                   1380:   register rtx operand1 = operands[1];
                   1381: 
                   1382:   /* We can only store registers to memory.  */
                   1383: 
                   1384:   if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG)
                   1385:     operands[1] = force_reg (mode, operand1);
                   1386: 
                   1387:   return 0;
                   1388: }
                   1389: 
                   1390: void
                   1391: double_reg_from_memory (operands)
                   1392: rtx operands[];
                   1393: {
                   1394:     rtx xoperands[4];
                   1395: 
                   1396:     if (GET_CODE(XEXP(operands[1],0)) == POST_INC)
                   1397:     {
                   1398:        output_asm_insn ("%u0=%1", operands);
                   1399:        output_asm_insn ("%w0=%1", operands);
                   1400:     }
                   1401:     else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC)
                   1402:     {
                   1403:        xoperands[1] = XEXP (XEXP (operands[1], 0), 0);
                   1404:        xoperands[0] = operands[0];
                   1405:        
                   1406:        /* We can't use j anymore since the compiler can allocate it. */
                   1407: /*     output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
                   1408:        output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands);
                   1409:     }
                   1410:     else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
                   1411:     {
                   1412:       rtx addr;
                   1413:       rtx base;
                   1414:       int offset;
                   1415: 
                   1416:       output_asm_insn ("%u0=%1", operands);
                   1417: 
                   1418: 
                   1419:       /* In order to print out the least significant word we must
                   1420:         use 'offset + 1'.  */
                   1421:       addr = XEXP (operands[1], 0);
                   1422:       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
                   1423:        offset = INTVAL(XEXP(addr,0)) + 1;
                   1424:       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
                   1425:        offset = INTVAL(XEXP(addr,1)) + 1;
                   1426: 
                   1427:       fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31);
                   1428:     }
                   1429:     else
                   1430:     {
                   1431:        xoperands[1] = XEXP(operands[1],0);
                   1432:        xoperands[0] = operands[0];
                   1433: 
                   1434:        output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands);
                   1435:     }
                   1436: }
                   1437: 
                   1438: 
                   1439: void
                   1440: double_reg_to_memory (operands)
                   1441: rtx operands[];
                   1442: {
                   1443:     rtx xoperands[4];
                   1444: 
                   1445:     if (GET_CODE(XEXP(operands[0],0)) == POST_INC)
                   1446:     {
                   1447:        output_asm_insn ("%0=%u1", operands);
                   1448:        output_asm_insn ("%0=%w1", operands);
                   1449:     }
                   1450:     else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC)
                   1451:     {
                   1452:        xoperands[0] = XEXP (XEXP (operands[0], 0), 0);
                   1453:        xoperands[1] = operands[1];
                   1454:        
                   1455:        /* We can't use j anymore since the compiler can allocate it. */
                   1456: 
                   1457: /*     output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */
                   1458:        output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands);
                   1459: 
                   1460:     }
                   1461:     else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
                   1462:     {
                   1463:       rtx addr;
                   1464:       int offset;
                   1465: 
                   1466:       output_asm_insn ("%0=%u1", operands);
                   1467: 
                   1468:       /* In order to print out the least significant word we must
                   1469:         use 'offset + 1'.  */
                   1470:       addr = XEXP (operands[0], 0);
                   1471:       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
                   1472:        offset = INTVAL(XEXP(addr,0)) + 1;
                   1473:       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
                   1474:        offset = INTVAL(XEXP(addr,1)) + 1;
                   1475:       else
1.1.1.2 ! root     1476:        fatal ("Invalid addressing mode");
1.1       root     1477: 
                   1478:       fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
                   1479:     }
                   1480:     else
                   1481:     {
                   1482:        xoperands[0] = XEXP(operands[0],0);
                   1483:        xoperands[1] = operands[1];
                   1484: 
                   1485:        output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands);
                   1486:     }
                   1487: }
                   1488: 
                   1489: void
                   1490: override_options ()
                   1491: {
                   1492:   if (chip_name == (char *) 0)
                   1493:     chip_name = DEFAULT_CHIP_NAME;
                   1494: 
                   1495:   if (text_seg_name == (char *) 0)
                   1496:     text_seg_name = DEFAULT_TEXT_SEG_NAME;
                   1497:   
                   1498:   if (data_seg_name == (char *) 0)
                   1499:     data_seg_name = DEFAULT_DATA_SEG_NAME;
                   1500:   
                   1501:   if (bss_seg_name == (char *) 0)
                   1502:     bss_seg_name = DEFAULT_BSS_SEG_NAME;
                   1503:   
                   1504:   if (const_seg_name == (char *) 0)
                   1505:     const_seg_name = DEFAULT_CONST_SEG_NAME;
                   1506:   
                   1507:   save_chip_name = (char *) xmalloc (strlen(chip_name) + 1);
                   1508:   strcpy (save_chip_name, chip_name);
                   1509: 
                   1510:   rsect_text = (char *) xmalloc (strlen(".rsect ") + 
                   1511:                                 strlen(text_seg_name) + 3);
                   1512:   rsect_data = (char *) xmalloc (strlen(".rsect ") + 
                   1513:                                 strlen(data_seg_name) + 3);
                   1514:   rsect_bss = (char *) xmalloc (strlen(".rsect ") + 
                   1515:                                strlen(bss_seg_name) + 3);
                   1516:   rsect_const = (char *) xmalloc (strlen(".rsect ") + 
                   1517:                                  strlen(const_seg_name) + 3);
                   1518:   
                   1519:   sprintf (rsect_text, ".rsect \"%s\"", text_seg_name);
                   1520:   sprintf (rsect_data, ".rsect \"%s\"", data_seg_name);
                   1521:   sprintf (rsect_bss,  ".rsect \"%s\"", bss_seg_name);
                   1522:   sprintf (rsect_const, ".rsect \"%s\"", const_seg_name);
                   1523:   
                   1524:   if (optimize)
                   1525:     {
                   1526:       if (TARGET_OPTIMIZE_SPEED)
                   1527:        {
                   1528:          flag_unroll_loops = 1;
                   1529:          flag_inline_functions = 1;
                   1530:        }
                   1531:     }
                   1532: }
                   1533: 
                   1534: enum rtx_code save_next_cc_user_code;
                   1535: 
                   1536: enum rtx_code
                   1537: next_cc_user_code (insn)
                   1538: rtx insn;
                   1539: {
                   1540:   if ( !(insn = next_cc0_user (insn)))
                   1541:     abort ();
                   1542:   else if (GET_CODE (insn) == JUMP_INSN
                   1543:           && GET_CODE (PATTERN (insn)) == SET
                   1544:           && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
                   1545:     return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
                   1546:   else if (GET_CODE (insn) == INSN
                   1547:           && GET_CODE (PATTERN (insn)) == SET
                   1548:           && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode))
                   1549:     return GET_CODE (SET_SRC (PATTERN (insn)));
                   1550:   else
                   1551:     abort ();
                   1552: }
                   1553: 
                   1554: void
                   1555: print_operand(file, op, letter)
                   1556: FILE *file;
                   1557: rtx op;
                   1558: int letter;
                   1559: {
                   1560:     enum rtx_code code;
                   1561: 
                   1562:     code = GET_CODE(op);
                   1563: 
                   1564:     switch (letter)
                   1565:     {
                   1566:        case 'I':
                   1567:          code = reverse_condition (code);
                   1568:          /* Fallthrough */
                   1569: 
                   1570:        case 'C':
                   1571:           if (code == EQ) 
                   1572:           { 
                   1573:              fputs ("eq", file); 
                   1574:              return; 
                   1575:          }
                   1576:           else if (code == NE)  
                   1577:          { 
                   1578:              fputs ("ne", file); 
                   1579:              return; 
                   1580:          }
                   1581:           else if (code == GT || code == GTU)  
                   1582:          { 
                   1583:              fputs ("gt", file); 
                   1584:              return; 
                   1585:          }
                   1586:           else if (code == LT || code == LTU)  
                   1587:          { 
                   1588:              fputs ("mi", file); 
                   1589:              return; 
                   1590:          }
                   1591:           else if (code == GE || code == GEU)  
                   1592:          {
                   1593:              fputs ("pl", file); 
                   1594:              return; 
                   1595:          }
                   1596:           else if (code == LE || code == LEU)  
                   1597:          { 
                   1598:              fputs ("le", file); 
                   1599:              return; 
                   1600:          }
                   1601:           else 
                   1602:              abort ();
                   1603:          break;
                   1604: 
                   1605:        default:
                   1606:           break;  
                   1607:     }
                   1608: 
                   1609:     if( code == REG )
                   1610:     {
                   1611:        /* Print the low half of a 32-bit register pair */
                   1612:         if (letter == 'w')
                   1613:            fprintf( file, "%s", reg_names[REGNO(op)+1] );
                   1614:         else if (letter == 'u' || !letter)
                   1615:            fprintf( file, "%s", reg_names[REGNO(op)]);
                   1616:        else if (letter == 'b')
                   1617:            fprintf ( file, "%sh", reg_names[REGNO(op)]);
                   1618:        else if (letter == 'm')
                   1619:          fprintf (file, "%s", himode_reg_name[REGNO(op)]);
                   1620:         else
                   1621:            fatal("Bad register extension code");
                   1622:     }
                   1623:     else if( code == MEM )
                   1624:         output_address( XEXP(op,0) );
                   1625:     else if( code == CONST_INT )
                   1626:     { 
                   1627:         if( letter == 'H' )
                   1628:             fprintf( file, "0x%x", (INTVAL(op) & 0xffff) );
                   1629:        else if (letter == 'h')
                   1630:             fprintf( file, "%d", INTVAL (op) );
                   1631:         else if( letter == 'U' )
                   1632:             fprintf( file, "0x%x", ((INTVAL(op) & 0xffff0000) >> 16) & 0xffff );
                   1633:         else
                   1634:            output_addr_const( file, op );
                   1635:     }
                   1636:     else if( code == CONST_DOUBLE && GET_MODE(op) != DImode )
                   1637:     {
                   1638:          union { double d; int i[2]; } u;
                   1639:          union { float f; int i; } u1;
                   1640:          u.i[0] = CONST_DOUBLE_LOW (op);
                   1641:          u.i[1] = CONST_DOUBLE_HIGH (op);
                   1642:          u1.f = u.d;
                   1643:           fprintf( file, "0x%x", u1.i );
                   1644:     }
                   1645:     else output_addr_const( file, op);
                   1646: }
                   1647: 
                   1648: 
                   1649: void
                   1650: print_operand_address(file, addr)
                   1651: FILE *file;
                   1652: rtx addr;
                   1653: {
                   1654:   rtx base;
                   1655:   int offset;
                   1656:   
                   1657:   switch (GET_CODE (addr))
                   1658:     {
                   1659:     case REG:
                   1660:       fprintf (file, "*%s", reg_names[REGNO (addr)]);
                   1661:       break;
                   1662:     case POST_DEC:
                   1663:       fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
                   1664:       break;
                   1665:     case POST_INC:
                   1666:       fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
                   1667:       break;
                   1668:     case PLUS:
                   1669:       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
                   1670:        offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1);
                   1671:       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
                   1672:        offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0);
                   1673:       if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
                   1674:        {
                   1675:          if (offset >= -31 && offset <= 0)
                   1676:            offset = 31 + offset;
                   1677:          else
1.1.1.2 ! root     1678:            fatal ("Invalid offset in ybase addressing");
1.1       root     1679:        }
                   1680:       else
1.1.1.2 ! root     1681:        fatal ("Invalid register in ybase addressing");
1.1       root     1682:       
                   1683:       fprintf (file, "*(%d)", offset);
                   1684:       break;
                   1685:       
                   1686:     default:
                   1687:       if( FITS_5_BITS( addr ) )
                   1688:        fprintf( file, "*(0x%x)", (INTVAL(addr) & 0x20) );
                   1689:       else
                   1690:        output_addr_const(file, addr);
                   1691:     }
                   1692: }
                   1693: 
                   1694: void
                   1695: output_dsp16xx_float_const(operands)
                   1696: rtx *operands;
                   1697: {
                   1698:   rtx dst = operands[0];
                   1699:   rtx src = operands[1];
                   1700:   
                   1701: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
                   1702:   REAL_VALUE_TYPE d;
                   1703:   long value;
                   1704:   
                   1705:   REAL_VALUE_FROM_CONST_DOUBLE (d, src);
                   1706:   REAL_VALUE_TO_TARGET_SINGLE (d, value);
                   1707:   
                   1708:   operands[1] = gen_rtx (CONST_INT, VOIDmode, value);
                   1709:   output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
                   1710: #else
                   1711:   fatal ("inline float constants not supported on this host");
                   1712: #endif
                   1713: }
                   1714: 
                   1715: int
                   1716: reg_save_size ()
                   1717: {
                   1718:   int reg_save_size = 0;
                   1719:  int regno;
                   1720:  
                   1721:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   1722:     if (dsp16xx_call_saved_register (regno))
                   1723:       {
                   1724:        reg_save_size += UNITS_PER_WORD;
                   1725:       }
                   1726: 
                   1727:   return (reg_save_size);
                   1728: }
                   1729: 
                   1730: int
                   1731: dsp16xx_starting_frame_offset()
                   1732: {
                   1733:   int reg_save_size = 0;
                   1734:  int regno;
                   1735:  
                   1736:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                   1737:     if (dsp16xx_call_saved_register (regno))
                   1738:       {
                   1739:        reg_save_size += UNITS_PER_WORD;
                   1740:       }
                   1741: 
                   1742:   return (reg_save_size);
                   1743: }
                   1744: 
                   1745: int
                   1746: initial_frame_pointer_offset()
                   1747: {
                   1748:   int frame_size;
                   1749:   int regno;
                   1750:   int offset = 0;
                   1751:   
                   1752:   offset = compute_frame_size (get_frame_size());
                   1753: 
                   1754: #ifdef STACK_GROWS_DOWNWARD
                   1755:   return (offset);
                   1756: #else
                   1757:   return (-offset);
                   1758: #endif
                   1759: }
                   1760: 
                   1761: /* Generate the minimum number of 1600 core shift instructions
                   1762:    to shift by 'shift_amount'. */
                   1763: 
                   1764: #if 0
                   1765: void
                   1766: emit_1600_core_shift (shift_op, operands, shift_amount, mode)
                   1767: enum rtx_code shift_op;
                   1768: rtx *operands;
                   1769: int shift_amount;
                   1770: enum machine_mode mode;
                   1771: {
                   1772:   int quotient;
                   1773:   int i;
                   1774:   int first_shift_emitted = 0;
                   1775:   
                   1776:   while (shift_amount != 0)
                   1777:     {
                   1778:       if (shift_amount/16)
                   1779:        {
                   1780:          quotient = shift_amount/16;
                   1781:          shift_amount = shift_amount - (quotient * 16);
                   1782:          for (i = 0; i < quotient; i++)
                   1783:            emit_insn (gen_rtx (SET, VOIDmode, operands[0],
                   1784:                                gen_rtx (shift_op, mode, 
                   1785:                                         first_shift_emitted ? operands[0] : operands[1],
                   1786:                                         gen_rtx (CONST_INT, VOIDmode, 16))));
                   1787:          first_shift_emitted = 1;
                   1788:        }
                   1789:       else if (shift_amount/8)
                   1790:        {
                   1791:          quotient = shift_amount/8;
                   1792:          shift_amount = shift_amount - (quotient * 8);
                   1793:          for (i = 0; i < quotient; i++)
                   1794:            emit_insn (gen_rtx (SET, VOIDmode, operands[0],
                   1795:                                gen_rtx (shift_op, mode, 
                   1796:                                         first_shift_emitted ? operands[0] : operands[1],
                   1797:                                         gen_rtx (CONST_INT, VOIDmode, 8))));
                   1798:          first_shift_emitted = 1;
                   1799:        }
                   1800:       else if (shift_amount/4)
                   1801:        {
                   1802:          quotient = shift_amount/4;
                   1803:          shift_amount = shift_amount - (quotient * 4);
                   1804:          for (i = 0; i < quotient; i++)
                   1805:            emit_insn (gen_rtx (SET, VOIDmode, operands[0],
                   1806:                                gen_rtx (shift_op, mode, 
                   1807:                                         first_shift_emitted ? operands[0] : operands[1],
                   1808:                                         gen_rtx (CONST_INT, VOIDmode, 4))));
                   1809:          first_shift_emitted = 1;
                   1810:        }
                   1811:       else if (shift_amount/1)
                   1812:        {
                   1813:          quotient = shift_amount/1;
                   1814:          shift_amount = shift_amount - (quotient * 1);
                   1815:          for (i = 0; i < quotient; i++)
                   1816:            emit_insn (gen_rtx (SET, VOIDmode, operands[0],
                   1817:                                gen_rtx (shift_op, mode, 
                   1818:                                         first_shift_emitted ? operands[0] : operands[1],
                   1819:                                         gen_rtx (CONST_INT, VOIDmode, 1))));
                   1820:          first_shift_emitted = 1;
                   1821:        }
                   1822:     }
                   1823: }
                   1824: #else
                   1825: void
                   1826: emit_1600_core_shift (shift_op, operands, shift_amount)
                   1827: enum rtx_code shift_op;
                   1828: rtx *operands;
                   1829: int shift_amount;
                   1830: {
                   1831:   int quotient;
                   1832:   int i;
                   1833:   int first_shift_emitted = 0;
                   1834:   char **shift_asm_ptr;
                   1835:   char **shift_asm_ptr_first;
                   1836: 
                   1837:   if (shift_op == ASHIFT)
                   1838:     {
                   1839:       shift_asm_ptr = ashift_left_asm;
                   1840:       shift_asm_ptr_first = ashift_left_asm_first;
                   1841:     }
                   1842:   else if (shift_op == ASHIFTRT)
                   1843:     {
                   1844:       shift_asm_ptr = ashift_right_asm;
                   1845:       shift_asm_ptr_first = ashift_right_asm_first;
                   1846:     }
                   1847:   else if (shift_op == LSHIFTRT)
                   1848:     {
                   1849:       shift_asm_ptr = lshift_right_asm;
                   1850:       shift_asm_ptr_first = lshift_right_asm_first;
                   1851:     }
                   1852:   else
1.1.1.2 ! root     1853:     fatal ("Invalid shift operator in emit_1600_core_shift");
1.1       root     1854: 
                   1855:   while (shift_amount != 0)
                   1856:     {
                   1857:       if (shift_amount/16)
                   1858:        {
                   1859:          quotient = shift_amount/16;
                   1860:          shift_amount = shift_amount - (quotient * 16);
                   1861:          for (i = 0; i < quotient; i++)
                   1862:            output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16]
                   1863:                              : shift_asm_ptr_first[SHIFT_INDEX_16]), operands);
                   1864:          first_shift_emitted = 1;
                   1865:        }
                   1866:       else if (shift_amount/8)
                   1867:        {
                   1868:          quotient = shift_amount/8;
                   1869:          shift_amount = shift_amount - (quotient * 8);
                   1870:          for (i = 0; i < quotient; i++)
                   1871:            output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8]
                   1872:                              : shift_asm_ptr_first[SHIFT_INDEX_8]), operands);
                   1873:          first_shift_emitted = 1;
                   1874:        }
                   1875:       else if (shift_amount/4)
                   1876:        {
                   1877:          quotient = shift_amount/4;
                   1878:          shift_amount = shift_amount - (quotient * 4);
                   1879:          for (i = 0; i < quotient; i++)
                   1880:            output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4]
                   1881:                              : shift_asm_ptr_first[SHIFT_INDEX_4]), operands);
                   1882:          first_shift_emitted = 1;
                   1883:        }
                   1884:       else if (shift_amount/1)
                   1885:        {
                   1886:          quotient = shift_amount/1;
                   1887:          shift_amount = shift_amount - (quotient * 1);
                   1888:          for (i = 0; i < quotient; i++)
                   1889:            output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1]
                   1890:                              : shift_asm_ptr_first[SHIFT_INDEX_1]), operands);
                   1891:          first_shift_emitted = 1;
                   1892:        }
                   1893:     }
                   1894: }
                   1895: #endif
                   1896: void
                   1897:   asm_output_common(file, name, size, rounded)
                   1898: FILE *file;
                   1899: char *name;
                   1900: int size;
                   1901: int rounded;
                   1902: {
                   1903:     bss_section ();
                   1904:     ASM_GLOBALIZE_LABEL (file, name);
                   1905:     assemble_name (file, name);
                   1906:     fputs (":", file);
                   1907:     if (rounded > 1)
                   1908:        fprintf (file, "%d * int\n", rounded);
                   1909:     else
                   1910:        fprintf (file, "int\n");
                   1911: }
                   1912: 
                   1913: void
                   1914: asm_output_local(file, name, size, rounded)
                   1915: FILE *file;
                   1916: char *name;
                   1917: int size;
                   1918: int rounded;
                   1919: {
                   1920:     bss_section ();
                   1921:     assemble_name (file, name);
                   1922:     fputs (":", file);
                   1923:     if (rounded > 1)
                   1924:        fprintf (file, "%d * int\n", rounded);
                   1925:     else
                   1926:        fprintf (file, "int\n");
                   1927: }
                   1928: 
                   1929: void
                   1930: asm_output_float (file, fp_const)
                   1931: FILE *file;
                   1932: double fp_const;
                   1933: {
                   1934: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
                   1935:       REAL_VALUE_TYPE d = fp_const;
                   1936:       long value;
                   1937: 
                   1938:       REAL_VALUE_TO_TARGET_SINGLE (d, value);
                   1939:       fputs ("\tint ", file);
                   1940: #ifdef WORDS_BIG_ENDIAN
                   1941:       fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff));
                   1942: #else
                   1943:       fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff);
                   1944: #endif
                   1945:       fputs ("\n", file);
                   1946: #else
                   1947:       fatal ("inline float constants not supported on this host");
                   1948: #endif
                   1949: }
                   1950: 
                   1951: void
                   1952: asm_output_long (file, value)
                   1953: FILE *file;
                   1954: long value;
                   1955: {
                   1956:       fputs ("\tint ", file);
                   1957: #ifdef WORDS_BIG_ENDIAN
                   1958:       fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff));
                   1959: #else
                   1960:       fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff);
                   1961: #endif
                   1962:       fputs ("\n", file);
                   1963: }
                   1964: 
                   1965: int
                   1966: dsp16xx_address_cost (addr)
                   1967: rtx addr;
                   1968: {
                   1969:     switch (GET_CODE (addr))
                   1970:     {
                   1971:          default:
                   1972:             break;
                   1973: 
                   1974:          case REG:
                   1975:             return 1;
                   1976: 
                   1977:          case CONST:
                   1978:             {
                   1979:                rtx offset = const0_rtx;
                   1980:                addr = eliminate_constant_term (addr, &offset);
                   1981: 
                   1982:                if (GET_CODE (addr) == LABEL_REF)
                   1983:                    return 2;
                   1984: 
                   1985:                if (GET_CODE (addr) != SYMBOL_REF)
                   1986:                    return 4;
                   1987: 
                   1988:                if (INTVAL (offset) == 0)
                   1989:                    return 2;
                   1990:              }
                   1991:             /* fall through */
                   1992: 
                   1993:          case POST_INC: case POST_DEC:
                   1994:             return (GET_MODE (addr) == QImode ? 1 : 2);
                   1995: 
                   1996:          case SYMBOL_REF: case LABEL_REF:
                   1997:             return 2;
                   1998: 
                   1999:          case PLUS:
                   2000:          {
                   2001:             register rtx plus0 = XEXP (addr, 0);
                   2002:             register rtx plus1 = XEXP (addr, 1);
                   2003:             
                   2004:             if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
                   2005:             {
                   2006:                 plus0 = XEXP (addr, 1);
                   2007:                 plus1 = XEXP (addr, 0);
                   2008:             }
                   2009:             
                   2010:             if (GET_CODE (plus0) != REG)
                   2011:                 break;
                   2012:             
                   2013:             switch (GET_CODE (plus1))
                   2014:             {
                   2015:                   default:
                   2016:                      break;
                   2017:                 
                   2018:                   case CONST_INT:
                   2019:                      return 4;
                   2020: 
                   2021:                   case CONST:
                   2022:                   case SYMBOL_REF:
                   2023:                   case LABEL_REF:
                   2024:                      return dsp16xx_address_cost (plus1) + 1;
                   2025:             }
                   2026:          }
                   2027:      }
                   2028:             
                   2029:      return 4;
                   2030: }
                   2031: 
                   2032: 
                   2033: /* Determine whether a function argument is passed in a register, and
                   2034:    which register.
                   2035: 
                   2036:    The arguments are CUM, which summarizes all the previous
                   2037:    arguments; MODE, the machine mode of the argument; TYPE,
                   2038:    the data type of the argument as a tree node or 0 if that is not known
                   2039:    (which happens for C support library functions); and NAMED,
                   2040:    which is 1 for an ordinary argument and 0 for nameless arguments that
                   2041:    correspond to `...' in the called function's prototype.
                   2042: 
                   2043:    The value of the expression should either be a `reg' RTX for the
                   2044:    hard register in which to pass the argument, or zero to pass the
                   2045:    argument on the stack.
                   2046: 
                   2047:    On the dsp1610 the first four words of args are normally in registers
                   2048:    and the rest are pushed. If we a long or on float mode, the argument
                   2049:    must begin on a even register boundary
                   2050: 
                   2051:    Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
                   2052:    For structures that are passed in memory, but could have been
                   2053:    passed in registers, we first load the structure into the
                   2054:    register, and then when the last argument is passed, we store
                   2055:    the registers into the stack locations.  This fixes some bugs
                   2056:    where GCC did not expect to have register arguments, followed */
                   2057: 
                   2058: 
                   2059: struct rtx_def *
                   2060: dsp16xx_function_arg (args_so_far, mode, type, named)
                   2061:      CUMULATIVE_ARGS args_so_far;
                   2062:      enum machine_mode mode;
                   2063:      tree type;
                   2064:      int named;
                   2065: {
                   2066:   if (TARGET_REGPARM)
                   2067:     {
                   2068:       if ((args_so_far & 1) != 0
                   2069:          && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
                   2070:        args_so_far++;
                   2071: 
                   2072:       if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
                   2073:        return gen_rtx (REG, mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
                   2074:       else
                   2075:        return (struct rtx_def *) 0;
                   2076:     }
                   2077:   else
                   2078:     return (struct rtx_def *) 0;
                   2079: }
                   2080: 
                   2081: /* Advance the argument to the next argument position.  */
                   2082: 
                   2083: void
                   2084: dsp16xx_function_arg_advance (cum, mode, type, named)
                   2085:      CUMULATIVE_ARGS *cum;     /* current arg information */
                   2086:      enum machine_mode mode;   /* current arg mode */
                   2087:      tree type;                        /* type of the argument or 0 if lib support */
                   2088:      int named;                        /* whether or not the argument was named */
                   2089: {
                   2090:   if (TARGET_REGPARM)
                   2091:     {
                   2092:       if ((*cum & 1) != 0
                   2093:          && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
                   2094:        *cum += 1;
                   2095: 
                   2096:       if (mode != BLKmode)
                   2097:        *cum += GET_MODE_SIZE (mode);
                   2098:       else
                   2099:        *cum += int_size_in_bytes (type);
                   2100:     }
                   2101: }
                   2102: 
                   2103: void
                   2104: dsp16xx_file_start ()
                   2105: {
                   2106:   fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name);
                   2107: #if 0
                   2108:        if (TARGET_BMU)
                   2109:                fprintf (asm_out_file, "#include <1610.h>\n");
                   2110: #endif
                   2111: }
                   2112: 
                   2113: rtx
                   2114: gen_tst_reg (x)
                   2115:      rtx x;
                   2116: {
                   2117:   enum machine_mode mode;
                   2118: 
                   2119:   mode = GET_MODE (x);
                   2120: 
                   2121:   if (mode == QImode)
                   2122:     {
                   2123:          emit_insn (gen_rtx (PARALLEL, VOIDmode,
                   2124:                        gen_rtvec (2,
                   2125:                                   gen_rtx (SET, VOIDmode, cc0_rtx, x),
                   2126:                                   gen_rtx (CLOBBER, VOIDmode,
                   2127:                                            gen_rtx (SCRATCH, QImode, 0)))));
                   2128:        }
                   2129:   else if (mode == HImode)
                   2130:     emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, x));
                   2131:   else
1.1.1.2 ! root     2132:     fatal ("Invalid mode for gen_tst_reg");
1.1       root     2133: 
                   2134:   return cc0_rtx;
                   2135: }
                   2136: 
                   2137: rtx
                   2138: gen_compare_reg (code, x, y)
                   2139:      enum rtx_code code;
                   2140:      rtx x, y;
                   2141: {
                   2142:   enum machine_mode mode;
                   2143: 
                   2144:   mode = GET_MODE (x);
                   2145:   /* For floating point compare insns, a call is generated so don't
                   2146:      do anything here. */
                   2147: 
                   2148:   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
                   2149:     return cc0_rtx;
                   2150: 
                   2151:   if (mode == QImode)
                   2152:     {
                   2153:       if (code == GTU || code == GEU ||
                   2154:          code == LTU || code == LEU)
                   2155:        {
                   2156:          emit_insn (gen_rtx (PARALLEL, VOIDmode,
                   2157:                        gen_rtvec (3,
                   2158:                                   gen_rtx (SET, VOIDmode, cc0_rtx,
                   2159:                                            gen_rtx (COMPARE, mode, x, y)),
                   2160:                                   gen_rtx (CLOBBER, VOIDmode,
                   2161:                                            gen_rtx (SCRATCH, QImode, 0)),
                   2162:                                   gen_rtx (CLOBBER, VOIDmode,
                   2163:                                            gen_rtx (SCRATCH, QImode, 0)))));
                   2164:        }
                   2165:       else
                   2166:        {
                   2167:          emit_insn (gen_rtx (PARALLEL, VOIDmode,
                   2168:                        gen_rtvec (3,
                   2169:                                   gen_rtx (SET, VOIDmode, cc0_rtx,
                   2170:                                            gen_rtx (COMPARE, mode, x, y)),
                   2171:                                   gen_rtx (CLOBBER, VOIDmode,
                   2172:                                            gen_rtx (SCRATCH, QImode, 0)),
                   2173:                                   gen_rtx (CLOBBER, VOIDmode,
                   2174:                                            gen_rtx (SCRATCH, QImode, 0)))));
                   2175:        }
                   2176:     }
                   2177:   else if (mode == HImode)
                   2178:     {
                   2179:       if (code == GTU || code == GEU ||
                   2180:          code == LTU || code == LEU)
                   2181:        {
                   2182: #if 1
                   2183:          emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
                   2184:                             gen_rtx (SET, VOIDmode, cc0_rtx, gen_rtx (COMPARE, VOIDmode, x, y)),
                   2185:                             gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
                   2186:                             gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
                   2187:                             gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
                   2188:                             gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)))));
                   2189: #else
                   2190:          if (!dsp16xx_ucmphi2_libcall)
                   2191:            dsp16xx_ucmphi2_libcall = gen_rtx (SYMBOL_REF, Pmode, UCMPHI2_LIBCALL);
                   2192:          emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2,
                   2193:                             x, HImode, y, HImode);
                   2194:          emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode))));
                   2195: #endif
                   2196:        }
                   2197:       else
                   2198:        emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
                   2199:                            gen_rtx (COMPARE, VOIDmode, force_reg(HImode, x), 
                   2200:                                     force_reg(HImode,y))));
                   2201:     }
                   2202:   else
1.1.1.2 ! root     2203:     fatal ("Invalid mode for integer comparison in gen_compare_reg");
1.1       root     2204: 
                   2205:   return cc0_rtx;
                   2206: }
                   2207: 
                   2208: char *
                   2209: output_block_move (operands)
                   2210:      rtx operands[];
                   2211: {
                   2212:   int loop_count = INTVAL(operands[2]);
                   2213:   rtx xoperands[4];
                   2214: 
                   2215:   fprintf (asm_out_file, "\tdo %d {\n", loop_count);
                   2216:   xoperands[0] = operands[4];
                   2217:   xoperands[1] = operands[1];
                   2218:   output_asm_insn ("%0=*%1++", xoperands);
                   2219: 
                   2220:   xoperands[0] = operands[0];
                   2221:   xoperands[1] = operands[4];
                   2222:   output_asm_insn ("*%0++=%1", xoperands);
                   2223: 
                   2224:   fprintf (asm_out_file, "\t}\n");
                   2225:   return "";
                   2226: }

unix.superglobalmegacorp.com

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