⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gexpr386.c

📁 本程序集是Allen I. Holub所写的《Compiler Design in C》一书的附随软件
💻 C
📖 第 1 页 / 共 5 页
字号:
								case en_cul:
								case en_cp:
                        ssize = 4;
                        break;
                case en_tempref:
                case en_regref:
												ssize = node->v.p[0]->v.i >> 8;
												break;
								case en_floatref:
								case en_cf:
												ssize = 6;
												break;
								case en_doubleref:
								case en_cd:
												ssize = 8;
												break;
								case en_longdoubleref:
								case en_cld:
												ssize = 10;
												break;
								default:
												ssize = -4;
                }
        if (chksize( ssize , rsize ))
                rsize = ssize;
        ap2 = gen_expr(node->v.p[1],F_DREG | F_FREG,rsize);
				mark();
        ap1 = gen_expr(node->v.p[0],F_ALL | F_NOBIT | F_DEST,ssize);
				ap4 = xalloc(sizeof(AMODE));
				ap4->preg = ap1->preg;
				ap4->mode = am_indisp;
				ap4->offset = makenode(en_icon,0,0);
				if (!equal_address(ap1,ap2)	)
					if (rsize > 4) {
						floatstore(ap4,ssize,flags);
						gen_codef(op_fwait,0,0,0);
					}
					else
						if (node->v.p[0]->nodetype == en_bits)
							bit_move(ap4,ap2,node->v.p[0],flags,ssize,rsize);
						else
							if (ap2->mode != am_dreg && ap2->mode != am_immed
										&& ap4->mode != am_dreg) {
								ap3 = temp_data();
  	  	    		gen_code(op_mov,rsize,ap3,ap2);
    	  	  		gen_code(op_mov,ssize,ap4,ap3);
								freeop(ap3);
							}
							else
  	      			gen_code(op_mov,ssize,ap4,ap2);
        freeop(ap1);
				do_extend(ap2,ssize,size,flags);
				make_legal(ap2,flags,size);
        return ap2;
}

AMODE    *gen_aincdec(ENODE *node, int flags, int size, int op)
/*
 *      generate an auto increment or decrement node. op should be
 *      either op_add (for increment) or op_sub (for decrement).
 */
{       AMODE    *ap1,*ap2;
        int             ssize,rsize;
        ssize = natural_size(node->v.p[0]);
				if (!(flags & F_NOVALUE)) {
					ap2 = temp_data();
				}
				mark();
        ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
				if (!(flags &F_NOVALUE)) {
					gen_code(op_mov,ssize,ap2,ap1);
				}
        gen_code(op,ssize,ap1,make_immed((int)node->v.p[1]));
				freeop(ap1);
				release();
				if (!(flags & F_NOVALUE)) {
					do_extend(ap2,ssize,size,flags);
					make_legal(ap2,flags,size);
				}
        return ap2;
}

