void putconst(ENODE *offset) /* * put a constant to the outputFile file. */ { switch( offset->nodetype ) { case en_autoreg: case en_autocon: case en_icon: case en_lcon: case en_iucon: case en_lucon: case en_ccon: case en_absacon: fprintf(outputFile,"0%lXH",offset->v.i); break; case en_rcon: case en_fcon: case en_lrcon: fprintf(outputFile,"%f",offset->v.f); break; case en_labcon: case en_nalabcon: /* if (!prm_nasm && !prm_flat) fprintf(outputFile,"CS:"); */ fprintf(outputFile,"L_%d",offset->v.i); break; case en_napccon: case en_nacon: fprintf(outputFile,"%s",offset->v.p[0]); break; case en_add: putconst(offset->v.p[0]); fprintf(outputFile,"+"); putconst(offset->v.p[1]); break; case en_sub: putconst(offset->v.p[0]); fprintf(outputFile,"-"); putconst(offset->v.p[1]); break; case en_uminus: fprintf(outputFile,"-"); putconst(offset->v.p[0]); break; default: DIAG("illegal constant node."); break; } }
PRIVATE void put_pointer P1 (const EXPR *, ep) { put_header (longgen, alignment_of_type (tp_pointer)); putconst (ep); outcol += 10; }
/* * put a constant to the output file. */ static void putconst P1 (const EXPR *, ep) { switch (ep->nodetype) { case en_autocon: case en_icon: oprintf ("%ld", ep->v.i); break; case en_labcon: oprintf ("%s%u", prefix, (unsigned) ep->v.l); break; case en_nacon: oprintf ("%s", outlate (ep->v.str)); break; case en_sym: oprintf ("%s", outlate (nameof (ep->v.sp))); break; case en_add: putconst (ep->v.p[0]); oprintf ("+"); putconst (ep->v.p[1]); break; case en_sub: putconst (ep->v.p[0]); oprintf ("-"); putconst (ep->v.p[1]); break; case en_uminus: oprintf ("-"); /*FALLTHRU */ case en_cast: putconst (ep->v.p[0]); break; case en_str: oprintf ("%s", ep->v.str); break; default: FATAL ( (__FILE__, "putconst", "illegal constant node %d", ep->nodetype)); break; } }
/* * output a general addressing mode. */ static void putamode P2 (const ADDRESS *, ap, ILEN, len) { switch (ap->mode) { case am_line: case am_str: putconst (ap->u.offset); break; default: FATAL ((__FILE__, "putamode", "illegal address mode %d", ap->mode)); break; } }
LOCAL struct bigblock * putch1(bigptr p) { struct bigblock *t; switch(p->tag) { case TCONST: return( putconst(p) ); case TADDR: return(p); case TEXPR: switch(p->b_expr.opcode) { case OPCALL: case OPCCALL: t = putcall(p); sendp2(callval); break; case OPCONCAT: t = fmktemp(TYCHAR, cpexpr(p->vleng) ); sendp2(putcat( cpexpr(t), p )); break; case OPCONV: if(!ISICON(p->vleng) || p->vleng->b_const.fconst.ci!=1 || ! XINT(p->b_expr.leftp->vtype) ) fatal("putch1: bad character conversion"); t = fmktemp(TYCHAR, MKICON(1) ); sendp2(putassign( cpexpr(t), p)); break; default: fatal1("putch1: invalid opcode %d", p->b_expr.opcode); t = NULL; /* XXX gcc */ } return(t); default: fatal1("putch1: bad tag %d", p->tag); } /* NOTREACHED */ return NULL; /* XXX gcc */ }
void putamode(AMODE *ap) /* * output a general addressing mode. */ { int oldnasm, l; switch( ap->mode ) { case am_seg: putseg(ap->seg,0); break; case am_screg: fprintf(outputFile,"CR%d",ap->preg); break; case am_sdreg: fprintf(outputFile,"DR%d",ap->preg); break; case am_streg: fprintf(outputFile,"TR%d",ap->preg); break; case am_immed: if (ap->length && (ap->offset->nodetype == en_labcon || ap->offset->nodetype == en_nacon || ap->offset->nodetype == en_nalabcon || ap->offset->nodetype == en_napccon)) { if (!prm_nasm) fprintf(outputFile,"OFFSET "); else if (!nosize) fprintf(outputFile,"DWORD "); } else if (prm_nasm && addsize) pointersize(ap->length); putconst(ap->offset); break; case am_direct: pointersize(ap->length); putseg(ap->seg,TRUE); /* if (!prm_flat) fprintf(outputFile,"DS:"); */ fprintf(outputFile,"["); oldnasm = prm_nasm; prm_nasm = TRUE; putconst(ap->offset); fputc(']',outputFile); prm_nasm = oldnasm; break; case am_dreg: putsizedreg("%s",ap->preg,ap->length); break; case am_freg: fprintf(outputFile,"ST(%d)",ap->preg); break; case am_indisp: pointersize(ap->length); putseg(ap->seg,TRUE); putsizedreg("[%s",ap->preg,4); if (ap->offset) { fputc('+',outputFile); putconst(ap->offset); } fputc(']',outputFile); break; case am_indispscale: { int scale = 1,t=ap->scale; while (t--) scale <<=1; pointersize(ap->length); putseg(ap->seg,TRUE); if (ap->preg == -1) fputc('[',outputFile); else putsizedreg("[%s+",ap->preg,4); putsizedreg("%s",ap->sreg,4); if (scale != 1) fprintf(outputFile,"*%d",scale); if (ap->offset) { fputc('+',outputFile); putconst(ap->offset); } fputc(']',outputFile); } break; default: DIAG("illegal address mode."); break; } }
LOCAL struct bigblock * putcx1(bigptr qq) { struct bigblock *q, *lp, *rp; register struct bigblock *resp; NODE *p; int opcode; int ltype, rtype; ltype = rtype = 0; /* XXX gcc */ if(qq == NULL) return(NULL); switch(qq->tag) { case TCONST: if( ISCOMPLEX(qq->vtype) ) qq = putconst(qq); return( qq ); case TADDR: if( ! addressable(qq) ) { resp = fmktemp(tyint, NULL); p = putassign( cpexpr(resp), qq->b_addr.memoffset ); sendp2(p); qq->b_addr.memoffset = resp; } return( qq ); case TEXPR: if( ISCOMPLEX(qq->vtype) ) break; resp = fmktemp(TYDREAL, NO); p = putassign( cpexpr(resp), qq); sendp2(p); return(resp); default: fatal1("putcx1: bad tag %d", qq->tag); } opcode = qq->b_expr.opcode; if(opcode==OPCALL || opcode==OPCCALL) { q = putcall(qq); sendp2(callval); return(q); } else if(opcode == OPASSIGN) { return( putcxeq(qq) ); } resp = fmktemp(qq->vtype, NULL); if((lp = putcx1(qq->b_expr.leftp) )) ltype = lp->vtype; if((rp = putcx1(qq->b_expr.rightp) )) rtype = rp->vtype; switch(opcode) { case OPCOMMA: frexpr(resp); resp = rp; rp = NULL; break; case OPNEG: p = putassign(realpart(resp), mkexpr(OPNEG, realpart(lp), NULL)); sendp2(p); p = putassign(imagpart(resp), mkexpr(OPNEG, imagpart(lp), NULL)); sendp2(p); break; case OPPLUS: case OPMINUS: p = putassign( realpart(resp), mkexpr(opcode, realpart(lp), realpart(rp) )); sendp2(p); if(rtype < TYCOMPLEX) { p = putassign(imagpart(resp), imagpart(lp) ); } else if(ltype < TYCOMPLEX) { if(opcode == OPPLUS) p = putassign( imagpart(resp), imagpart(rp) ); else p = putassign( imagpart(resp), mkexpr(OPNEG, imagpart(rp), NULL) ); } else p = putassign( imagpart(resp), mkexpr(opcode, imagpart(lp), imagpart(rp) )); sendp2(p); break; case OPSTAR: if(ltype < TYCOMPLEX) { if( ISINT(ltype) ) lp = intdouble(lp); p = putassign( realpart(resp), mkexpr(OPSTAR, cpexpr(lp), realpart(rp) )); sendp2(p); p = putassign( imagpart(resp), mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) )); } else if(rtype < TYCOMPLEX) { if( ISINT(rtype) ) rp = intdouble(rp); p = putassign( realpart(resp), mkexpr(OPSTAR, cpexpr(rp), realpart(lp) )); sendp2(p); p = putassign( imagpart(resp), mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) )); } else { p = putassign( realpart(resp), mkexpr(OPMINUS, mkexpr(OPSTAR, realpart(lp), realpart(rp)), mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) )); sendp2(p); p = putassign( imagpart(resp), mkexpr(OPPLUS, mkexpr(OPSTAR, realpart(lp), imagpart(rp)), mkexpr(OPSTAR, imagpart(lp), realpart(rp)) )); } sendp2(p); break; case OPSLASH: /* fixexpr has already replaced all divisions * by a complex by a function call */ if( ISINT(rtype) ) rp = intdouble(rp); p = putassign( realpart(resp), mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) ); sendp2(p); p = putassign( imagpart(resp), mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) ); sendp2(p); break; case OPCONV: p = putassign( realpart(resp), realpart(lp) ); if( ISCOMPLEX(lp->vtype) ) q = imagpart(lp); else if(rp != NULL) q = realpart(rp); else q = mkrealcon(TYDREAL, 0.0); sendp2(p); p = putassign( imagpart(resp), q); sendp2(p); break; default: fatal1("putcx1 of invalid opcode %d", opcode); } frexpr(lp); frexpr(rp); ckfree(qq); return(resp); }
/* * Convert a f77 tree statement to something that looks like a * pcc expression tree. */ NODE * putx(bigptr q) { struct bigblock *x1; NODE *p = NULL; /* XXX */ int opc; int type, k; #ifdef PCC_DEBUG if (tflag) { printf("putx %p\n", q); fprint(q, 0); } #endif switch(q->tag) { case TERROR: ckfree(q); break; case TCONST: switch(type = q->vtype) { case TYLOGICAL: type = tyint; case TYLONG: case TYSHORT: p = mklnode(ICON, q->b_const.fconst.ci, 0, types2[type]); ckfree(q); break; case TYADDR: p = mklnode(ICON, 0, 0, types2[type]); p->n_name = copys(memname(STGCONST, (int)q->b_const.fconst.ci)); ckfree(q); break; default: p = putx(putconst(q)); break; } break; case TEXPR: switch(opc = q->b_expr.opcode) { case OPCALL: case OPCCALL: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else { putcall(q); p = callval; } break; case OPMIN: case OPMAX: p = putmnmx(q); break; case OPASSIGN: if (ISCOMPLEX(q->b_expr.leftp->vtype) || ISCOMPLEX(q->b_expr.rightp->vtype)) { frexpr(putcxeq(q)); } else if (ISCHAR(q)) p = putcheq(q); else goto putopp; break; case OPEQ: case OPNE: if (ISCOMPLEX(q->b_expr.leftp->vtype) || ISCOMPLEX(q->b_expr.rightp->vtype) ) { p = putcxcmp(q); break; } case OPLT: case OPLE: case OPGT: case OPGE: if(ISCHAR(q->b_expr.leftp)) p = putchcmp(q); else goto putopp; break; case OPPOWER: p = putpower(q); break; case OPSTAR: /* m * (2**k) -> m<<k */ if (XINT(q->b_expr.leftp->vtype) && ISICON(q->b_expr.rightp) && ((k = flog2(q->b_expr.rightp->b_const.fconst.ci))>0) ) { q->b_expr.opcode = OPLSHIFT; frexpr(q->b_expr.rightp); q->b_expr.rightp = MKICON(k); goto putopp; } case OPMOD: goto putopp; case OPPLUS: case OPMINUS: case OPSLASH: case OPNEG: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else goto putopp; break; case OPCONV: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else if (ISCOMPLEX(q->b_expr.leftp->vtype)) { p = putx(mkconv(q->vtype, realpart(putcx1(q->b_expr.leftp)))); ckfree(q); } else goto putopp; break; case OPAND: /* Create logical AND */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); k = newlabel(); putif(q->b_expr.leftp, k); putif(q->b_expr.rightp, k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); putlabel(k); p = putx(x1); break; case OPNOT: /* Logical NOT */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); k = newlabel(); putif(q->b_expr.leftp, k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); putlabel(k); p = putx(x1); break; case OPOR: /* Create logical OR */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); k = newlabel(); putif(mkexpr(OPEQ, q->b_expr.leftp, mklogcon(0)), k); putif(mkexpr(OPEQ, q->b_expr.rightp, mklogcon(0)), k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); putlabel(k); p = putx(x1); break; case OPCOMMA: for (x1 = q; x1->b_expr.opcode == OPCOMMA; x1 = x1->b_expr.leftp) putexpr(x1->b_expr.rightp); p = putx(x1); break; case OPEQV: case OPNEQV: case OPADDR: case OPBITOR: case OPBITAND: case OPBITXOR: case OPBITNOT: case OPLSHIFT: case OPRSHIFT: putopp: p = putop(q); break; default: fatal1("putx: invalid opcode %d", opc); } break; case TADDR: p = putaddr(q, YES); break; default: fatal1("putx: impossible tag %d", q->tag); } return p; }
PRIVATE void put_short P1 (const EXPR *, ep) { put_header (wordgen, alignment_of_type (tp_short)); putconst (ep); outcol += 10; }
PRIVATE void put_char P1 (const EXPR *, ep) { put_header (bytegen, alignment_of_type (tp_char)); putconst (ep); outcol += 10; }