示例#1
0
void GenerateThrow(Statement *stmt)
{
	AMODE *ap;

    if( stmt != NULL && stmt->exp != NULL )
	{
		initstack();
		ap = GenerateExpression(stmt->exp,F_ALL,8);
		if (ap->mode==am_immed) {
            if (isFISA64)
                FISA64_GenLdi(makereg(1),ap,8);
            else
			    GenerateTriadic(op_ori,0,makereg(1),makereg(0),ap);
        }
		else if( ap->mode != am_reg)
			GenerateDiadic(op_lw,0,makereg(1),ap);
		else if (ap->preg != 1 )
			GenerateTriadic(op_or,0,makereg(1),ap,makereg(0));
		ReleaseTempRegister(ap);
		if (isFISA64)
		    FISA64_GenLdi(makereg(2),make_immed((int64_t)stmt->label),8);
        else
		    GenerateTriadic(op_ori,0,makereg(2),makereg(0),make_immed((int64_t)stmt->label));
	}
	GenerateMonadic(isThor?op_br:op_bra,0,make_clabel(throwlab));
}
示例#2
0
文件: istmt.c 项目: jossk/OrangeC
SYMBOL *gen_mp_virtual_thunk(SYMBOL *vsp)
{

        QUAD *oi = intermed_head, *ot = intermed_tail;
        LIST *v = mpthunklist;
        SYMBOL *sp;
        IMODE *ap1,  *ap2;
        char buf[256];
        while (v)
        {
            sp = (SYMBOL*)v->data;
            if (sp->value.i == vsp->value.classdata.vtabindex)
                if (isstructured(vsp->tp->btp) == isstructured(sp->tp->btp))
                    return sp;
            v = v->link;
        }
        intermed_head = intermed_tail = NULL;
        blockMax = 0;
        blockCount = tempCount = 0;
        exitBlock = 0;
        IncGlobalFlag();
        sp = Alloc(sizeof(SYMBOL));
        sp->storage_class = sc_static;
        sp->tp = vsp->tp;
        sp->value.i = vsp->value.classdata.vtabindex;
        //sprintf(buf, "@$mpt$%d$%d", sp->value.i, isstructured(sp->tp->btp));
        sp->name = sp->decoratedName = litlate(buf);
        sp->errname = sp->decoratedName;
        sp->staticlabel = FALSE;
        sp->gennedvirtfunc = TRUE;
        v = (LIST *)Alloc(sizeof(LIST));
        v->data = sp;
        v->link = mpthunklist;
        mpthunklist = v;
        DecGlobalFlag();

        gen_virtual(sp, FALSE);
        addblock(i_goto);
        gen_icode(i_substack, NULL, ap2 = tempreg(ISZ_ADDR, 0), NULL);
        gen_icode(i_add, ap2, ap2 , make_immed(ISZ_NONE, isstructured(sp->tp->btp) ? ISZ_ADDR * 2 : ISZ_ADDR));
        ap1 = indnode(ap2, ISZ_ADDR);
        gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0);
        if (sp->value.classdata.baseofs)
            gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.classdata.baseofs));
        ap1 = indnode(ap2, ISZ_ADDR);
        gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0);
        gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.i));
        ap1 = indnode(ap2, ISZ_ADDR);
        gen_icode(i_directbranch, 0, ap1, 0);
        addblock(i_ret);
        optimize();
        rewrite_icode(); /* Translate to machine code & dump */
        if (chosenAssembler->gen->post_function_gen)
            chosenAssembler->gen->post_function_gen(intermed_head);
        gen_endvirtual(sp);
        intermed_head = oi;
        intermed_tail = ot;
        return sp;
}
示例#3
0
void gencompactswitch(SNODE *stmt, int deflab)
{       int             tablab,curlab,i, size = natural_size(stmt->exp);
        AMODE    *ap,*ap2;
  long switchbottom=gswitchbottom, switchcount=gswitchcount;
  long switchtop=gswitchtop;
  int *switchlabels=0;
				tablab = nextlabel++;
        curlab = nextlabel++;
        initstack();
        ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
				initstack();
				if (switchbottom)
					gen_code(op_sub,4,ap,make_immed(switchbottom));
				if (size < 0)
					gen_code(op_jl,0,make_label(deflab),0);
				else
					gen_code(op_jb,0,make_label(deflab),0);
				gen_code(op_cmp,4,ap,make_immed(switchtop-switchbottom));
				if (size < 0)
					gen_code(op_jge,0,make_label(deflab),0);
				else
					gen_code(op_jnc,0,make_label(deflab),0);
				gen_code(op_shl,4,ap,make_immed(2));
				ap2 = xalloc(sizeof(AMODE));
				ap->mode = am_indisp;
				ap2->preg = ap->preg;
				ap->offset = makenode(en_labcon,(char *)tablab,0);
				gen_code(op_jmp,4,ap,0);

				initstack();
				align(4);
				gen_label(tablab);
		switchlabels = xalloc((switchtop-switchbottom) * sizeof(int));
	for (i=switchbottom; i < switchtop; i++) {
		switchlabels[i-switchbottom] = deflab;
	}
	stmt = stmt->s1;
	while (stmt) {
                if( stmt->s2 )          /* default case ? */
                        {
                        stmt->label = (SNODE *)deflab;
												diddef = TRUE;
                        }
                else
                        {
												switchlabels[(int)stmt->label-switchbottom] = curlab;
												stmt->label = (SNODE *)curlab;
                        }
                if(stmt->next != 0 )
                        curlab = nextlabel++;
                stmt = stmt->next;
                }
	for (i=0; i < switchtop-switchbottom; i++)
		gen_code(op_dd,4,make_label(switchlabels[i]),0);
}
示例#4
0
文件: istmt.c 项目: jossk/OrangeC
void genxswitch(STATEMENT *stmt, SYMBOL *funcsp)
/*
 *      analyze and generate best switch statement.
 */
{
    int oldbreak, i;
    struct cases cs;
    IMODE *ap, *ap3;

#ifdef USE_LONGLONG
    ULLONG_TYPE a = 1;
#endif
    oldbreak = breaklab;
    breaklab = stmt->breaklabel;
    memset(&cs,0,sizeof(cs));
#ifndef USE_LONGLONG
    cs.top = INT_MIN;
    cs.bottom = INT_MAX;
#else
    cs.top = (a << 63); /* LLONG_MIN*/
    cs.bottom = cs.top - 1; /* LLONG_MAX*/
#endif
    count_cases(stmt->cases,&cs) ;
    cs.top++;
    ap3 = gen_expr(funcsp, stmt->select, F_VOL | F_NOVALUE, ISZ_UINT);
    ap = LookupLoadTemp(NULL, ap3);
    if (ap != ap3)
    {
        IMODE *barrier;
        if (stmt->select->isatomic)
        {
            barrier = doatomicFence(funcsp, stmt->select, NULL);
        }
        gen_icode(i_assn, ap, ap3, NULL);
        if (stmt->select->isatomic)
        {
            doatomicFence(funcsp, stmt->select, barrier);
        }
    }
    gen_icode2(i_coswitch, make_immed(ISZ_NONE,cs.count), ap, make_immed(ISZ_NONE,cs.top - cs.bottom), stmt->label);
    gather_cases(stmt->cases,&cs);
    qsort(cs.ptrs, cs.count, sizeof(cs.ptrs[0]), gcs_compare);
    for (i = 0; i < cs.count; i++)
    {
        gen_icode2(i_swbranch,0,make_immed(ISZ_NONE,cs.ptrs[i].id),0,cs.ptrs[i].label);
    }
    breaklab = oldbreak;
}
示例#5
0
// Generate a function body.
//
void GenerateFunction(SYM *sym, Statement *stmt)
{
	char buf[20];
	char *bl;

	throwlab = retlab = contlab = breaklab = -1;
	lastsph = 0;
	memset(semaphores,0,sizeof(semaphores));
	throwlab = nextlabel++;
	while( lc_auto & 7 )	/* round frame size to word */
		++lc_auto;
	if (sym->IsInterrupt) {
		//GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
		//GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
	}
	if (!sym->IsNocall) {
		GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(24));
		// For a leaf routine don't bother to store the link register or exception link register.
		if (sym->IsLeaf)
			GenerateDiadic(op_sw,0,makereg(27),make_indirect(30));
		else {
			GenerateDiadic(op_sw, 0, makereg(27), make_indexed(0,30));
			GenerateDiadic(op_sw, 0, makereg(28), make_indexed(8,30));
			GenerateDiadic(op_sw, 0, makereg(31), make_indexed(16,30));
			GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab));
		}
		GenerateDiadic(op_mov,0,makereg(27),makereg(30));
		if (lc_auto)
			GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto));
	}
	if (optimize)
		opt1(stmt);
    GenerateStatement(stmt);
    GenerateReturn(sym,0);
	// Generate code for the hidden default catch
	GenerateLabel(throwlab);
	if (sym->IsLeaf){
		if (sym->DoesThrow) {
			GenerateDiadic(op_mov,0,makereg(31),makereg(28));
			GenerateDiadic(op_bra,0,make_label(retlab),NULL);				// goto regular return cleanup code
		}
	}
	else {
		GenerateDiadic(op_lw,0,makereg(31),make_indexed(8,27));		// load throw return address from stack into LR
		GenerateDiadic(op_sw,0,makereg(31),make_indexed(16,27));		// and store it back (so it can be loaded with the lm)
		GenerateDiadic(op_bra,0,make_label(retlab),NULL);				// goto regular return cleanup code
	}
}
示例#6
0
/*
 *      generate shift equals operators.
 */
