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