int push_param(ENODE *ep, int size)
/*
 *      push the operand expression onto the stack.
 */
{       AMODE    *ap, *ap2;
				int rv,sz;
				switch (ep->nodetype) {
								case en_absacon:
												ep->v.i = (( SYM *)ep->v.p[0])->value.i;
                        ap = xalloc(sizeof(AMODE));
                        ap->mode = am_immed;
                        ap->offset = ep;     /* use as constant node */
                        gen_code(op_push,4,ap,0);
												rv = 4;
												break;
                case en_napccon:
                case en_nacon:
												ep->v.p[0] = ((SYM *)ep->v.p[0])->name;
                case en_labcon:
                case en_nalabcon:
                        ap = xalloc(sizeof(AMODE));
                        ap->mode = am_immed;
                        ap->offset = ep;     /* use as constant node */
                        gen_code(op_push,4,ap,0);
                        make_legal(ap,F_ALL,4);
												rv = 4;
												break;
								case en_cf:
								case en_floatref:
												ap = gen_expr(ep,F_FREG | F_VOL,6);
												gen_code(op_sub,4,makedreg(ESP),make_immed(4));
												ap2 = make_immed(0);
												ap2->preg = ESP;
												ap2->mode = am_indisp;
												gen_codef(op_fstp,6,ap2,0);
												gen_codef(op_fwait,0,0,0);
												rv = 4;
												break;
								case en_cd:
								case en_doubleref:
												ap = gen_expr(ep,F_FREG | F_VOL,8);
												gen_code(op_sub,4,makedreg(ESP),make_immed(8));
												ap2 = make_immed(0);
												ap2->preg = ESP;
												ap2->mode = am_indisp;
												gen_codef(op_fstp,8,ap2,0);
												gen_codef(op_fwait,0,0,0);
												rv = 8;
												break;
								case en_cld:
								case en_longdoubleref:
												ap = gen_expr(ep,F_FREG | F_VOL,8);
												gen_code(op_sub,4,makedreg(ESP),make_immed(10));
												ap2 = make_immed(0);
												ap2->preg = ESP;
												ap2->mode = am_indisp;
												gen_codef(op_fstp,10,ap2,0);
												gen_codef(op_fwait,0,0,0);
												rv = 8;
												break;
								case en_rcon: 
								case en_fcon:
								case en_lrcon:
												rv = size;
												if (rv == 6) rv= 4;
												if (rv == 10) rv= 12;
												ap = gen_expr(ep,F_FREG | F_VOL,size);
												make_floatconst(ap,size);
												gen_code(op_sub,4,makedreg(ESP),make_immed(rv));
												ap2 = make_immed(0);
												ap2->preg = ESP;
												ap2->mode = am_indisp;
												gen_codef(op_fstp,rv,ap2,0);
												gen_codef(op_fwait,0,0,0);
												break;
								default:
												rv = 4;
      			  					ap = gen_expr(ep,F_ALL,4);
												if (ap->mode != am_dreg &&ap->mode != am_immed&& ap->mode != am_freg) {
													sz = natural_size(ep->v.p[0]);
													if (sz < 4 && sz >-4) 
														do_extend(ap,sz,4,F_DREG);
												}
												if (ap->mode == am_freg) {
													gen_code(op_push,4,makedreg(3),0);
													ap2 = make_immed(0);
													ap2->preg = ESP;
													ap2->mode = am_indisp;
													gen_codef(op_fistp,4,ap2,0);
													gen_codef(op_fwait,0,0,0);
												}
												else
													gen_code(op_push,4,ap,0);
												break;
				}
        freeop(ap);
	stackdepth += rv;
	return(rv);
}
int push_stackblock(ENODE *ep)
{
	AMODE *ap;
	int sz = (ep->size + stackadd) &stackmod;
	if (!sz)
		return(0);
	gen_code(op_sub,4,makedreg(ESP),make_immed(sz));
	gen_code(op_push,4,makedreg(ESI),0);
	gen_code(op_push,4,makedreg(EDI),0);
	stackdepth+=sz+8;
	gen_code(op_lea,4,makedreg(EDI),make_stack(-8));
				switch (ep->nodetype) {
                case en_napccon:
                case en_nacon:
												ep->v.p[0] = ((SYM *)ep->v.p[0])->name;
                case en_nalabcon:
                case en_labcon:
                        ap = xalloc(sizeof(AMODE));
                        ap->mode = am_direct;
                        ap->offset = ep;     /* use as constant node */
                        gen_code(op_lea,4,makedreg(ESI),ap);
												break;
								case en_absacon:
												ep->v.i = (( SYM *)ep->v.p[0])->value.i;
                        ap = xalloc(sizeof(AMODE));
                        ap->mode = am_direct;
                        ap->offset = ep;     /* use as constant node */
                        gen_code(op_lea,4,makedreg(ESI),ap);
												break;
								default:
      			  					ap = gen_expr(ep,F_DREG | F_MEM | F_IMMED,4);
												gen_code(op_mov,4,makedreg(ESI),ap);
												break;
				}
	gen_code(op_mov,4,makedreg(ECX),make_immed(sz));
	gen_code(op_cld,0,0,0);
	gen_code(op_rep,0,0,0);
	gen_code(op_movsb,0,0,0);
	gen_code(op_pop,4,makedreg(EDI),0);
	gen_code(op_pop,4,makedreg(ESI),0);
	stackdepth-=8;
	freeop(ap);
	return(sz);
}

int     gen_parms(ENODE *plist,int size)
/*
 *      push a list of parameters onto the stack and return the
 *      size of parameters pushed.
 */
{       int     i;
        i = 0;
        while( plist != 0 )
                {         	
								if (plist->nodetype == en_stackblock)
									i+=push_stackblock(plist->v.p[0]);
								else
                	i+=push_param(plist->v.p[0],size);
                plist = plist->v.p[1];
                }
        return i;
}