AMODE *GenerateAssignShift(ENODE *node,int flags,int size,int op)
{
	struct amode    *ap1, *ap2, *ap3;

	ap1 = GetTempRegister();
	//size = GetNaturalSize(node->p[0]);
    ap3 = GenerateExpression(node->p[0],F_ALL,size);
    ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
	if (ap3->mode==am_reg)
		GenerateDiadic(op_mov,0,ap1,ap3);
	else if (ap3->mode == am_immed) {
		error(ERR_LVALUE);
		if (isFISA64)
		    FISA64_GenLdi(ap1,ap2);
        else
		    GenerateDiadic(op_ldi,0,ap1,ap3);
	}
	else
        GenLoad(ap1,ap3,size);
	MaskShift(op, ap1, size);
	if (ap2->mode==am_immed)
		GenerateTriadic(op,0,ap1,ap1,make_immed(ap2->offset->i));
	else
		GenerateTriadic(op,0,ap1,ap1,ap2);
	if (ap3->mode != am_reg)
        GenStore(ap1,ap3,size);
    ReleaseTempRegister(ap2);
    ReleaseTempRegister(ap3);
    MakeLegalAmode(ap1,flags,size);
    return ap1;
}
示例#7
0
AMODE *GenerateShift(ENODE *node,int flags, int size, int op)
{
	AMODE *ap1, *ap2, *ap3;

    ap3 = GetTempRegister();
    ap1 = GenerateExpression(node->p[0],F_REG,size);
    ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
	MaskShift(op, ap1, GetNaturalSize(node->p[0]));
	if (ap2->mode==am_immed) {
		switch(op)
		{
        case op_asl:    op = op_asli; break;
        case op_sll:    op = op_slli; break;
		case op_shl:	op = op_shli; break;
		case op_shlu:	op = op_shlui; break;
		case op_asr:	op = isThor?op_shri:op_asri; break;
		case op_sra:    op = op_srai; break;
		case op_shr:	op = op_shri; break;
		case op_shru:	op = op_shrui; break;
		case op_srl:    op = op_srli; break;
		case op_lsr:    op = op_lsri; break;
		}
		GenerateTriadic(op,0,ap3,ap1,make_immed(ap2->offset->i));
	}
	else
		GenerateTriadic(op,0,ap3,ap1,ap2);

	ReleaseTempRegister(ap2);
	ReleaseTempRegister(ap1);
    MakeLegalAmode(ap3,flags,size);
    return ap3;
}
示例#8
0
/*  Assums the dseg is the next higher seg value from the cseg	*/
void loadds(void)
{
    gen_code(op_push, makesegreg(DS), 0);
    gen_code(op_push, makesegreg(CS), 0);
    gen_codes(op_add, 2, make_stack(0), make_immed(8));
    gen_code(op_pop, makesegreg(DS), 0);
}
示例#9
0
void bingen(int lower, int avg, int higher,AMODE *ap1, int deflab, int size,long * switchids,int * switchlabels,int *switchbinlabels)
{
	AMODE *ap2 = make_immed(switchids[avg]);
	AMODE *ap3 = make_label(switchlabels[avg]);
	if (switchbinlabels[avg] != -1)
		gen_label(switchbinlabels[avg]);
	gen_code(op_cmp,4,ap1,ap2);
	gen_code(op_je,0,ap3,0);
	if (avg == lower) {
		ap3 = make_label(deflab);
		gen_code(op_jmp,0,ap3,0);
	}
	else {
		int avg1 = (lower + avg)/2;
		int avg2 = (higher + avg+1)/2;
		if (avg+1 < higher) 
			ap3 = make_label(switchbinlabels[avg2]=nextlabel++);
		else
			ap3 = make_label(deflab);
		if (size < 0)
			gen_code(op_jg,0,ap3,0);
		else
			gen_code(op_ja,0,ap3,0);
		bingen(lower,avg1,avg,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
		if (avg+1 < higher)
			bingen(avg+1,avg2,higher,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
	}
}
示例#10
0
void bingen(int lower, int avg, int higher, AMODE *ap1, struct cases *cs, int size)
{
    AMODE *ap2 = make_immed(cs->ptrs[avg].id);
    AMODE *ap3 = make_label(cs->ptrs[avg].label);
    if (cs->ptrs[avg].binlabel !=  - 1)
        gen_label(cs->ptrs[avg].binlabel);
    gen_coden(op_cmp, size, ap1, ap2);
    gen_code(op_je, ap3, 0);
    if (avg == lower)
    {
        if (cs->deflab < 0)
            cs->deflab = nextlabel++;
        ap3 = make_label(cs->deflab);
        gen_code(op_jmp, ap3, 0);
    }
    else
    {
        int avg1 = (lower + avg) / 2;
        int avg2 = (higher + avg + 1) / 2;
        if (avg + 1 < higher)
            ap3 = make_label(cs->ptrs[avg2].binlabel = nextlabel++);
        else
            ap3 = make_label(cs->deflab);
        if (size < 0)
            gen_code(op_jg, ap3, 0);
        else
            gen_code(op_ja, ap3, 0);
        bingen(lower, avg1, avg, ap1, cs, size);
        if (avg + 1 < higher)
            bingen(avg + 1, avg2, higher, ap1, cs, size);
    }
}
示例#11
0
文件: istmt.c 项目: jossk/OrangeC
void gen_genword(STATEMENT *stmt, SYMBOL *funcsp)
/*
 * generate data in the code seg
 */
{
    (void)funcsp;
    gen_icode(i_genword, 0, make_immed(ISZ_NONE,(int)stmt->select), 0);
}
示例#12
0
AMODE *GenerateFunctionCall(ENODE *node, int flags)
{ 
	AMODE *ap, *result;
	SYM *sym;
    int             i;
	int msk;

 	msk = SaveTempRegs();
	sym = NULL;
    i = GeneratePushParameterList(node->p[1]);
	// Call the function
	if( node->p[0]->nodetype == en_nacon ) {
        GenerateDiadic(op_call,0,make_offset(node->p[0]),NULL);
		sym = gsearch(node->p[0]->sp);
	}
    else
    {
		ap = GenerateExpression(node->p[0],F_REG,8);
		ap->mode = am_ind;
		GenerateDiadic(op_jal,0,makereg(31),ap);
		ReleaseTempRegister(ap);
    }
	// Pop parameters off the stack
	if (i!=0) {
		if (sym) {
			if (!sym->IsPascal)
				GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
		}
		else
			GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
	}
	RestoreTempRegs(msk);
    result = GetTempRegister();
    if( result->preg != 1 || (flags & F_REG) == 0 )
		if (sym) {
			if (sym->tp->btp->type==bt_void)
				;
			else
				GenerateDiadic(op_mov,0,result,makereg(1));
		}
		else
			GenerateDiadic(op_mov,0,result,makereg(1));
    return result;
}
示例#13
0
文件: istmt.c 项目: jossk/OrangeC
SYMBOL *gen_vsn_virtual_thunk(SYMBOL *func, int ofs)
{
        QUAD *oi = intermed_head, *ot = intermed_tail;		
        SYMBOL *sp;
        IMODE *ap1,  *ap2;
        char buf[256];
        //sprintf(buf, "@$vsn%s$%d", func->decoratedName, ofs);
        sp = search(buf, gsyms);
        if (sp)
            return sp;
        intermed_head = intermed_tail = NULL;
        blockMax = 0;
        blockCount = tempCount = 0;
        exitBlock = 0;
        IncGlobalFlag();
        sp = Alloc(sizeof(SYMBOL));
        sp->storage_class = sc_static;
        sp->value.i = ofs;
        sp->name = sp->decoratedName = litlate(buf);
        sp->errname = sp->decoratedName;
        sp->staticlabel = FALSE;
        sp->tp = func->tp;
        sp->gennedvirtfunc = TRUE;
        insert(sp, gsyms);
        DecGlobalFlag();
        gen_virtual(sp, FALSE);
        addblock(i_goto);
        gen_icode(i_substack, NULL, ap2 = tempreg(ISZ_ADDR, 0), NULL );
        gen_icode(i_add, ap1 = tempreg(ISZ_ADDR, 0), ap2, make_immed(ISZ_NONE, getSize(bt_pointer)));
        ap1 = indnode(ap1, ISZ_ADDR);
        gen_icode(i_add, ap1, ap1 , make_immed(ISZ_NONE, - ofs));
        ap1 = make_imaddress(varNode(en_napccon, func), ISZ_ADDR);
        gen_icode(i_directbranch, 0, ap1, 0);
        addblock(i_ret);
        optimize();
        rewrite_icode(); /* Translate to machine code & dump */
        if (chosenAssembler->gen->post_function_gen)
            chosenAssembler->gen->post_function_gen(intermed_head);
        gen_endvirtual(sp);
        intermed_head = oi;
        intermed_tail = ot;
        return sp;
}
示例#14
0
AMODE *GenerateFunctionCall(ENODE *node, int flags)
{ 
	AMODE *ap, *result;
	SYM *sym;
    int             i;
	int msk;
	int sp;

 	//msk = SaveTempRegs();
	sp = TempInvalidate();
	sym = (SYM*)NULL;
    i = GeneratePushParameterList(node->p[1]);
	// Call the function
	if( node->p[0]->nodetype == en_cnacon ) {
        GenerateMonadic(op_jsr,0,make_offset(node->p[0]));
		sym = gsearch(node->p[0]->sp);
	}
    else
    {
		ap = GenerateExpression(node->p[0],F_BREG,8);
		ap->mode = am_brind;
		GenerateDiadic(op_jsr,0,makebreg(LR),ap);
		ReleaseTempRegister(ap);
    }
	// Pop parameters off the stack
	if (i!=0) {
		if (sym) {
			if (!sym->IsPascal)
				GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8));
		}
		else
			GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8));
	}
	//RestoreTempRegs(msk);
	TempRevalidate(sp);
	ap = GetTempRegister();
	GenerateDiadic(op_mov,0,ap,makereg(1));
    return ap;
}
示例#15
0
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 
        }
