void gencompactswitch(SNODE *stmt, struct cases *cs)
{
    int tablab, size;
    AMODE *ap,  *ap2;
    LLONG_TYPE i;
    tablab = nextlabel++;
    InitRegs();
    size = natural_size(stmt->exp);
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
    {
	    ap = gen_expr_external(stmt->exp, FALSE, F_AXDX, BESZ_QWORD);
        if (cs->bottom)
        {
            gen_codes(op_sub, BESZ_DWORD, makedreg(EAX), make_immed(cs->bottom));
            #if sizeof(LLONG_TYPE) == 4
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom < 0
                    ?  - 1: 0));
            #else 
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom >>
                    32));
            #endif 
        }
void genreturn(SNODE *stmt, int flag)
/*
 *      generate a return statement.
 */
{       AMODE    *ap,*ap1;
				int size;
        if( stmt != 0 && stmt->exp != 0 ) {
                initstack();
								if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) {
									size = currentfunc->tp->btp->size;
									ap = gen_expr(stmt->exp,F_ALL,4);
									if (!(save_mask & 0x40))
										gen_push(ESI,am_dreg,0);                                  
									if (!(save_mask & 0x80))
										gen_push(EDI,am_dreg,0);                                  
									if (prm_linkreg) {
										ap1 = xalloc(sizeof(AMODE));
										ap1->preg = EBP;
										ap1->mode = am_indisp;
										if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) 
											ap1->offset = makenode(en_icon,(char *)(currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size+3) &0xFFFFFFFCL)),0);
										else
											ap1->offset = makenode(en_icon,(char *)8,0);
									}
									else
										if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) 
											ap1 = make_stack(-stackdepth-framedepth-currentfunc->tp->lst.head->value.i-((currentfunc->tp->lst.head->tp->size+3) & 0xfffffffcL));
										else
											ap1 = make_stack(-stackdepth-framedepth);
									gen_code(op_mov,4,makedreg(ESI),ap);		                  
									gen_code(op_mov,4,makedreg(EDI),ap1);
									gen_code(op_mov,4,makedreg(EAX),makedreg(EDI));
									gen_code(op_mov,4,makedreg(ECX),make_immed(size));  
									gen_code(op_cld,0,0,0);
									gen_code(op_rep,1,0,0);                                   
									gen_code(op_movsb,1,0,0);		                              
									if (!(save_mask & 0x80))
										gen_pop(EDI,am_dreg,0);
									if (!(save_mask & 0x40))
										gen_pop(ESI,am_dreg,0);
								}
								else {
									size = currentfunc->tp->btp->size;
  	              ap = gen_expr(stmt->exp,F_DREG | F_FREG,size);
									if (size > 4) {
										if (ap->mode != am_freg)
											gen_code(op_fld,size,ap,0);
									}
            	    else
              	  		if( ap->mode != am_dreg || ap->preg != 0 )
                	        gen_code(op_mov,size,makedreg(0),ap);
                }
								freeop(ap);
				}
				if (flag) {
	        if( retlab != -1 )
                gen_label(retlab);
          if( fsave_mask != 0 )
						diag("Float restore in return");
					if (!prm_linkreg && lc_maxauto)
						gen_code(op_add,4,makedreg(ESP),make_immed(lc_maxauto));
					if (currentfunc->intflag) {
						gen_code(op_popad,0,0,0);
						if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) {
							gen_code(op_leave,0,0,0);
						}
           	gen_code(op_iretd,0,0,0);
					}
					else {
           	if( save_mask != 0 )
							popregs(save_mask);
						if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) {
							gen_code(op_leave,0,0,0);
						}
						if (currentfunc->pascaldefn) {
							long retsize = 0;
							if (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) {
								retsize = currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size + 3) & 0xfffffffcL);
								if (prm_linkreg)
									retsize -= 8;
							}		
							if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) 
								retsize += 4;
							if (retsize) {
            		gen_code(op_ret,0,make_immed(retsize),0);
								return;
							}
						}		
            gen_code(op_ret,0,0,0);
					}
				}
        else {
					if (retlab == -1)
            retlab = nextlabel++;
          gen_code(op_jmp,0,make_label(retlab),0);
				}
}
Exemple #3
0
void loadregs(void)
/*
 * initialize allocated registers
 */
{
    CSE *csp;
    ENODE *exptr;
    unsigned mask, rmask, i, fmask, frmask, size;
    AMODE *ap,  *ap2;
    csp = olist;
    while (csp != 0)
    {
        int sz;
        if (csp->reg !=  - 1)
        {
             /* see if preload needed */
            exptr = csp->exp;
            if (!lvalue(exptr) || ((SYM*)exptr->v.p[0]->v.p[0])->funcparm)
            {
                exptr = csp->exp;
                InitRegs();
                sz = csp->size;
                ap = gen_expr_external(exptr, FALSE, F_MEM | F_DREG | F_IMMED, sz);
                if (csp->reg < 16)
                {
                    if (ap->mode == am_dreg)
                        peep_tail->oper1->preg = csp->reg;
                    else
                    {
                        if (csp->reg > 3 && chksize(BESZ_WORD, sz))
                            DIAG("byte sized non-register in analyze");
                        ap2 = makedreg(csp->reg);
                        ap2->length = BESZ_DWORD;
                        if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap
                            ->length ==  - BESZ_DWORD)
                            gen_codes(op_mov, BESZ_DWORD, ap2, ap);
                        else
                            if (sz < 0)
                                gen_code(op_movsx, ap2, ap);
                            else
                                gen_code(op_movzx, ap2, ap);
                    }
                }
                else
                if (csp->reg < 32)
                {
                    if (ap->mode == am_dreg)
                        peep_tail->oper1->preg = csp->reg - 12;
                    else
                    {
                        if (csp->reg - 12 > 3 && chksize(BESZ_WORD, sz))
                            DIAG("byte sized non-register in analyze");
                        ap2 = makedreg(csp->reg - 12);
                        ap2->length = BESZ_DWORD;
                        if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap
                            ->length ==  - BESZ_DWORD)
                            gen_codes(op_mov, BESZ_DWORD, ap2, ap);
                        else
                            if (sz < 0)
                                gen_code(op_movsx, ap2, ap);
                            else
                                gen_code(op_movzx, ap2, ap);
                    }
                }
                else
                {
                    /* Should never get here */
                    DIAG("float reg assigned in analyze");
                }
                if (lvalue(exptr) && ((SYM*)exptr->v.p[0]->v.p[0])->funcparm)
                {
                    ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->inreg = TRUE;
                    ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->value.i =  - csp
                        ->reg - (csp->size < 0 ?  - csp->size: csp->size) *256;
                }
            }
        }
        csp = csp->next;
    }
    gen_label(startlab);
}
Exemple #4
0
void loadregs(void)
/*
 * Initailze allocated regs
 *
 */
{       CSE      *csp;
        ENODE    *exptr;
        unsigned      mask, rmask,i,fmask,frmask,size;
        AMODE    *ap, *ap2;
        csp = olist;
        while( csp != 0 ) {
								int sz;
                if( csp->reg != -1 )
                        {               /* see if preload needed */
                        exptr = csp->exp;
                        if( !lvalue(exptr) || ((SYM *)exptr->v.p[0]->v.p[0])->funcparm )
                                {
																exptr = csp->exp;
                                initstack();
																sz = csp->size;
                                ap = gen_expr(exptr,F_ALL,sz);
							                  if (sz == 0 && ap->mode == am_immed)
																	sz = 4;
                                if( csp->reg < 16 ) {
							                  	if (sz == 0 && ap->mode == am_immed)
																		sz = 4;
																	if (ap->mode == am_dreg)
																		peep_tail->oper2->preg = csp->reg;
																	else {
                                        ap2 = makedreg(csp->reg);
                                				gen_code(op_move,sz,ap,ap2);
																				do_extend(ap2,sz,4,F_DREG);
																	}
																}
                                else
																	if (csp->reg < 32) {
							                  		if (sz == 0 && ap->mode == am_immed)
																			sz = 4;
																		if (ap->mode == am_areg)
																			peep_tail->oper2->preg = csp->reg - 16;
																		else {
  	                                      ap2 = makeareg(csp->reg - 16);
    	                            				gen_code(op_move,4,ap,ap2);
																		}
																	}
																	else {
									                  if (sz == 0 && ap->mode == am_immed)
																			sz = 8;
																		if (ap->mode == am_freg)
																			peep_tail->oper2->preg = csp->reg - 32;
																		else {
  	                                      ap2 = makefreg(csp->reg - 32);
																					size = 8;
																					if (exptr->nodetype == en_floatref)
																						size = 6;
    	                            				gen_code(op_fmove,size,ap,ap2);
																		}
																	}
                                freeop(ap);
																if (lvalue(exptr) && ((SYM *)exptr->v.p[0]->v.p[0])->funcparm) {
																	((SYM *)exptr->v.p[0]->v.p[0])->inreg = TRUE;
																	((SYM *)exptr->v.p[0]->v.p[0])->value.i = -csp->reg;
																}
                                }
                        }
                csp = csp->next;
                }
}
Exemple #5
0
void allocate(int datareg, int addreg, int floatreg, SNODE *block)
/*
 *      allocate will allocate registers for the expressions that have
 *      a high enough desirability.  It also puts the function
 * header, consisting of saved registers and stack decrments for local
 * variables
 */
{
    CSE *csp;
    ENODE *exptr;
    unsigned mask, rmask, i, fmask, frmask, size;
    AMODE *ap,  *ap2;
    mask = asmMask;
    rmask = asmRMask;
    fmask = frmask = 0;
    for (i = cf_freedata; i < datareg; i++)
    {
        rmask = rmask | (1 << (15-i));
        mask = mask | (1 << i);
    }
    for (i = cf_freeaddress + 16; i < addreg; i++)
    {
        rmask = rmask | (1 << (23-i));
        mask = mask | (1 << (i - 8));
    }
    while (bsort(&olist))
        ;
     /* sort the expression list */
    csp = olist;
    while (csp != 0)
    {
        if (csp->reg ==  - 1 && !(csp->exp->cflags &DF_VOL) && !csp->voidf)
        {
            if (desire(csp) < 3)
                csp->reg =  - 1;
            else
            {
                if (csp->exp->nodetype == en_rcon || csp->exp->nodetype ==
                    en_fcon || csp->exp->nodetype == en_lrcon || csp->exp
                    ->nodetype == en_floatref || csp->exp->nodetype ==
                    en_doubleref || csp->exp->nodetype == en_longdoubleref ||
                    csp->exp->nodetype == en_fimaginarycon || 
                    csp->exp->nodetype == en_rimaginarycon ||
                    csp->exp->nodetype == en_lrimaginarycon ||
                    csp->exp->nodetype == en_fimaginaryref || 
                    csp->exp->nodetype == en_rimaginaryref ||
                    csp->exp->nodetype == en_lrimaginaryref) {}
                else if ((csp->duses <= csp->uses / 4) && (datareg < cf_maxdata)
                    && dataregs)
                    csp->reg = (datareg)++;
                else if (!(csp->size == 1 || csp->size ==  - 1 || csp->size ==
                    5) && (addreg < cf_maxaddress) && addrregs)
                    csp->reg = (addreg)++;
                else if ((datareg < cf_maxdata) && dataregs)
                    csp->reg = (datareg)++;
                if (csp->reg !=  - 1)
                //                        if (lvalue(csp->exp))
                //                           csp->seg = defseg(csp->exp->v.p[0]) ;
                //                        else
				if (!csp->seg)
				{
                    csp->seg = defseg(csp->exp);
					if (csp->seg)
						csp->reg = -1;
				}
            }

        }
        if (csp->reg !=  - 1)
        {
            if (lvalue(csp->exp) && !((SYM*)csp->exp->v.p[0]->v.p[0])->funcparm)
            {
                ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->inreg = TRUE;
                ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->value.i =  - csp
                    ->reg - (csp->size < 0 ?  - csp->size: csp->size) *256;
            }
            if (csp->reg < 16)
            {
                rmask = rmask | (1 << (15-csp->reg));
                mask = mask | (1 << csp->reg);
            }
            if (csp->reg < 32)
            {
                rmask = rmask | (1 << (23-csp->reg));
                mask = mask | (1 << (csp->reg - 8));
            }
            else
            {
                frmask = frmask | (1 << (39-csp->reg));
                fmask = fmask | (1 << (csp->reg - 32));
            }
        }
        csp = csp->next;
    }
    allocstack(); /* Allocate stack space for the local vars */
    floatstack_mode = 0; /* no space for floating point temps */
    if (currentfunc->intflag || currentfunc->faultflag)
    {
        mask = 0;
        rmask = 0;
        if (currentfunc->loadds)
            loadds();
        if (prm_farkeyword)
        {
            GenPush(ES + 24, am_dreg, 0);
            GenPush(FS + 24, am_dreg, 0);
            GenPush(GS + 24, am_dreg, 0);
        }
        gen_code(op_pushad, 0, 0);
    }
    if ((conscount || try_block_list || currentfunc->value.classdata.throwlist
        && currentfunc->value.classdata.throwlist->data) && prm_xcept)
    {
        xceptoffs = lc_maxauto += sizeof(XCEPTDATA);
    }
	if (prm_debug)
	{
        rmask = rmask | (1 << (15-EBX));
        mask = mask | (1 << EBX);
        rmask = rmask | (1 << (15-ESI-4));
        mask = mask | (1 << (ESI+4));
        rmask = rmask | (1 << (15-EDI-4));
        mask = mask | (1 << (EDI+4));
	}
    if (prm_cplusplus && prm_xcept || (funcfloat || lc_maxauto || currentfunc
        ->tp->lst.head && currentfunc->tp->lst.head != (SYM*) - 1)
         || (currentfunc->value.classdata.cppflags &PF_MEMBER) && !(currentfunc
             ->value.classdata.cppflags &PF_STATIC)
     || !prm_smartframes || !stackframeoff)
    {
        /* enter is *really* inefficient so we will not use it */
        if (!currentfunc->intflag)
            gen_codes(op_push, 4, makedreg(EBP), 0);
        gen_codes(op_mov, 4, makedreg(EBP), makedreg(ESP));
        if (lc_maxauto)
            gen_code(op_sub, makedreg(ESP), make_immed(lc_maxauto));
        // FIXME ... could auto-alloc an FP value when no frame!
        frame_ins = peep_tail;
    }
    else
        frame_ins = 0;
    if (mask != 0)
        PushRegs(rmask);
    save_mask = mask;
    if (fmask != 0)
        fsave_mask = fmask;
    if (currentfunc->loadds && !currentfunc->intflag)
    {
        loadds();

    }
    if (prm_stackcheck && lc_maxauto)
    {
        AMODE *ap1;
        ap = set_symbol("__stackerror", 1);
        ap1 = set_symbol("__stackbottom", 0);
        ap1->mode = am_direct;
        gen_codes(op_cmp, 4, makedreg(ESP), ap1);
        gen_codes(op_jb, 0, ap, 0);
    }
    AddProfilerData();
    if ((conscount || try_block_list || currentfunc->value.classdata.throwlist
        && currentfunc->value.classdata.throwlist->data) && prm_xcept)
    {
        currentfunc->value.classdata.conslabel = nextlabel++;
        currentfunc->value.classdata.destlabel = nextlabel++;
        gen_codes(op_mov, 4, makedreg(EAX), make_label(nextlabel - 2));
        call_library("__InitExceptBlock");
        gen_label(nextlabel - 1);
    }
}