|
|
1.1 ! root 1: /* Subroutines for insn-output.c for Convex. ! 2: Copyright (C) 1989,1991 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #include "config.h" ! 21: #include "rtl.h" ! 22: #include "regs.h" ! 23: #include "hard-reg-set.h" ! 24: #include "real.h" ! 25: #include "insn-config.h" ! 26: #include "conditions.h" ! 27: #include "insn-flags.h" ! 28: #include "output.h" ! 29: #include "insn-attr.h" ! 30: ! 31: /* Boolean to keep track of whether the current section is .text or not. ! 32: Used by .align handler in convex.h. */ ! 33: ! 34: int current_section_is_text; ! 35: ! 36: /* set_cmp saves the operands of a "cmp" insn, along with the type character ! 37: * to be used in the compare instruction. ! 38: * ! 39: * gen_cmp finds out what comparison is to be performed and outputs the ! 40: * necessary instructions, e.g. ! 41: * "eq.w a1,a2\;jbra.t L5" ! 42: * for (cmpsi a1 a2) (beq L5) */ ! 43: ! 44: static rtx xop0, xop1; ! 45: static char typech, regch; ! 46: ! 47: char * ! 48: set_cmp (op0, op1, typechr) ! 49: rtx op0, op1; ! 50: char typechr; ! 51: { ! 52: xop0 = op0; ! 53: xop1 = op1; ! 54: typech = typechr; ! 55: if (GET_CODE (op0) == REG) ! 56: regch = A_REGNO_P (REGNO (op0)) ? 'a' : 's'; ! 57: else if (GET_CODE (op1) == REG) ! 58: regch = A_REGNO_P (REGNO (op1)) ? 'a' : 's'; ! 59: else abort (); ! 60: return ""; ! 61: } ! 62: ! 63: char * ! 64: gen_cmp (label, cmpop, tf) ! 65: rtx label; ! 66: char *cmpop; ! 67: char tf; ! 68: { ! 69: char buf[80]; ! 70: char revop[4]; ! 71: rtx ops[3]; ! 72: ! 73: ops[2] = label; ! 74: ! 75: /* Constant must be first; swap operands if necessary. ! 76: If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu ! 77: and reverse the sense of the jump. */ ! 78: ! 79: if (CONSTANT_P (xop1)) ! 80: { ! 81: ops[0] = xop1; ! 82: ops[1] = xop0; ! 83: if (cmpop[0] == 'l') ! 84: { ! 85: bcopy (cmpop, revop, sizeof revop); ! 86: revop[1] ^= 'e' ^ 't'; ! 87: tf ^= 't' ^ 'f'; ! 88: cmpop = revop; ! 89: } ! 90: } ! 91: else ! 92: { ! 93: ops[0] = xop0; ! 94: ops[1] = xop1; ! 95: } ! 96: ! 97: sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf); ! 98: output_asm_insn (buf, ops); ! 99: return ""; ! 100: } ! 101: ! 102: /* Routines to separate CONST_DOUBLEs into component parts. */ ! 103: ! 104: int ! 105: const_double_high_int (x) ! 106: rtx x; ! 107: { ! 108: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ! 109: return CONST_DOUBLE_LOW (x); ! 110: else ! 111: return CONST_DOUBLE_HIGH (x); ! 112: } ! 113: ! 114: int ! 115: const_double_low_int (x) ! 116: rtx x; ! 117: { ! 118: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ! 119: return CONST_DOUBLE_HIGH (x); ! 120: else ! 121: return CONST_DOUBLE_LOW (x); ! 122: } ! 123: ! 124: /* Return the number of args in the call insn X. */ ! 125: ! 126: static int ! 127: call_num_args (x) ! 128: rtx x; ! 129: { ! 130: if (GET_CODE (x) == CALL) ! 131: return INTVAL (x->fld[1].rtx); ! 132: if (GET_CODE (x) == SET) ! 133: return call_num_args (SET_SRC (x)); ! 134: abort (); ! 135: } ! 136: ! 137: /* Scan forward from a call to decide whether we need to reload AP ! 138: from 12(FP) after it. We need to if there can be a reference to ! 139: arg_pointer_rtx before the next call, which will clobber AP. ! 140: Look forward in the instruction list until encountering a call ! 141: (don't need the load), or a reference to AP (do need it), or ! 142: a jump (don't know, do the load). */ ! 143: ! 144: static int ! 145: ap_reload_needed (insn) ! 146: rtx insn; ! 147: { ! 148: for (;;) ! 149: { ! 150: insn = NEXT_INSN (insn); ! 151: switch (GET_CODE (insn)) ! 152: { ! 153: case JUMP_INSN: ! 154: /* Basic block ends. If return, no AP needed, else assume it is. */ ! 155: return GET_CODE (PATTERN (insn)) != RETURN; ! 156: case CALL_INSN: ! 157: /* A subsequent call. AP isn't needed unless the call itself ! 158: requires it. But zero-arg calls don't clobber AP, so ! 159: don't terminate the search in that case. */ ! 160: if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn))) ! 161: return 1; ! 162: if (! TARGET_ARGCOUNT && call_num_args (PATTERN (insn)) == 0) ! 163: break; ! 164: return 0; ! 165: case BARRIER: ! 166: /* Barrier, don't need AP. */ ! 167: return 0; ! 168: case INSN: ! 169: /* Other insn may need AP; if not, keep looking. */ ! 170: if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn))) ! 171: return 1; ! 172: } ! 173: } ! 174: } ! 175: ! 176: /* Output the insns needed to do a call. */ ! 177: ! 178: char * ! 179: output_call (insn, address, argcount) ! 180: rtx insn, address, argcount; ! 181: { ! 182: int set_ap = TARGET_ARGCOUNT || argcount != const0_rtx; ! 183: ! 184: /* If AP is used by the call address, evaluate the address into a temp. */ ! 185: if (reg_mentioned_p (arg_pointer_rtx, address)) ! 186: if (set_ap) ! 187: { ! 188: address = XEXP (address, 0); ! 189: output_asm_insn ("ld.w %0,a1", &address); ! 190: address = gen_rtx (MEM, QImode, gen_rtx (REG, Pmode, 9)); ! 191: } ! 192: ! 193: /* If there are args, point AP to them. */ ! 194: if (set_ap) ! 195: output_asm_insn ("mov sp,ap"); ! 196: ! 197: /* If we are passing an arg count, convert it to words and push it. */ ! 198: if (TARGET_ARGCOUNT) ! 199: { ! 200: argcount = gen_rtx (CONST_INT, VOIDmode, (INTVAL (argcount) + 3) / 4); ! 201: output_asm_insn ("pshea %a0", &argcount); ! 202: } ! 203: ! 204: /* The call. */ ! 205: output_asm_insn ("calls %0", &address); ! 206: ! 207: /* If we clobbered AP, reload it if it is live. */ ! 208: if (set_ap) ! 209: if (ap_reload_needed (insn)) ! 210: output_asm_insn ("ld.w 12(fp),ap"); ! 211: ! 212: /* If we pushed an arg count, pop it and the args. */ ! 213: if (TARGET_ARGCOUNT) ! 214: { ! 215: argcount = gen_rtx (CONST_INT, VOIDmode, INTVAL (argcount) * 4 + 4); ! 216: output_asm_insn ("add.w %0,sp", &argcount); ! 217: } ! 218: ! 219: return ""; ! 220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.