Пример #1
0
void Assem_x86::emitImm( const Operand &o,int size ) {

    if( size<4 && o.immLabel.size() ) throw Ex( "immediate value cannot by a label" );

    switch( size ) {
    case 1:
        emit( o.imm );
        return;
    case 2:
        emitw( o.imm );
        return;
    case 4:
        a_reloc( o.immLabel );
        emitd( o.imm );
        return;
    }
}
Пример #2
0
static void gen(Error_printer *err, Frag *frag, Node * n)
{
	switch(n->what) {
		case nCOMMA: {
			genn(err, frag, n->l), gen(err, frag, n->r);
			break;
		} case nPAREN: {
			gen(err, frag, n->r);
			break;
		} case nLIST: {
			int amnt = genl(err, frag, n->r);
			push_lst(frag);
			emitn(frag, amnt);
			emitc(frag, iFIX);
			fixlooplvl(frag, amnt);
			break;
		} case nVOID: {
			push_void(frag);
			break;
		} case nTHIS: {
			push_this(frag);
			break;
		} case nNUM: {
			push_num(frag);
			emitl(frag, n->n);
			break;
		} case nFP: {
			push_fp(frag);
			emitd(frag, n->fp);
			break;
		} case nSTR: {
			push_str(frag);
			emits(frag, n->s, n->n);
			break;
		} case nNAM: {
			push_nam(frag);
			emitp(frag, n->s);
			emitc(frag, iGET_ATOM);
			break;
		} case nSET: {
			gen(err, frag, n->r);
//			gena(err, frag, n->l);  (lvalue change)
			gen(err, frag, n->l);
			emitc(frag, iSET);
			rmlooplvl(frag, lvlVALUE, 0, 0);
			break;
		} case nIF: {
			gencond(err, frag, n->r, 1);
			break;
		} case nPOST: {
			gen(err, frag, n->l);
			gen(err, frag, n->r);
//			gena(err, frag, n->l); (lvalue change)
			gen(err, frag, n->l);
			emitc(frag, iSET);
			rmlooplvl(frag, lvlVALUE, 0, 0);
			emitc(frag, iPOP);
			rmlooplvl(frag, lvlVALUE, 0, 0);
			break;
		} case nADDR: {
			/* Generate a code snippet */
			genfunc(err, frag, consempty(n->loc), n->r);
			break;
		} case nDEFUN: {
			if (n->r->what==nSEMI) {
				if (n->r->l->what==nCALL && n->r->l->l->what==nNAM) { /* fn sq(x) x*x */
					genfunc(err, frag, n->r->l->r, n->r->r);
					push_nam(frag);
					emitp(frag, n->r->l->l->s);
					emitc(frag, iGETF_ATOM);
					emitc(frag, iSET);
					rmlooplvl(frag, lvlVALUE, 0, 0);
				} else if (n->r->l->what==nNAM && n->r->r->what==nSEMI && n->r->r->l->what==nPAREN) { /* fn sq (x) x*x */
					genfunc(err, frag, n->r->r->l, n->r->r->r);
					push_nam(frag);
					emitp(frag, n->r->l->s);
					emitc(frag, iGETF_ATOM);
					emitc(frag, iSET);
					rmlooplvl(frag, lvlVALUE, 0, 0);
				} else if (n->r->l->what==nNAM && n->r->r->what==nPAREN) { /* fn sq (x) */
					genfunc(err, frag, n->r->r, consempty(n->loc));
					push_nam(frag);
					emitp(frag, n->r->l->s);
					emitc(frag, iGETF_ATOM);
					emitc(frag, iSET);
					rmlooplvl(frag, lvlVALUE, 0, 0);
				} else if (n->r->l->what==nPAREN) { /* fn (x) x*x */
					genfunc(err, frag, n->r->l, n->r->r);
				} else {
					error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line);
					push_void(frag);
				}
			} else if(n->r->what==nCALL && n->r->l->what==nNAM) { /* fn sq(x) */
				genfunc(err, frag, n->r->r, consempty(n->loc));
				push_nam(frag);
				emitp(frag, n->r->l->s);
				emitc(frag, iGETF_ATOM);
				emitc(frag, iSET);
				rmlooplvl(frag, lvlVALUE, 0, 0);
			} else if(n->r->what==nPAREN) { /* fn () */
				genfunc(err,frag, n->r, consempty(n->loc));
			} else {
				error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line);
				push_void(frag);
			}
			break;
		} case nLAMBDA: {
			genfunc(err, frag, n->r->l, n->r->r);
			break;
		} case nSEMI: {
			if (n->r->what == nELSE) {
				int done = genelif(err, frag, n->l, 1);
				if (!done)
					error_2(err, "\"%s\" %d: else w/o if error", n->r->loc->name, n->r->loc->line);
				if (n->r->r->what == nIF) {
					addlist(frag, done, genbra(err, frag, n->r->r->l, 1));
					n = n->r;
				}
				mklooplvl(frag, lvlSCOPE, 0, 0);
				gen(err, frag, n->r->r);
				rmlooplvl(frag, lvlSCOPE, 0, 0);
				setlist(frag, done, frag->code);
			} else {
				genn(err, frag, n->l);
				gen(err, frag, n->r);
			}
			break;
		} case nEQ: case nNE: case nGT: case nLT: case nGE: case nLE: case nLAND: case nLOR: case nNOT: {
			int b = genbra(err, frag, n, 1);
			int link;
			push_num(frag);
			emitl(frag, 1);
			emitc(frag, iBRA);
			link=emitn(frag, 0);
			setlist(frag, b, frag->code);
			push_num(frag);
			emitl(frag, 0);
			*(int *)(frag->begcode+link)=frag->code-link;
			break;
		} case nCALL: {
//			int nargs = genl(err, frag, n->r); /* By value */
			int nargs = gencl(err, frag, n->r); /* Functionalize */
			push_lst(frag);
			emitn(frag, nargs);
//			gena(err, frag, n->l); (lvalue change)
			gen(err, frag, n->l);
			emitc(frag, iCALL);
			fixlooplvl(frag, nargs + 1);
			break;
		} case nCALL1: { /* Ends up being the same as above */
//			if (n->r->what != nNAM)
//				error_2(err, "\"%s\" %d: Invalid member name", n->r->loc->name, n->r->loc->line);
			if (n->r->what == nNAM) { /* Turn it into a string .x -> ."x" */
				n->r->what = nSTR;
			}
			int nargs = gencl(err, frag, n->r);
//			push_str(frag);
//			emits(frag, n->r->s, n->r->n);
			push_lst(frag);
			emitn(frag, nargs);
//			gena(err, frag, n->l); (lvalue change)
			gen(err, frag, n->l);
			emitc(frag, iCALL);
			fixlooplvl(frag, nargs + 1);
			break;
		} case nCOM: case nNEG: case nSHL: case nSHR: case nMUL: case nDIV: case nMOD: case nAND:
		  case nADD: case nSUB: case nOR: case nXOR: case nAT: {
			if (n->l)
				gen(err, frag, n->l);
			if (n->r)
				gen(err, frag, n->r);
			emitc(frag, what_tab[n->what].i);
			if (n->r && n->l)
				rmlooplvl(frag, lvlVALUE, 0, 0);
			break;
		} default: {
			genn(err, frag, n);
			push_void(frag);
		}
	}
}
Пример #3
0
void Assem_x86::assemInst( const string &name,const string &lhs,const string &rhs ) {

    //parse operands
    Operand lop( lhs ),rop( rhs );
    lop.parse();
    rop.parse();

    //find instruction
    int cc=-1;
    Inst *inst=0;

    //kludge for condition code instructions...
    if( name[0]=='j' ) {
        if( (cc=findCC(name.substr(1)))>=0 ) {
            static Inst jCC= { "jCC",IMM,NONE,RW_RD|PLUSCC,"\x2\x0F\x80" };
            inst=&jCC;
        }
    } else if( name[0]=='s' && name.substr( 0,3 )=="set" ) {
        if( (cc=findCC(name.substr(3)))>=0 ) {
            static Inst setCC= { "setne",R_M8,NONE,_2|PLUSCC,"\x2\x0F\x90" };
            inst=&setCC;
        }
    }

    if( inst ) {
        if( !(lop.mode&inst->lmode) || !(rop.mode&inst->rmode) ) throw Ex( "illegal addressing mode" );
    } else {
        InstIter it=instMap.find( name );
        if( it==instMap.end() ) throw Ex( "unrecognized instruction" );
        inst=it->second;
        for(;;) {
            if( (lop.mode&inst->lmode) && (rop.mode&inst->rmode) ) break;
            if( (++inst)->name ) throw Ex( "illegal addressing mode" );
        }
    }

    //16/32 bit modifier - NOP for now
    if( inst->flags & (O16|O32) ) {}

    int k,n=inst->bytes[0];
    for( k=1; k<n; ++k ) emit( inst->bytes[k] );
    if( inst->flags&PLUSREG ) emit( inst->bytes[k]+lop.reg );
    else if( inst->flags&PLUSCC ) emit( inst->bytes[k]+cc );
    else emit( inst->bytes[k] );

    if( inst->flags&(_0|_1|_2|_3|_4|_5|_6|_7|_R ) ) {

        //find the memop;
        const Operand &mop=
            (inst->rmode&(MEM|MEM8|MEM16|MEM32|R_M|R_M8|R_M16|R_M32))?rop:lop;

        //find the spare field value.
        int rm=0;
        switch( inst->flags&(_0|_1|_2|_3|_4|_5|_6|_7|_R ) ) {
        case _0:
            rm=0;
            break;
        case _1:
            rm=1;
            break;
        case _2:
            rm=2;
            break;
        case _3:
            rm=3;
            break;
        case _4:
            rm=4;
            break;
        case _5:
            rm=5;
            break;
        case _6:
            rm=6;
            break;
        case _7:
            rm=7;
            break;
        case _R:
            rm=(inst->rmode&(REG8|REG16|REG32))?rop.reg:lop.reg;
            break;
        }
        rm<<=3;
        if( mop.mode & REG ) {			//reg
            emit( 0xc0|rm|mop.reg );
        } else if( mop.baseReg>=0 ) {		//base, index?
            int mod=mop.offset ? 0x40 : 0x00;
            if( mop.baseLabel.size() || mop.offset<-128 || mop.offset>127 ) mod=0x80;
            if( mop.baseReg==5 && !mod ) mod=0x40;
            if( mop.indexReg>=0 ) {		//base, index!
                emit( mod|rm|4 );
                emit( (mop.shift<<6)|(mop.indexReg<<3)|mop.baseReg );
            } else {						//base, no index!
                if( mop.baseReg!=4 ) emit( mod|rm|mop.baseReg);
                else {
                    emit( mod|rm|4 );
                    emit( (4<<3)|mop.baseReg );
                }
            }
            if( (mod&0xc0)==0x40 ) emit( mop.offset );
            else if( (mod&0xc0)==0x80 ) {
                //reloc
                a_reloc( mop.baseLabel );
                emitd( mop.offset );
            }
        } else if( mop.indexReg>=0 ) {	//index, no base!
            emit( rm|4 );
            emit( (mop.shift<<6)|(mop.indexReg<<3)|5 );
            //reloc
            a_reloc( mop.baseLabel );
            emitd( mop.offset );
        } else {							//[disp]
            emit( rm|5 );
            //reloc
            a_reloc( mop.baseLabel );
            emitd( mop.offset );
        }
    }

    if( inst->flags&RW_RD ) {
        r_reloc( lop.immLabel );
        emitd( lop.imm-4 );
    }

    if( inst->flags&IB ) {
        if( lop.mode&IMM ) emitImm( lop,1 );
        else emitImm( rop,1 );
    } else if( inst->flags&IW ) {
        if( lop.mode&IMM ) emitImm( lop,2 );
        else emitImm( rop,2 );
    } else if( inst->flags&ID ) {
        if( lop.mode&IMM ) emitImm( lop,4 );
        else emitImm( rop,4 );
    }
}