|
|
1.1 root 1: /* Subroutines for insn-output.c for MIL-STD-1750. 1.1.1.2 ! root 2: Copyright (C) 1994, 1995 Free Software Foundation, Inc. ! 3: Contributed by O.M.Kellogg, DASA ([email protected]) 1.1 root 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 1, 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: #ifndef FILE 23: #include <stdio.h> 24: #endif 1.1.1.2 ! root 25: #include <string.h> 1.1 root 26: 27: #define __datalbl 28: #include "config.h" 29: #include "rtl.h" 30: #include "tree.h" 31: #include "expr.h" 32: #define HAVE_cc0 33: #include "conditions.h" 34: #include "real.h" 35: 36: struct datalabel_array datalbl[DATALBL_ARRSIZ]; 37: int datalbl_ndx = -1; 38: struct jumplabel_array jmplbl[JMPLBL_ARRSIZ]; 39: int jmplbl_ndx = -1; 40: int label_pending = 0, program_counter = 0; 41: enum section current_section = Normal; 42: char *sectname[4] = 1.1.1.2 ! root 43: {"Init", "Normal", "Konst", "Static"}; 1.1 root 44: 45: int 46: notice_update_cc (exp) 47: rtx exp; 48: { 49: if (GET_CODE (exp) == SET) 50: { 51: enum rtx_code src_code = GET_CODE (SET_SRC (exp)); 52: /* Jumps do not alter the cc's. */ 53: if (SET_DEST (exp) == pc_rtx) 54: return; 1.1.1.2 ! root 55: /* Moving a register or constant into memory doesn't alter the cc's. */ ! 56: if (GET_CODE (SET_DEST (exp)) == MEM ! 57: && (src_code == REG || src_code == CONST_INT)) ! 58: return; 1.1 root 59: /* Function calls clobber the cc's. */ 1.1.1.2 ! root 60: if (src_code == CALL) 1.1 root 61: { 62: CC_STATUS_INIT; 63: return; 64: } 65: /* Emulated longword bit-ops leave cc's incorrect */ 1.1.1.2 ! root 66: if (GET_MODE (SET_DEST (exp)) == HImode ? 1.1 root 67: src_code == AND || src_code == IOR || 68: src_code == XOR || src_code == NOT : 0) 69: { 70: CC_STATUS_INIT; 71: return; 72: } 73: /* Tests and compares set the cc's in predictable ways. */ 1.1.1.2 ! root 74: if (SET_DEST (exp) == cc0_rtx) 1.1 root 75: { 76: CC_STATUS_INIT; 77: cc_status.value1 = SET_SRC (exp); 78: return; 79: } 1.1.1.2 ! root 80: /* Anything else will set cc_status. */ ! 81: cc_status.flags = CC_NO_OVERFLOW; ! 82: cc_status.value1 = SET_SRC (exp); ! 83: cc_status.value2 = SET_DEST (exp); ! 84: return; 1.1 root 85: } 86: else if (GET_CODE (exp) == PARALLEL 87: && GET_CODE (XVECEXP (exp, 0, 0)) == SET) 88: { 89: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) 90: return; 91: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) 92: { 93: CC_STATUS_INIT; 94: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); 95: return; 96: } 97: CC_STATUS_INIT; 98: } 99: else 100: { 101: CC_STATUS_INIT; 102: } 103: } 104: 105: 106: rtx 107: function_arg (cum, mode, type, named) 108: int cum; 109: enum machine_mode mode; 110: tree type; 111: int named; 112: { 113: int size; 114: rtx result; 115: 116: if (MUST_PASS_IN_STACK (mode, type)) 117: return (rtx) 0; 118: if (mode == BLKmode) 119: size = int_size_in_bytes (type); 120: else 121: size = GET_MODE_SIZE (mode); 122: if (cum + size < 12) 123: return gen_rtx (REG, mode, cum); 124: else 125: return (rtx) 0; 126: } 127: 128: 129: #ifndef STRDUP 130: char * 131: strdup (str) 132: char *str; 133: { 134: char *p; 135: if (str == NULL) 136: return NULL; 137: if ((p = (char *) malloc (strlen (str) + 1)) == NULL) 138: { 139: fprintf (stderr, "dynamic memory exhausted"); 140: abort (); 141: } 142: return strcpy (p, str); 143: } 144: 145: #endif 146: 147: 148: double 149: get_double (x) 150: rtx x; 151: { 152: union 153: { 154: double d; 155: long i[2]; 156: } 157: du; 158: 159: du.i[0] = CONST_DOUBLE_LOW (x); 160: du.i[1] = CONST_DOUBLE_HIGH (x); 161: return du.d; 162: } 163: 164: char * 165: float_label (code, value) 166: char code; 167: double value; 168: { 169: int i = 1; 170: static char label[32]; 171: char *p; 172: 173: label[0] = code; 174: p = label + 1; 175: sprintf (p, "%lf", value); 176: while (*p) 177: { 178: *p = (*p == '+') ? 'p' : 179: (*p == '-') ? 'm' : *p; 180: p++; 181: } 182: return strdup (label); 183: } 184: 185: 186: char * 1.1.1.2 ! root 187: movcnt_regno_adjust (op) ! 188: rtx *op; 1.1 root 189: { 190: static char outstr[40]; 191: int cntreg = REGNO (op[2]), cntreg_1750 = REGNO (op[0]) + 1; 192: int dstreg = REGNO (op[0]), srcreg = REGNO (op[1]); 193: 194: if (cntreg == cntreg_1750) 195: sprintf (outstr, "mov r%%0,r%%1"); 196: else if (dstreg + 1 == srcreg && srcreg == cntreg + 2) 197: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", cntreg, dstreg); 198: else if (dstreg + 1 == srcreg && srcreg < cntreg) 199: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, cntreg); 200: else if (srcreg + 1 == cntreg && dstreg > cntreg) 201: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, dstreg); 202: else 203: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,%%1\n\txwr r%d,r%d", 204: cntreg, cntreg_1750, cntreg_1750, cntreg); 205: return outstr; 206: } 207: 208: char * 1.1.1.2 ! root 209: mod_regno_adjust (instr, op) ! 210: char *instr; ! 211: rtx *op; 1.1 root 212: { 213: static char outstr[40]; 214: char *r = (!strncmp (instr, "dvr", 3) ? "r" : ""); 215: int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1; 216: 217: if (modregno_gcc == modregno_1750) 218: sprintf (outstr, "%s r%%0,%s%%2", instr, r); 219: else 220: sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d", 221: modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc); 222: return outstr; 223: } 224: 225: 226: /* Auxiliary to `nonindirect_operand': 227: Check if op is a valid memory operand for 1750A arith./logic (non-move) 228: instructions. */ 229: int 1.1.1.2 ! root 230: memop_valid (op) ! 231: rtx op; 1.1 root 232: { 233: if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode) 234: return 0; 235: switch (GET_CODE (op)) 236: { 237: case MEM: 238: case MINUS: 239: case MULT: 240: case DIV: 241: return 0; 242: case PLUS: 243: if (!memop_valid (XEXP (op, 0))) 244: return 0; 245: return memop_valid (XEXP (op, 1)); 246: case REG: 247: if (REGNO (op) > 0) 248: return 1; 249: return 0; 250: case CONST: 251: case CONST_INT: 252: case SYMBOL_REF: 253: case SUBREG: 254: return 1; 255: default: 256: printf ("memop_valid: code=%d\n", (int) GET_CODE (op)); 257: return 1; 258: } 259: } 260: 261: /* extra predicate for recog: */ 262: int 1.1.1.2 ! root 263: nonindirect_operand (op, mode) ! 264: rtx op; ! 265: enum machine_mode mode; 1.1 root 266: { 267: int retval; 268: 269: switch (GET_CODE (op)) 270: { 271: case MEM: 272: retval = memop_valid (XEXP (op, 0)); 273: return retval; 274: case REG: 275: return 1; 276: default: 277: if (!CONSTANT_P (op)) 278: return 0; 279: } 280: return 1; 281: } 282: 283: /* predicate for the STC instruction: */ 284: int 1.1.1.2 ! root 285: small_nonneg_const (op, mode) ! 286: rtx op; ! 287: enum machine_mode mode; 1.1 root 288: { 289: if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15) 290: return 1; 291: return 0; 292: } 293: 1.1.1.2 ! root 294: ! 295: /* predicate for 1750 `B' addressing mode (Base Register with Offset) ! 296: memory operand */ ! 297: int ! 298: b_mode_operand (op) ! 299: rtx op; ! 300: { ! 301: if (GET_CODE (op) == MEM) ! 302: { ! 303: rtx inner = XEXP (op, 0); ! 304: if (GET_CODE (inner) == PLUS) ! 305: { ! 306: rtx plus_op0 = XEXP (inner, 0); ! 307: if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0)) ! 308: { ! 309: rtx plus_op1 = XEXP (inner, 1); ! 310: if (GET_CODE (plus_op1) == CONST_INT ! 311: && INTVAL (plus_op1) >= 0 ! 312: && INTVAL (plus_op1) <= 255) ! 313: return 1; ! 314: } ! 315: } ! 316: } ! 317: return 0; ! 318: } ! 319: 1.1 root 320: /* Decide whether to output a conditional jump as a "Jump Conditional" 321: or as a "Branch Conditional": */ 322: 323: int 1.1.1.2 ! root 324: find_jmplbl (labelnum) ! 325: int labelnum; 1.1 root 326: { 327: int i, found = 0; 328: 329: for (i = 0; i <= jmplbl_ndx; i++) 330: if (labelnum == jmplbl[i].num) 331: { 332: found = 1; 333: break; 334: } 335: if (found) 336: return i; 337: return -1; 338: } 339: 340: char * 1.1.1.2 ! root 341: branch_or_jump (condition, targetlabel_number) ! 342: char *condition; ! 343: int targetlabel_number; 1.1 root 344: { 345: static char buf[30]; 346: int index; 347: 348: if ((index = find_jmplbl (targetlabel_number)) >= 0) 349: if (program_counter - jmplbl[index].pc < 128) 350: { 351: sprintf (buf, "b%s %%l0", condition); 352: return buf; 353: } 354: sprintf (buf, "jc %s,%%l0", condition); 355: return buf; 356: } 357: 358: 1.1.1.2 ! root 359: int ! 360: unsigned_comparison_operator (insn) ! 361: rtx insn; ! 362: { ! 363: switch (GET_CODE (insn)) ! 364: { ! 365: case GEU: ! 366: case GTU: ! 367: case LEU: ! 368: case LTU: ! 369: return 1; ! 370: default: ! 371: return 0; ! 372: } ! 373: } ! 374: ! 375: int ! 376: next_cc_user_is_unsigned (insn) ! 377: rtx insn; ! 378: { ! 379: if ( !(insn = next_cc0_user (insn))) ! 380: abort (); ! 381: else if (GET_CODE (insn) == JUMP_INSN ! 382: && GET_CODE (PATTERN (insn)) == SET ! 383: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) ! 384: return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0)); ! 385: else if (GET_CODE (insn) == INSN ! 386: && GET_CODE (PATTERN (insn)) == SET) ! 387: return unsigned_comparison_operator (SET_SRC (PATTERN (insn))); ! 388: else ! 389: abort (); ! 390: } ! 391: ! 392: 1.1 root 393: 394: /* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been 395: made functions: */ 396: 397: print_operand (file, x, kode) 398: FILE *file; 399: rtx x; 400: enum rtx_code kode; 401: { 402: switch (GET_CODE (x)) 403: { 404: case REG: 405: fprintf (file, "%d", REGNO (x)); 406: break; 407: case SYMBOL_REF: 408: fprintf (file, "%s", XSTR (x, 0)); 409: break; 410: case LABEL_REF: 411: case CONST: 412: case MEM: 1.1.1.2 ! root 413: if (kode == 'Q') ! 414: fprintf (file, "r%d,%d", ! 415: REGNO (XEXP (XEXP (x, 0), 0)), ! 416: INTVAL (XEXP (XEXP (x, 0), 1))); ! 417: else ! 418: output_address (XEXP (x, 0)); 1.1 root 419: break; 420: case CONST_DOUBLE: 421: /* { 422: double value = get_double (x); 423: char fltstr[32]; 424: sprintf (fltstr, "%lf", value); 425: 426: if (kode == 'D' || kode == 'E') 427: { 428: int i, found = 0; 429: for (i = 0; i <= datalbl_ndx; i++) 430: if (strcmp (fltstr, datalbl[i].value) == 0) 431: { 432: found = 1; 433: break; 434: } 435: if (!found) 436: { 437: strcpy (datalbl[i = ++datalbl_ndx].value, fltstr); 438: datalbl[i].name = float_label (kode, value); 439: datalbl[i].size = (kode == 'E') ? 3 : 2; 440: check_section (Konst); 441: fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name, 442: (kode == 'E' ? "ef" : "f"), fltstr); 443: check_section (Normal); 444: } 445: } 446: else if (kode == 'F' || kode == 'G') 447: { 448: int i, found = 0; 449: for (i = 0; i <= datalbl_ndx; i++) 450: if (strcmp (fltstr, datalbl[i].value) == 0) 451: { 452: found = 1; 453: break; 454: } 455: if (!found) 456: { 457: fprintf (stderr, 458: "float value %lfnot found upon label reference\n", value); 459: strcpy (datalbl[i = ++datalbl_ndx].value, fltstr); 460: datalbl[i].name = float_label (kode, value); 461: datalbl[i].size = (kode == 'G') ? 3 : 2; 462: check_section (Konst); 463: fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name, 464: (kode == 'G' ? "ef" : "f"), fltstr); 465: check_section (Normal); 466: } 467: fprintf (file, "%s ;P_O 'F'", datalbl[i].name); 468: } 469: else 470: fprintf (file, " %s ;P_O cst_dbl ", fltstr); 471: } 472: */ 473: fprintf (file, "%lf", get_double (x)); 474: break; 475: case CONST_INT: 476: if (kode == 'J') 477: fprintf (file, "%d", -INTVAL (x)); 478: else if (INTVAL (x) > 0x7FFF) 479: fprintf (file, "%d ; range correction (val>0x7FFF) applied", 480: INTVAL (x) - 0x10000); 481: else 482: fprintf (file, "%d", INTVAL (x)); 483: break; 484: case CODE_LABEL: 485: fprintf (file, "L%d", XINT (x, 3)); 486: break; 487: case CALL: 488: fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'", 489: XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1)); 490: break; 491: case PLUS: 492: { 493: rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1); 494: int op0code = GET_CODE (op0), op1code = GET_CODE (op1); 495: if (op1code == CONST_INT) 496: switch (op0code) 497: { 498: case REG: 499: fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST", 500: INTVAL (op1), REGNO (op0)); 501: break; 502: case SYMBOL_REF: 503: fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0)); 504: break; 505: case MEM: 506: fprintf (file, "%d,[mem:", INTVAL (op1)); 507: output_address (XEXP (op0, 0)); 508: fprintf (file, "] ;P_O plus"); 509: break; 510: default: 511: fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d", 512: (int) op0code, INTVAL (op1)); 513: } 514: else if (op1code == SYMBOL_REF && op0code == REG) 515: fprintf (file, "%s,r%d ; P_O: (plus reg sym)", 516: XSTR (op1, 0), REGNO (op0)); 517: else 518: fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code); 519: } 520: break; 521: default: 522: fprintf (file, "p_o_UFO code=%d", GET_CODE (x)); 523: } 524: } 525: 526: print_operand_address (file, addr) 527: FILE *file; 528: rtx addr; 529: { 530: switch (GET_CODE (addr)) 531: { 532: case REG: 533: fprintf (file, "0,r%d ; P_O_A", REGNO (addr)); 534: break; 535: case PLUS: 536: { 537: register rtx x = XEXP (addr, 0), y = XEXP (addr, 1); 538: switch (GET_CODE (x)) 539: { 540: case REG: 541: switch (GET_CODE (y)) 542: { 543: case CONST: 544: output_address (XEXP (y, 0)); 545: fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x)); 546: break; 547: case CONST_INT: 548: fprintf (file, "%d,r%d", INTVAL (y), REGNO (x)); 549: break; 550: case SYMBOL_REF: 551: fprintf (file, "%s,r%d ; P_O_A reg + sym", 552: XSTR (y, 0), REGNO (x)); 553: break; 1.1.1.2 ! root 554: case LABEL_REF: ! 555: output_address (XEXP (y, 0)); ! 556: fprintf (file, ",r%d ; P_O_A reg + label", REGNO (x)); ! 557: break; 1.1 root 558: default: 559: fprintf (file, "[P_O_A reg%d+UFO code=%d]", 560: REGNO (x), GET_CODE (y)); 561: } 562: break; 563: case LABEL_REF: 1.1.1.2 ! root 564: output_address (XEXP (x, 0)); ! 565: break; 1.1 root 566: case SYMBOL_REF: 567: switch (GET_CODE (y)) 568: { 569: case CONST_INT: 570: fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0)); 571: break; 572: case REG: 573: fprintf (file, "%s,r%d ;P_O_A sym + reg", 574: XSTR (x, 0), REGNO (y)); 575: break; 576: default: 577: fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]", 578: XSTR (x, 0), GET_CODE (y)); 579: } 580: break; 581: case CONST: 582: output_address (XEXP (x, 0)); 583: if (GET_CODE (y) == REG) 584: fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x)); 585: else 586: fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y)); 587: break; 588: case MEM: 589: output_address (y); 590: fprintf (file, ",[mem:"); 591: output_address (XEXP (x, 0)); 592: fprintf (file, "] ;P_O_A plus"); 593: break; 594: default: 595: fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]", 596: GET_CODE (x), GET_CODE (y)); 597: } 598: } 599: break; 600: case CONST_INT: 601: if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000) 602: fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr)); 603: else 604: { 605: fprintf (file, "[p_o_a=ILLEGAL_CONST]"); 606: output_addr_const (file, addr); 607: } 608: break; 609: case LABEL_REF: 610: case SYMBOL_REF: 611: fprintf (file, "%s", XSTR (addr, 0)); 612: break; 613: case MEM: 614: fprintf (file, "[memUFO:"); 615: output_address (XEXP (addr, 0)); 616: fprintf (file, "]"); 617: break; 618: case CONST: 619: output_address (XEXP (addr, 0)); 620: fprintf (file, " ;P_O_A const"); 621: break; 1.1.1.2 ! root 622: case CODE_LABEL: ! 623: fprintf (file, "L%d", XINT (addr, 3)); ! 624: break; 1.1 root 625: default: 626: fprintf (file, " p_o_a UFO, code=%d val=0x%x", 627: (int) GET_CODE (addr), INTVAL (addr)); 628: break; 629: } 630: } 631:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.