示例#16
0
static void MaskShift(int op, AMODE *ap1, int size)
{
	switch(op) {
	case op_shru:
j1:
		switch (size) {
			case 1:	GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xff)); break;
			case 2:	GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffff)); break;
			case 4:	GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffffffff)); break;
			default:	;
		}
		break;
    case op_srl:
    case op_sra:
	case op_asr:
	case op_shr:
		if (isTable888|isFISA64|isThor) {
			if (ap1->isUnsigned)
				goto j1;
			switch (size) {
				case 1:	GenerateDiadic(op_sxb,0,ap1,ap1); break;
				case 2:	GenerateDiadic(op_sxc,0,ap1,ap1); break;
				case 4:	GenerateDiadic(op_sxh,0,ap1,ap1); break;
				default:	;
			}
		}
		else {
			switch (size) {
				case 1:	GenerateDiadic(op_sext8,0,ap1,ap1); break;
				case 2:	GenerateDiadic(op_sext16,0,ap1,ap1); break;
				case 4:	GenerateDiadic(op_sext32,0,ap1,ap1); break;
				default:	;
			}
		}
		break;
	}
}
示例#17
0
// push entire parameter list onto stack
//
static int GeneratePushParameterList(ENODE *plist)
{
	ENODE *st = plist;
	int i,n;
	// count the number of parameters
	for(n = 0; plist != NULL; n++ )
		plist = plist->p[1];
	// move stack pointer down by number of parameters
	if (st)
		GenerateTriadic(op_subui,0,makereg(regSP),makereg(regSP),make_immed(n*8));
	plist = st;
    for(i = 0; plist != NULL; i++ )
    {
		GeneratePushParameter(plist->p[0],i,n);
		plist = plist->p[1];
    }
    return i;
}
示例#18
0
void scppinit(void)
{
	if (!strcmp(currentfunc->name,"_main")) {
		AMODE *ap1,*ap2,*ap3,*ap4;
		int lbl = nextlabel++;
		initstack();
		ap1 = temp_data();
		ap4 = xalloc(sizeof(AMODE));
		ap4->preg = ap1->preg;
		ap4->mode = am_indisp;
		ap4->offset = makenode(en_icon,0,0);
		ap2 = set_symbol("cppistart",0);
		ap3 = set_symbol("cppiend",0);
		gen_code(op_mov,4,ap1,ap2);
		gen_label(lbl);
		gen_code(op_push,4,ap1,0);
		gen_code(op_call,4,ap4,0);
		gen_code(op_pop,4,ap1,0);
		gen_code(op_add,4,ap1,make_immed(4));
		gen_code(op_cmp,4,ap1,ap3);
		gen_code(op_jb,0,make_label(lbl),0);
		freeop(ap1);
	}
}
示例#19
0
文件: istmt.c 项目: jossk/OrangeC
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP)
/*
 *      generate a return statement.
 */
{
    IMODE *ap,  *ap1, *ap3;
    EXPRESSION ep;
    /* returns a value? */
    if (stmt != 0 && stmt->select != 0)
    {
        if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) ||
                                          basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr))
        {
            SYMBOL *sp = anonymousVar(sc_parameter, &stdpointer);
            EXPRESSION *en = varNode(en_auto, sp);
            IMODE *ap3 = gen_expr(funcsp, stmt->select, 0, ISZ_ADDR), *ap2, *ap1;
            DumpIncDec(funcsp);
            if (!ap3->retval)
            {
                ap1 = LookupLoadTemp(NULL, ap3);
                if (ap1 != ap3)
                {
                    IMODE *barrier;
                    if (stmt->select->isatomic)
                    {
                        barrier = doatomicFence(funcsp, stmt->select, NULL);
                    }
                    gen_icode(i_assn, ap1, ap3, NULL);
                    if (stmt->select->isatomic)
                    {
                        doatomicFence(funcsp, stmt->select, barrier);
                    }
                }
            }
            else
            {
                ap1 = ap3;
            }
            if ((funcsp->linkage == lk_pascal) &&
                basetype(funcsp->tp)->syms->table[0] && 
                ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void)
            {
                sp->offset = funcsp->paramsize;
            }
            else
            {
                sp->offset = chosenAssembler->arch->retblocksize+(funcsp->farproc
                    *getSize(bt_pointer));
                if (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual)
                    sp->offset += getSize(bt_pointer);
            }
                
            en = exprNode(en_l_p, en, NULL);
            ap3 = gen_expr(funcsp, en, 0, ISZ_ADDR);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (en->isatomic)
                {
                    barrier = doatomicFence(funcsp, en, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (en->isatomic)
                {
                    doatomicFence(funcsp, en, barrier);
                }
            }
            gen_icode(i_assnblock, make_immed(ISZ_NONE, basetype(funcsp->tp)->btp->size),
                      ap, ap1);
            ap1 = tempreg(ISZ_ADDR, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, NULL);
        }
        else if (basetype(funcsp->tp)->btp && basetype(funcsp->tp)->btp->type ==
            bt_memberptr)
        {
            ap3 = gen_expr(funcsp, stmt->select, F_VOL, ISZ_ADDR);
            DumpIncDec(funcsp);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (stmt->select->isatomic)
                {
                    barrier = doatomicFence(funcsp, stmt->select, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (stmt->select->isatomic)
                {
                    doatomicFence(funcsp, stmt->select, barrier);
                }
            }
            ap1 = tempreg(ISZ_ADDR, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, 0);
        }
        else
        {
            int size = natural_size(stmt->select);
            ap3 = gen_expr(funcsp, stmt->select, 0, size);
            DumpIncDec(funcsp);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (stmt->select->isatomic)
                {
                    barrier = doatomicFence(funcsp, stmt->select, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (stmt->select->isatomic)
                {
                    doatomicFence(funcsp, stmt->select, barrier);
                }
            }
            if (abs(size) < ISZ_UINT)
                size = -ISZ_UINT;
            ap1 = tempreg(size, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, 0);
        }
    }
    else
    {
        DumpIncDec(funcsp);
    }
    /* create the return or a branch to the return
     * return is put at end of function...
     */
    if (flag)
    {
        int retsize = 0;
        if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall)
        {
           retsize = funcsp->paramsize ;
        }
        gen_label(retlab);
        if (!noepilogue)
        {
            if (allocaAP)
            {
                gen_icode(i_loadstack, 0, allocaAP, 0);
            }
/*			if (funcsp->loadds && funcsp->farproc)
                gen_icode(i_unloadcontext,0,0,0);
*/
        
            gen_icode(i_epilogue,0,0,0);
            if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) {
/*				if (funcsp->loadds)
                    gen_icode(i_unloadcontext,0,0,0);
*/
                gen_icode(i_popcontext, 0,0,0);
                gen_icode(i_rett, 0, make_immed(ISZ_NONE,funcsp->linkage == lk_interrupt), 0);
            } else
            {
                gen_icode(i_ret, 0, make_immed(ISZ_NONE,retsize), 0);
            }
        }
    }
    else
    {	
        /* not using gen_igoto because it will make a new block */
        gen_icode(i_goto, NULL, NULL, NULL);
        intermed_tail->dc.v.label = retlab;
    }
}
示例#20
0
// Generate a function body.
//
void GenerateFunction(SYM *sym, Statement *stmt)
{
	char buf[20];
	char *bl;
	int cnt, nn;
	AMODE *ap;
	ENODE *ep;
	SYM *sp;

	throwlab = retlab = contlab = breaklab = -1;
	lastsph = 0;
	memset(semaphores,0,sizeof(semaphores));
	throwlab = nextlabel++;
	while( lc_auto & 7 )	/* round frame size to word */
		++lc_auto;
	if (sym->IsInterrupt) {
		//GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
		//GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
	}
	if (!sym->IsNocall) {
		GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(32));
		if (lc_auto || sym->NumParms > 0) {
			GenerateDiadic(op_ss|op_sw,0,makereg(regBP),make_indirect(SP));
		}
//		if (sym->UsesPredicate)
			GenerateDiadic(op_ss|op_sws, 0, make_string("pregs"), make_indexed(24,SP));
		// For a leaf routine don't bother to store the link register or exception link register.
		if (!sym->IsLeaf) {
			if (exceptions) {
				GenerateDiadic(op_ss|op_sws, 0, makebreg(CLR), make_indexed(8,SP));
			}
			GenerateDiadic(op_ss|op_sws, 0, makebreg(LR), make_indexed(16,SP));
			if (exceptions) {
				ep = allocEnode();
				ep->nodetype = en_clabcon;
				ep->i = throwlab;
				ap = allocAmode();
				ap->mode = am_immed;
				ap->offset = ep;
				GenerateDiadic(op_ldis,0, makebreg(CLR), ap);
			}
		}
		if (lc_auto || sym->NumParms > 0) {
			GenerateDiadic(op_mov,0,makereg(regBP),makereg(regSP));
			if (lc_auto)
				GenerateTriadic(op_subui,0,makereg(regSP),makereg(regSP),make_immed(lc_auto));
		}

		// Save registers used as register variables.
		// **** Done in Analyze.c ****
		//if( save_mask != 0 ) {
		//	GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8));
		//	cnt = (bitsset(save_mask)-1)*8;
		//	for (nn = 31; nn >=1 ; nn--) {
		//		if (save_mask & (1 << nn)) {
		//			GenerateTriadic(op_sw,0,makereg(nn),make_indexed(cnt,SP),NULL);
		//			cnt -= 8;
		//		}
		//	}
		//}
	}
	if (optimize)
		sym->NumRegisterVars = opt1(stmt);
    GenerateStatement(stmt);
    GenerateReturn(sym,0);
	// Generate code for the hidden default catch
	if (exceptions) {
		if (sym->IsLeaf){
			if (sym->DoesThrow) {
				GenerateLabel(throwlab);
				ap = GetTempRegister();
				GenerateDiadic(op_mfspr,0,ap,makebreg(CLR));
				GenerateDiadic(op_mtspr,0,makebreg(LR),ap);
				ReleaseTempRegister(ap);
				GenerateMonadic(op_bra,0,make_clabel(retlab));				// goto regular return cleanup code
			}
		}
		else {
			GenerateLabel(throwlab);
			GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(8,regBP));		// load throw return address from stack into LR
			GenerateDiadic(op_sws,0,makebreg(regLR),make_indexed(16,regBP));		// and store it back (so it can be loaded with the lm)
			GenerateMonadic(op_bra,0,make_clabel(retlab));				// goto regular return cleanup code
		}
	}
}
示例#21
0
// Generate a return statement.
//
void GenerateReturn(SYM *sym, Statement *stmt)
{
	AMODE *ap;
	int nn;
	int lab1;
	int cnt;

	// Generate code to evaluate the return expression.
    if( stmt != NULL && stmt->exp != NULL )
	{
		initstack();
		ap = GenerateExpression(stmt->exp,F_ALL & ~F_BREG,8);
		// Force return value into register 1
		if( ap->preg != 1 ) {
			if (ap->mode == am_immed)
				GenerateDiadic(op_ldi, 0, makereg(1),ap);
			else if (ap->mode == am_reg)
				GenerateDiadic(op_mov, 0, makereg(1),ap);
			else
				GenerateDiadic(op_lw,0,makereg(1),ap);
		}
	}

	// Generate the return code only once. Branch to the return code for all returns.
	if( retlab == -1 )
    {
		retlab = nextlabel++;
		GenerateLabel(retlab);
		// Unlock any semaphores that may have been set
		for (nn = lastsph - 1; nn >= 0; nn--)
			GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn]));
		if (sym->IsNocall)	// nothing to do for nocall convention
			return;
		// Restore registers used as register variables.
		if( bsave_mask != 0 ) {
			cnt = (bitsset(bsave_mask)-1)*8;
			for (nn = 15; nn >=1 ; nn--) {
				if (bsave_mask & (1 << nn)) {
					GenerateDiadic(op_ss|op_lws,0,makebreg(nn),make_indexed(cnt,SP));
					cnt -= 8;
				}
			}
			GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(bsave_mask)*8));
		}
		if( save_mask != 0 ) {
			cnt = (bitsset(save_mask)-1)*8;
			for (nn = 31; nn >=1 ; nn--) {
				if (save_mask & (1 << nn)) {
					GenerateDiadic(op_ss|op_lw,0,makereg(nn),make_indexed(cnt,SP));
					cnt -= 8;
				}
			}
			GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8));
		}
		// Unlink the stack
		// For a leaf routine the link register and exception link register doesn't need to be saved/restored.
		if (lc_auto || sym->NumParms > 0) {
			GenerateDiadic(op_mov,0,makereg(SP),makereg(regBP));
			GenerateDiadic(op_ss|op_lw,0,makereg(regBP),make_indirect(regSP));
		}
		if (!sym->IsLeaf) {
			if (exceptions)
				GenerateDiadic(op_ss|op_lws,0,makebreg(CLR),make_indexed(8,regSP));
			GenerateDiadic(op_ss|op_lws,0,makebreg(LR),make_indexed(16,regSP));
//			if (sym->UsesPredicate)
		}
		GenerateDiadic(op_ss|op_lws,0,make_string("pregs"),make_indexed(24,regSP));
		//if (isOscall) {
		//	GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave"));
		//	gen_regrestore();
		//}
		// Generate the return instruction. For the Pascal calling convention pop the parameters
		// from the stack.
		if (sym->IsInterrupt) {
			//GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24));
			//GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE));
			//GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8));
			GenerateMonadic(op_rti,0,(AMODE *)NULL);
			return;
		}
		if (sym->IsPascal) {
			GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32+sym->NumParms * 8));
			GenerateMonadic(op_rts,0,(AMODE *)NULL);
		}
		else {
			GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32));
			GenerateMonadic(op_rts,0,(AMODE*)NULL);
		}
    }
	// Just branch to the already generated stack cleanup code.
	else {
		GenerateMonadic(op_bra,0,make_clabel(retlab));
	}
}
示例#22
0
// Generate a function body.
//
void GenerateFunction(SYM *sym, Statement *stmt)
{
	char buf[20];
	char *bl;
	int cnt, nn;
	AMODE *ap;
	ENODE *ep;
	SYM *sp;
  std::string vep;

	throwlab = retlab = contlab = breaklab = -1;
	lastsph = 0;
	memset(semaphores,0,sizeof(semaphores));
	throwlab = nextlabel++;
	retlab = nextlabel++;
	while( lc_auto & 7 )	/* round frame size to word */
		++lc_auto;
	if (sym->IsInterrupt) {
		//GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
		//GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
	}
	if (sym->prolog) {
       if (optimize)
           opt1(sym->prolog);
	   GenerateStatement(sym->prolog);
  }
	if (!sym->IsNocall) {
		GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(-GetReturnBlockSize()));
		if (lc_auto || sym->NumParms > 0) {
			GenerateDiadic(op_sw,0,makereg(regBP),make_indirect(regSP));
		}
//		if (sym->UsesPredicate)
			GenerateDiadic(op_sws, 0, make_string("pregs"), make_indexed(24,regSP));
			GenerateDiadic(op_sw, 0, makereg(regCLP),make_indexed(32,regSP));
		// For a leaf routine don't bother to store the link register or exception link register.
		// Since virtual functions call other functions, they can't be leaf
    // routines.
		if (!sym->IsLeaf || sym->IsVirtual) {
			if (exceptions) {
				GenerateDiadic(op_sws, 0, makebreg(regXLR), make_indexed(8,regSP));
			}
			GenerateDiadic(op_sws, 0, makebreg(regLR), make_indexed(16,regSP));
			if (exceptions) {
				ep = allocEnode();
				ep->nodetype = en_clabcon;
				ep->i = throwlab;
				ap = allocAmode();
				ap->mode = am_immed;
				ap->offset = ep;
				GenerateDiadic(op_ldis,0, makebreg(regXLR), ap);
			}
		}

		GenerateDiadic(op_lw,0,makereg(regCLP),make_indexed(GetReturnBlockSize(),regSP));

    vep = *sym->mangledName;
    vep += "_VEP";
	  GenerateMonadic(op_fnname,0,make_string((char *)vep.c_str()));
	
  	// Generate switch to call derived methods
  	if (sym->IsVirtual || sym->derivitives) {
  	  char buf[20];
  	  char *buf2;
  	  DerivedMethod *mthd;
  	  
  	  dfs.printf("VirtualFunction Switch");
  	  GenerateDiadic(op_lcu,0,makereg(24),make_indirect(regCLP));
  	  mthd = sym->derivitives;
  	  while (mthd) {
     	  sprintf(buf, "p%d", 7);
  	    buf2 = my_strdup(buf);
        GenerateTriadic(op_cmpi,0,make_string(buf2),makereg(24),make_immed(mthd->typeno));
        vep = *(mthd->name);
        vep += "_VEP";      // Virtual Entry Point
     	  GeneratePredicatedMonadic(7,PredOp(op_eq),op_jmp,0,
          make_string((char *)vep.c_str()));   // jump to the method
     	  mthd = mthd->next;
  	  }
    }
		if (lc_auto || sym->NumParms > 0) {
			GenerateDiadic(op_mov,0,makereg(regBP),makereg(regSP));
			if (lc_auto)
				GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(-lc_auto));
		}

		// Save registers used as register variables.
		// **** Done in Analyze.c ****
		//if( save_mask != 0 ) {
		//	GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8));
		//	cnt = (bitsset(save_mask)-1)*8;
		//	for (nn = 31; nn >=1 ; nn--) {
		//		if (save_mask & (1 << nn)) {
		//			GenerateTriadic(op_sw,0,makereg(nn),make_indexed(cnt,SP),NULL);
		//			cnt -= 8;
		//		}
		//	}
		//}
	}
	if (optimize)
		sym->NumRegisterVars = opt1(stmt);
  GenerateStatement(stmt);
  GenerateEpilog(sym);
	// Generate code for the hidden default catch
	if (exceptions) {
		if (sym->IsLeaf){
			if (sym->DoesThrow) {
				GenerateLabel(throwlab);
				ap = GetTempRegister();
				GenerateDiadic(op_mfspr,0,ap,makebreg(regXLR));
				GenerateDiadic(op_mtspr,0,makebreg(regLR),ap);
				ReleaseTempRegister(ap);
				GenerateMonadic(op_br,0,make_clabel(retlab));				// goto regular return cleanup code
			}
		}
		else {
			GenerateLabel(throwlab);
			GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(8,regBP));		// load throw return address from stack into LR
			GenerateDiadic(op_sws,0,makebreg(regLR),make_indexed(16,regBP));		// and store it back (so it can be loaded with the lm)
			GenerateMonadic(op_br,0,make_clabel(retlab));				// goto regular return cleanup code
		}
	}
}
示例#23
0
AMODE *GenerateFunctionCall(ENODE *node, int flags)
{ 
	AMODE *ap, *result;
	SYM *sym;
  int             i;
	int msk;
	int sp;
	int isPascal = FALSE;
 
  dfs.puts("<GenerateFunctionCall>");
 	//msk = SaveTempRegs();
 	if (node->p[0] < (ENODE *)0x0FLL) {
 	  error(ERR_NULLPOINTER);
 	  goto xit1;
 	}
	sp = TempInvalidate();
	sym = (SYM*)NULL;
  i = GeneratePushParameterList(node->p[1]);
	// Call the function
	if( node->p[0]->nodetype == en_cnacon ) {
	  dfs.printf("cnacon node:%s|\n",(char *)node->p[0]->sp->c_str());
//		if (node->p[0]->i==25)
//			GenerateDiadic(op_sw,0,makereg(regCLP),make_indexed(0,regSP));
    if (node->p[0]->sp < (std::string *)0x0FLL)
      node->p[0]->sp = new std::string("<null>");
    GenerateMonadic(op_jsr,0,make_offset(node->p[0]));
    sym = gsearch(*node->p[0]->sp);
    dfs.puts((char*)(node->p[0]->sp->c_str()));
    if (sym) {
       dfs.puts("<found></found>");
       }
    else {
       dfs.printf("<notfound>%s</notfound>",(char*)(node->p[0]->sp->c_str()));
    }
	}
  else
  {

		ap = GenerateExpression(node->p[0],F_BREG,8);
		ap->mode = am_brind;
		isPascal = node->p[0]->isPascal;
		GenerateDiadic(op_jsr,0,makebreg(1),ap);
		ReleaseTempRegister(ap);

    }
	// Pop parameters off the stack
	if (i!=0) {
		if (sym) {
			if (!sym->IsPascal)
				GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8));
		}
		else if (!isPascal)
			GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8));
	}
	//RestoreTempRegs(msk);
	TempRevalidate(sp);
xit1:
	ap = GetTempRegister();
	if (flags & F_NOVALUE)
		;
	else
		GenerateDiadic(op_mov,0,ap,makereg(1));
  dfs.puts("</GenerateFunctionCall>");
    return ap;
}
示例#24
0
// Generate function epilog code.
//
void GenerateEpilog(SYM *sym)
{
	AMODE *ap;
	int nn;
	int lab1;
	int cnt;

	// Generate the return code only once. Branch to the return code for all returns.
	GenerateLabel(retlab);
	// Unlock any semaphores that may have been set
	for (nn = lastsph - 1; nn >= 0; nn--)
		GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn]));
	if (sym->IsNocall)	// nothing to do for nocall convention
		return;
	// Restore registers used as register variables.
	if( bsave_mask != 0 ) {
		cnt = (bitsset(bsave_mask)-1)*8;
		for (nn = 15; nn >=1 ; nn--) {
			if (bsave_mask & (1 << nn)) {
				GenerateDiadic(op_lws,0,makebreg(nn),make_indexed(cnt,regSP));
				cnt -= 8;
			}
		}
		GenerateTriadic(op_addui,0,makereg(SP),makereg(regSP),make_immed(popcnt(bsave_mask)*8));
	}
	if( save_mask != 0 ) {
		cnt = (bitsset(save_mask)-1)*8;
		for (nn = 31; nn >=1 ; nn--) {
			if (save_mask & (1 << nn)) {
				GenerateDiadic(op_lw,0,makereg(nn),make_indexed(cnt,regSP));
				cnt -= 8;
			}
		}
		GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(popcnt(save_mask)*8));
	}
	// Unlink the stack
	// For a leaf routine the link register and exception link register doesn't need to be saved/restored.
	if (lc_auto || sym->NumParms > 0) {
		GenerateDiadic(op_mov,0,makereg(regSP),makereg(regBP));
		GenerateDiadic(op_lw,0,makereg(regBP),make_indirect(regSP));
	}
	if (!sym->IsLeaf) {
		if (exceptions)
			GenerateDiadic(op_lws,0,makebreg(regXLR),make_indexed(8,regSP));        // 11=CLR
		GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(16,regSP));            // 1 = LR
//			if (sym->UsesPredicate)
	}
	GenerateDiadic(op_lws,0,make_string("pregs"),make_indexed(24,regSP));
	GenerateDiadic(op_lw,0,makereg(regCLP),make_indexed(32,regSP));
	    if (sym->epilog) {
           if (optimize)
              opt1(sym->epilog);
	       GenerateStatement(sym->epilog);
	       return;
       }
	//if (isOscall) {
	//	GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave"));
	//	gen_regrestore();
	//}
	// Generate the return instruction. For the Pascal calling convention pop the parameters
	// from the stack.
	if (sym->IsInterrupt) {
		//GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24));
		//GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE));
		//GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8));
		GenerateMonadic(op_rti,0,(AMODE *)NULL);
		return;
	}
	if (sym->IsPascal) {
		GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize()+sym->NumParms * 8));
		GenerateMonadic(op_rts,0,(AMODE *)NULL);
	}
	else {
		GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize()));
		GenerateMonadic(op_rts,0,(AMODE*)NULL);
	}
}
示例#25
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);
    }
}
示例#26
0
文件: istmt.c 项目: doniexun/OrangeC
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP)
/*
 *      generate a return statement.
 */
{
    IMODE *ap = NULL,  *ap1, *ap3;
    EXPRESSION ep;
    int size;
    /* returns a value? */
    if (stmt != 0 && stmt->select != 0)
    {
        if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) ||
                                          basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr))
        {
            EXPRESSION *en = anonymousVar(sc_parameter, &stdpointer);
            SYMBOL *sp = en->v.sp;
            gen_expr(funcsp, stmt->select, 0, ISZ_ADDR);
            DumpIncDec(funcsp);
            sp->offset = chosenAssembler->arch->retblocksize;
            sp->allocate = FALSE;
            if ((funcsp->linkage == lk_pascal) &&
                    basetype(funcsp->tp)->syms->table[0] && 
                    ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void)
                sp->offset = funcsp->paramsize;
            deref(&stdpointer, &en);
            ap = gen_expr(funcsp, en, 0, ISZ_ADDR);
            size = ISZ_ADDR;
        }
        else
        {
            size = natural_size(stmt->select);
            ap3 = gen_expr(funcsp, stmt->select, 0, size);
            DumpIncDec(funcsp);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (stmt->select->isatomic)
                {
                    barrier = doatomicFence(funcsp, stmt->select, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (stmt->select->isatomic)
                {
                    doatomicFence(funcsp, stmt->select, barrier);
                }
            }
            if (abs(size) < ISZ_UINT)
                size = -ISZ_UINT;
        }
    }
    else
    {
        DumpIncDec(funcsp);
    }
    if (ap)
    {
        ap1 = tempreg(size, 0);
        ap1->retval = TRUE;
        gen_icode(i_assn, ap1, ap, 0);
    }
    if (stmt && stmt->destexp)
    {
        gen_expr(funcsp, stmt->destexp, F_NOVALUE, ISZ_ADDR);
    }
    /* create the return or a branch to the return
     * return is put at end of function...
     */
    if (flag)
    {
        int retsize = 0;
        if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall)
        {
           retsize = funcsp->paramsize ;
        }
        gen_label(retlab);
        if (!noepilogue)
        {
            if (allocaAP)
            {
                gen_icode(i_loadstack, 0, allocaAP, 0);
            }
/*			if (funcsp->loadds && funcsp->farproc)
                gen_icode(i_unloadcontext,0,0,0);
*/
        
            if (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcRundownFunc)
                gen_expr(funcsp, funcsp->xc->xcRundownFunc, F_NOVALUE, ISZ_UINT);
            gen_icode(i_epilogue,0,0,0);
            if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) {
/*				if (funcsp->loadds)
                    gen_icode(i_unloadcontext,0,0,0);
*/
                gen_icode(i_popcontext, 0,0,0);
                gen_icode(i_rett, 0, make_immed(ISZ_UINT,funcsp->linkage == lk_interrupt), 0);
            } else
            {
                gen_icode(i_ret, 0, make_immed(ISZ_UINT,retsize), 0);
            }
        }
    }
    else
    {	
        /* not using gen_igoto because it will make a new block */
        gen_icode(i_goto, NULL, NULL, NULL);
        intermed_tail->dc.v.label = retlab;
    }
}
示例#27
0
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);
				}
}
示例#28
0
void genstmt(SNODE *stmt)
/*
 *      genstmt will generate a statement and follow the next pointer
 *      until the block is generated.
 */
{
		   while( stmt != 0 )
                {
                switch( stmt->stype )
                        {
												case st_block:
																genstmt(stmt->exp);
																break;
                        case st_label:
                                gen_label((int)stmt->label);
                                break;
                        case st_goto:
                                gen_code(op_jmp,0,make_label((int)stmt->label),0);
                                break;
                        case st_expr:
                                initstack();
                                gen_expr(stmt->exp,F_ALL | F_NOVALUE,
                                        natural_size(stmt->exp));
                                break;
                        case st_return:
                                genreturn(stmt,0);
                                break;
                        case st_if:
                                genif(stmt);
                                break;
                        case st_while:
                                genwhile(stmt);
                                break;
                        case st_do:
                                gendo(stmt);
                                break;
                        case st_for:
                                gen_for(stmt);
                                break;
                        case st_continue:
                                gen_code(op_jmp,0,make_label(contlab),0);
                                break;
                        case st_break:
                                gen_code(op_jmp,0,make_label(breaklab),0);
                                break;
                        case st_switch:
                                genxswitch(stmt);
                                break;
												case st_line:
		 														gen_line(stmt);
																break;
												case st_asm:
																if (stmt->exp)
																	add_peep(stmt->exp);
																break;
												case st__genword:
																gen_code(op_genword,0,make_immed((int)stmt->exp),0);
																break;
                        default:

                                diag("unknown statement.");
                                break;
                        }
                stmt = stmt->next;
                }
}
示例#29
0
文件: istmt.c 项目: jossk/OrangeC
/*-------------------------------------------------------------------------*/
void gen_tryblock(void *val)
{
    /* xceptoffs will be put in the label field later */
    gen_icode(i_tryblock, 0, make_immed(ISZ_NONE, (int)val), 0);
}
示例#30
0
void allocate(int datareg, int addreg, int floatreg, SNODE *block )
/*
 *      allocate will allocate registers for the expressions that have
 *      a high enough desirability.
 */
{       CSE      *csp;
        ENODE    *exptr;
        unsigned      mask, rmask,i,fmask,frmask,size;
        AMODE    *ap, *ap2;
				framedepth = 4+lc_maxauto;
        mask = 0;
				rmask = 0;
				fmask = frmask = 0;
				for (i=cf_freedata; i < datareg; i++) {
						framedepth+=4;
						rmask = rmask | (1 << (15 - i));
                        mask = mask | (1 << i);
				}
				for (i=cf_freeaddress+16; i < addreg; i++) {
						framedepth+=4;
						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) {
										if (floatreg <24 && floatregs)
											csp->reg = floatreg++;
									}
			            else if( (datareg < cf_maxdata) && (csp->duses <= csp->uses/4) && dataregs)
                    csp->reg = (datareg)++;
      	      		else if( !(csp->size == 1 || csp->size == -1) && (addreg < cf_maxaddress) &&addrregs)
        	          csp->reg = (addreg)++;
								}
						}
            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])->inreg = TRUE;
							((SYM *)csp->exp->v.p[0]->v.p[0])->value.i = -csp->reg;
						}
						if (csp->reg < 16) {
							framedepth+=4;
							rmask = rmask | (1 << (15 - csp->reg));
                        mask = mask | (1 << csp->reg);
						}
						else if (csp->reg < 32) {
							framedepth+=4;
							rmask = rmask | (1 << (23 - csp->reg));
                        mask = mask | (1 << (csp->reg-8));
						}
						else {
							framedepth+=12;
							frmask = frmask | (1 << (39 - csp->reg));
              fmask = fmask | (1 << (csp->reg-32));
						}
				}
                csp = csp->next;
                }
				allocstack();								/* Allocate stack space for the local vars */
				if (currentfunc->tp->lst.head !=0 && currentfunc->tp->lst.head != (SYM *)-1) {
					if (prm_phiform || currentfunc->intflag) {
						mask |= (1 << (linkreg +8));
						rmask |= (1 << (15 - linkreg -8));
						framedepth+=4;
					}
					if (currentfunc->intflag) {
						mask |= 0xffff;
						rmask |= 0xffff;
						framedepth = lc_maxauto;
					}
				}
				if (prm_linkreg && !currentfunc->intflag && (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1 || lc_maxauto)) {
					gen_code(op_link,0,makeareg(linkreg),make_immed(-lc_maxauto));
				}				
			  if( mask != 0 ) 
              gen_code(op_movem,4,make_mask(rmask,0,0),push);
        save_mask = mask;
				if (fmask!=0)
                gen_code(op_fmovem,10,make_mask(frmask,0,1),push);
				fsave_mask = fmask;
				if ((prm_phiform || currentfunc->intflag) && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) {
					gen_code(op_move,4,makeareg(0), makeareg(linkreg));
				}
				if ((!prm_linkreg || currentfunc->intflag) && lc_maxauto) {
					AMODE *ap = xalloc(sizeof(AMODE)); 
					ap->mode = am_indx;
					ap->offset = makenode(en_icon,(char *)-lc_maxauto,0);
					ap->preg = 7;
          gen_code(op_lea,0,ap,makeareg(7));
				}
				
				if (prm_stackcheck) {
					AMODE *ap1;
					ap = set_symbol("_stackerror",1);
					ap1 = set_symbol("_stackbottom",0);
					if (prm_rel) {
						ap1->mode = am_indx;
						ap1->preg = basereg;
					}
					else {
						ap1->mode = am_adirect;
						if (prm_smalldata)
							ap1->preg = 2;
						else
							ap1->preg = 4;
					}
					gen_code(op_cmp,4,ap1,makeareg(7));
					gen_code(op_bhi,0,ap,0);
				}
}