|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.