AMODE    *gen_fcall(ENODE *node,int flags, int size)
/*
 *      generate a function call node and return the address mode
 *      of the result.
 */
{       AMODE    *ap, *result;
				ENODE *node2;
        int             i,ssize;
        result = temp_data();
        temp_data(); temp_data();       /* push any used data registers */
        freeop(result); freeop(result); freeop(result);
				if (node->nodetype == en_callblock) {
					i = gen_parms(node->v.p[1]->v.p[1]->v.p[1]->v.p[0],size);
      		ap = gen_expr(node->v.p[0],F_ALL,4);
					gen_code(op_push,4,ap,0);
					i+=4;
					stackdepth+=4;
					node = node->v.p[1];
					freeop(ap);
					ssize = 4;
				}
				else {
	        i = gen_parms(node->v.p[1]->v.p[1]->v.p[0],size);    /* generate parameters */
					ssize = node->v.p[0]->v.i;
				}
				if (node->nodetype == en_intcall) {
					AMODE *ap2 = xalloc(sizeof(AMODE));
					ap2->mode = am_seg;
					ap2->seg = e_cs;
					gen_code(op_pushfd,0,0,0);
					gen_code(op_push,0,ap2,0);
				}
									
   	    if( node->v.p[1]->v.p[0]->nodetype == en_nacon || node->v.p[1]->v.p[0]->nodetype == en_napccon ) {
								SYM *sp= node->v.p[1]->v.p[0]->v.p[0];
								if (sp->inreg) {
									ap = makedreg(sp->value.i);
								}
								else {
									node->v.p[1]->v.p[0]->v.p[0] = sp->name;
     	          	ap = make_offset(node->v.p[1]->v.p[0]);
									ap->mode = am_immed;
								}
         	      gen_code(op_call,0,ap,0);
				}
 	      else
   	            {
								if (node->v.p[1]->v.p[0]->nodetype == en_l_ref) {
									node2=node->v.p[1]->v.p[0]->v.p[0];
								}
								else {
									if (node->v.p[1]->v.p[0]->nodetype != en_tempref)
										DIAG("gen_fcall - questionable indirection");
									node2=node->v.p[1]->v.p[0];
								}
     	          ap = gen_expr(node2,F_ALL,4);
       	        freeop(ap);
         	      gen_code(op_call,4,ap,0);
                }
        if( i != 0 ) {
								if (i == 4)
									gen_code(op_pop,4,makedreg(ECX),0);
								else
                	gen_code(op_add,4,makedreg(4),make_immed(i));
								stackdepth -= i;
				}
				if (ssize > 4) {
						result = fstack();
				}
				else {
          result = temp_data();
        	if( result->preg != EAX)
                gen_code(op_mov,4,result,makedreg(EAX));
				}
				result->tempflag = 1;
				do_extend(result,ssize,size,flags);
				make_legal(result,flags,size);
        return result;
}
AMODE    *gen_pfcall(ENODE *node,int flags, int size)
/*
 *      generate a function call node to a pascal function
 *			and return the address mode of the result.
 */
{       AMODE    *ap, *result;
        int             i,ssize;
				ENODE * invnode = 0,*anode,*node2;
				
				/* invert the parameter list */
				if (node->nodetype == en_pcallblock)
					anode = node->v.p[1]->v.p[1]->v.p[1]->v.p[0];
				else
					anode = node->v.p[1]->v.p[1]->v.p[0];
				while (anode) {
					invnode = makenode(anode->nodetype,anode->v.p[0],invnode);
					anode = anode->v.p[1];
				}
        result = temp_data();
        temp_data(); temp_data();       /* push any used data registers */
        freeop(result); freeop(result); freeop(result);
				if (node->nodetype == en_pcallblock) {
      		ap = gen_expr(node->v.p[0],F_ALL,4);
					gen_code(op_push,4,ap,0);
					freeop(ap);
					i=4;
					stackdepth+=4;
					i += gen_parms(invnode,size);
					node = node->v.p[1];
					ssize = 4;
				}
				else {
	        i = gen_parms(invnode,size);    /* generate parameters */
					ssize = node->v.p[0]->v.i;
				}
									
   	    if( node->v.p[1]->v.p[0]->nodetype == en_nacon || node->v.p[1]->v.p[0]->nodetype == en_napccon ) {
								SYM *sp= node->v.p[1]->v.p[0]->v.p[0];
								if (sp->inreg) {
									ap = makedreg(sp->value.i);
								}
								else {
									node->v.p[0]->v.p[0]->v.p[0] = sp->name;
     	          	ap = make_offset(node->v.p[1]->v.p[0]);
									ap->mode = am_immed;
								}
         	      gen_code(op_call,0,ap,0);
				}
 	      else
   	            {
								if (node->v.p[1]->v.p[0]->nodetype == en_l_ref) {
									node2=node->v.p[1]->v.p[0]->v.p[0];
								}
								else {
									if (node->v.p[1]->v.p[0]->nodetype != en_tempref)
										DIAG("gen_fcall - questionable indirection");
									node2=node->v.p[1]->v.p[0];
								}
     	          ap = gen_expr(node2,F_ALL,4);
       	        freeop(ap);
         	      gen_code(op_call,4,ap,0);
                }
				stackdepth -= i;
				if (ssize > 4) {
						result = fstack();
				}
				else {
          result = temp_data();
        	if( result->preg != EAX)
                gen_code(op_mov,4,result,makedreg(EAX));
				}
				result->tempflag = 1;
				do_extend(result,ssize,size,flags);
				make_legal(result,flags,size);
        return result;
}

AMODE    *gen_expr(ENODE *node, int flags, int size)
/*
 *      general expression evaluation. returns the addressing mode
 *      of the result.
 */
{
				AMODE    *ap1, *ap2;
        int             lab0, lab1;
        int             natsize;
        if( node == 0 )
                {
                DIAG("null node in gen_expr.");
                return 0;
                }
        switch( node->nodetype )
                {
								case en_bits:
												size = natural_size(node->v.p[0]);
												ap1 = gen_expr(node->v.p[0],F_ALL,size);
												if (!(flags & F_NOBIT))
													bit_legal(ap1,node,size);
												return ap1;
								case en_cb: 
								case en_cub:
								case en_cw: 
								case en_cuw:
								case en_cl: 
								case en_cul:
								case en_cf: 
								case en_cd: 
						

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -