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