|
|
1.1 ! root 1: /* ! 2: * n1/i386/outmch.c ! 3: * This file contains a number of small, machine dependent output ! 4: * routines called from the main code output routines in 'out.c'. ! 5: * Most have something to do with function calls and argument lists. ! 6: * i386. ! 7: */ ! 8: ! 9: #ifdef vax ! 10: #include "INC$LIB:cc1.h" ! 11: #else ! 12: #include "cc1.h" ! 13: #endif ! 14: ! 15: extern ival_t outargs(); ! 16: ! 17: /* ! 18: * Output a call. ! 19: * Make the left subtree (the name) addressable if required. ! 20: * Take a quick look to see if the semantics of the indirect call will work. ! 21: * If this is not an indirect call (iflag==0), then the "nsef" flag is set ! 22: * in the call to "genadr", to supress the generation of escape prefix bytes. ! 23: */ ! 24: outcall(tp, cxt, lab) register TREE *tp; ! 25: { ! 26: register ival_t nb; ! 27: register int iflag; ! 28: ! 29: nb = outargs(tp->t_rp); ! 30: iflag = 0; ! 31: tp = tp->t_lp; ! 32: if (tp->t_op == STAR) { ! 33: iflag = 1; ! 34: tp = tp->t_lp; ! 35: if (!isadr(tp->t_flag)) { ! 36: while (tp->t_op == LEAF) ! 37: tp = tp->t_lp; ! 38: outofs(tp); ! 39: } ! 40: } ! 41: outopcall(iflag); ! 42: genadr(tp, iflag==0, 0, NULL); ! 43: if (nb != 0) { ! 44: if (nb == 4) ! 45: genr(ZPOP, A_RECX); ! 46: else ! 47: genri(ZADD, A_RESP, nb); ! 48: } ! 49: } ! 50: ! 51: /* ! 52: * Output the argument list of a function. ! 53: * The arguments are moved to the stack right to left. ! 54: * Structure arguments, marked by a PTB type, get block moved into place. ! 55: * If the function is "alien" we push in the opposite order. ! 56: */ ! 57: ival_t ! 58: outargs(atp) TREE *atp; ! 59: { ! 60: register TREE *tp; ! 61: register ival_t s, n; ! 62: TYPE type; ! 63: ! 64: if ((tp=atp) == NULL) ! 65: return (ival_t)0; ! 66: if (tp->t_op == ARGLST) { ! 67: s = 0; ! 68: s += outargs(tp->t_rp); ! 69: s += outargs(tp->t_lp); ! 70: return s; ! 71: } ! 72: if ((type=tp->t_type)==PTB) { ! 73: /* UNDONE: fix for BCS struct passing! */ ! 74: n = s = tp->t_size; ! 75: n = (s+3)&~03; ! 76: if (n != 0) { ! 77: genri(ZSUB, A_RESP, n); /* grab dest space */ ! 78: geni(ZPUSH, s); /* count */ ! 79: output(tp, MFNARG, 0, 0); /* src */ ! 80: genrr(ZMOV, A_REAX, A_RESP); ! 81: genri(ZADD, A_REAX, (ival_t)8); ! 82: genr(ZPUSH, A_REAX); /* dest */ ! 83: geng(ZCALL, "memcpy"); ! 84: genri(ZADD, A_RESP, (ival_t)12); ! 85: } ! 86: return n; ! 87: } ! 88: output(tp, MFNARG, 0, 0); ! 89: return (ival_t)pertype[type].p_size; ! 90: } ! 91: ! 92: /* ! 93: * This routine does the work of the [TL OP0], [TL OP1] and [TL OP2] macros. ! 94: * It is given an opcode and returns the opcode that is used. ! 95: * Allows collapsing of code table entries which differ only slightly, ! 96: * based on signed/unsigned and byte/word/dword differences. ! 97: */ ! 98: maptype(opvariant, opcode, tp) ! 99: int opvariant; ! 100: register int opcode; ! 101: register TREE *tp; ! 102: { ! 103: int type, byteflag, wordflag, unsflag; ! 104: int fltflag; ! 105: ! 106: fltflag = is_ndp_op(opcode); ! 107: if (opvariant == M_TL) ! 108: tp = tp->t_lp; /* use left type */ ! 109: else if (opvariant == M_TR) ! 110: tp = tp->t_rp; /* use right type */ ! 111: else if (opvariant != M_TN) /* use node type or */ ! 112: return opcode; /* return opcode unchanged */ ! 113: type = tp->t_type; ! 114: byteflag = isbyte(type); ! 115: wordflag = isword(type); ! 116: unsflag = isuns(type); ! 117: if (unsflag) { ! 118: /* ! 119: * Replace opcode by unsigned variant. ! 120: * ZSAL -> ZSHL is unnecessary because SAL == SHL. ! 121: */ ! 122: switch (opcode) { ! 123: case ZMOVSX: opcode = ZMOVZX; break; ! 124: case ZSAR: opcode = ZSHR; break; ! 125: case ZIDIV: opcode = ZDIV; break; ! 126: case ZIMUL: opcode = ZMUL; break; ! 127: } ! 128: } ! 129: if (byteflag || wordflag) { ! 130: /* ! 131: * Replace opcode by byte or word variant. ! 132: * This assumes a fixed order for variants ! 133: * in h/i386/opcode.h: [dword, byte, word]. ! 134: */ ! 135: switch (opcode) { ! 136: case ZADD: ! 137: case ZAND: ! 138: case ZCMP: ! 139: case ZDEC: ! 140: case ZINC: ! 141: case ZMOV: ! 142: case ZOR: ! 143: case ZSAL: ! 144: case ZSAR: ! 145: case ZSHR: ! 146: case ZSUB: ! 147: case ZTEST: ! 148: case ZXOR: ! 149: return (byteflag) ? opcode + 1 : opcode + 2; ! 150: case ZMOVSX: return (byteflag) ? ZMOVSXB : ZMOVSX; ! 151: case ZMOVZX: return (byteflag) ? ZMOVZXB : ZMOVZX; ! 152: } ! 153: } else { ! 154: /* ZMOVSX or ZMOVZX with 32-bit operand just means ZMOV. */ ! 155: switch (opcode) { ! 156: case ZMOVSX: ! 157: case ZMOVZX: return ZMOV; ! 158: } ! 159: } ! 160: if (fltflag) { ! 161: /* ! 162: * Replace opcode by type-dependent variant. ! 163: * This assumes a fixed order for variants ! 164: * in h/i386/opcode.h: [double, float, dword, word]. ! 165: */ ! 166: switch(opcode) { ! 167: case ZFADDD: ! 168: case ZFCOMPD: ! 169: case ZFDIVD: ! 170: case ZFLDD: ! 171: case ZFMULD: ! 172: case ZFRDIVD: ! 173: case ZFRSUBD: ! 174: case ZFSTD: ! 175: case ZFSTPD: ! 176: case ZFSUBD: ! 177: switch(type) { ! 178: case F64: return opcode; ! 179: case F32: return opcode + 1; ! 180: case S32: return opcode + 2; ! 181: case S16: return opcode + 3; ! 182: } ! 183: } ! 184: } ! 185: return opcode; /* return opcode unchanged */ ! 186: } ! 187: ! 188: /* ! 189: * Generate output prefix bytes ! 190: * (none for dword operands, LO for word operands, LO LO for byte operands) ! 191: * depending on the supplied type. ! 192: * Makes the code tables much more concise. ! 193: */ ! 194: mappfx(tp, opv, pfx, npfxp) TREE *tp; int opv; unsigned char *pfx; int *npfxp; ! 195: { ! 196: register int type; ! 197: ! 198: if (opv == M_TL) ! 199: tp = tp->t_lp; ! 200: else if (opv == M_TR) ! 201: tp = tp->t_rp; ! 202: else if (opv != M_TN) ! 203: return; ! 204: type = tp->t_type; ! 205: if (isbyte(type) || isword(type)) { ! 206: pfx[*npfxp] = M_LO; ! 207: ++*npfxp; ! 208: if (isbyte(type)) { ! 209: pfx[*npfxp] = M_LO; ! 210: ++*npfxp; ! 211: } ! 212: } ! 213: ! 214: } ! 215: ! 216: /* ! 217: * Emit call opcode. ! 218: */ ! 219: outopcall(iflag) ! 220: { ! 221: bput(CODE); ! 222: bput((iflag) ? ZICALL : ZCALL); ! 223: } ! 224: ! 225: /* end of n1/i386/outmch.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.