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; } }
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); } } }
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 ); } }