void commit(void) { if (Q_cmp != cnone) { commit_cmp(); return; } if (Q_bool != bnone) { commit_bool(); return; } if (empty == Q_type) return; spill(); switch (Q_type) { case addr_auto: cgldla(Q_val); break; case addr_static: cgldsa(Q_val); break; case addr_globl: cgldga(gsym(Q_name)); break; case addr_label: cgldlab(Q_val); break; case literal: cglit(Q_val); break; case auto_byte: cgclear(); cgldlb(Q_val); break; case auto_word: cgldlw(Q_val); break; case static_byte: cgclear(); cgldsb(Q_val); break; case static_word: cgldsw(Q_val); break; case globl_byte: cgclear(); cgldgb(gsym(Q_name)); break; case globl_word: cgldgw(gsym(Q_name)); break; default: fatal("internal: unknown Q_type"); } load(); Q_type = empty; }
void genstore(int *lv) { if (NULL == lv) return; gentext(); if (!lv[LVSYM]) { cgpopptr(); if (PCHAR == lv[LVPRIM]) cgstorib(); else cgstoriw(); } else if (CAUTO == Stcls[lv[LVSYM]]) { if (PCHAR == lv[LVPRIM]) cgstorlb(Vals[lv[LVSYM]]); else cgstorlw(Vals[lv[LVSYM]]); } else if (CLSTATC == Stcls[lv[LVSYM]]) { if (PCHAR == lv[LVPRIM]) cgstorsb(Vals[lv[LVSYM]]); else cgstorsw(Vals[lv[LVSYM]]); } else { if (PCHAR == lv[LVPRIM]) cgstorgb(gsym(Names[lv[LVSYM]])); else cgstorgw(gsym(Names[lv[LVSYM]])); } }
void geninc(int *lv, int inc, int pre) { int y, b; gentext(); y = lv[LVSYM]; if (needscale(lv[LVPRIM])) { genincptr(lv, inc, pre); return; } b = PCHAR == lv[LVPRIM]; /* will duplicate move to aux register in (*char)++ */ commit(); if (!y && !pre) cgldinc(); if (!pre) { genrval(lv); commit(); } if (!y) { if (pre) if (inc) b? cginc1ib(): cginc1iw(); else b? cgdec1ib(): cgdec1iw(); else if (inc) b? cginc2ib(): cginc2iw(); else b? cgdec2ib(): cgdec2iw(); } else if (CAUTO == Stcls[y]) { if (inc) b? cginclb(Vals[y]): cginclw(Vals[y]); else b? cgdeclb(Vals[y]): cgdeclw(Vals[y]); } else if (CLSTATC == Stcls[y]) { if (inc) b? cgincsb(Vals[y]): cgincsw(Vals[y]); else b? cgdecsb(Vals[y]): cgdecsw(Vals[y]); } else { if (inc) b? cgincgb(gsym(Names[y])): cgincgw(gsym(Names[y])); else b? cgdecgb(gsym(Names[y])): cgdecgw(gsym(Names[y])); } if (pre) genrval(lv); }
void genname(char *name) { genraw(gsym(name)); genraw(":\n"); }
A pString_Connection::syncSendCover(A msg_, A aTimeout) { struct timeval gameover, *tvp; I rc; ipcWarn(wrnlvl(),"%t pString_Connection::syncSend\n"); tvp = atotv(aTimeout, &gameover); if(writeChannel()==0) return syncErrorResult("nochan","channel is null"); /* put stuff on queue */ int dataSize = msg_->n; int bufferSize = HeaderLength +dataSize; int temp = htonl(dataSize); MSBuffer *sb=new MSBuffer( bufferSize); if(NULL==sb) return syncErrorResult("Buffer","new MSBuffer routine failed."); sb->stuff((char *)(&temp), HeaderLength); sb->stuff((const char *)msg_->p, dataSize); sendTheBuffer(sb); /* while loop on select() until timeout or write queue empty */ rc=syncWriteLoop(tvp); if(0>rc) return syncErrorResult(errorSymbol,errorMessage); else return gvi(Et,3,gsym("OK"),gi(rc),writeQueueStatus()); }
/* generate a test. set 'inv' to invert test. Stack entry is popped */ int gtst(int inv, int t) { int v, *p, c; v = vtop->r & VT_VALMASK; if (v == VT_CMP) { c = vtop->c.i ^ inv; switch(c) { case TOK_EQ: c = IL_OP_BEQ; break; case TOK_NE: c = IL_OP_BNE_UN; break; case TOK_LT: c = IL_OP_BLT; break; case TOK_LE: c = IL_OP_BLE; break; case TOK_GT: c = IL_OP_BGT; break; case TOK_GE: c = IL_OP_BGE; break; case TOK_ULT: c = IL_OP_BLT_UN; break; case TOK_ULE: c = IL_OP_BLE_UN; break; case TOK_UGT: c = IL_OP_BGT_UN; break; case TOK_UGE: c = IL_OP_BGE_UN; break; } t = out_opj(c, t); } else if (v == VT_JMP || v == VT_JMPI) { /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ p = &vtop->c.i; while (*p != 0) p = (int *)*p; *p = t; t = vtop->c.i; } else { t = gjmp(t); gsym(vtop->c.i); } } vtop--; return t; }
A getBeamMSyncMode(void) { if(msyncMode) { if(msyncFlag&MS_ASYNC && msyncFlag&MS_INVALIDATE) return gvi(Et,2,MS(si("MS_ASYNC")),MS(si("MS_INVALIDATE"))); else if(msyncFlag&MS_SYNC && msyncFlag&MS_INVALIDATE) return gvi(Et,2,MS(si("MS_SYNC")),MS(si("MS_INVALIDATE"))); else if(msyncFlag==MS_ASYNC) return gsym("MS_ASYNC"); else if(msyncFlag==MS_SYNC) return gsym("MS_SYNC"); else return gi(msyncFlag); } else return gsym("none"); }
void gencall(int y) { gentext(); commit(); cgcall(gsym(symbols[y].name)); load(); }
static void genincptr(int *lv, int inc, int pre) { int y, size; size = objsize(deref(lv[LVPRIM]), TVARIABLE, 1); gentext(); y = lv[LVSYM]; commit(); if (!y && !pre) cgldinc(); if (!pre) { genrval(lv); commit(); } if (!y) { if (pre) if (inc) cginc1pi(size); else cgdec1pi(size); else if (inc) cginc2pi(size); else cgdec2pi(size); } else if (CAUTO == Stcls[y]) { if (inc) cgincpl(Vals[y], size); else cgdecpl(Vals[y], size); } else if (CLSTATC == Stcls[y]) { if (inc) cgincps(Vals[y], size); else cgdecps(Vals[y], size); } else { if (inc) cgincpg(gsym(Names[y]), size); else cgdecpg(gsym(Names[y]), size); } if (pre) genrval(lv); }
A pString_Connection::syncReadCover(A aTimeout) { struct timeval gameover, *tvp; A dataobj; ipcWarn(wrnlvl(),"%t pString_Connection::SyncRead\n"); tvp = atotv(aTimeout, &gameover); if(readChannel()==0) return syncErrorResult("nochan","channel is null"); /* while loop on select() until timeout or complete message received */ dataobj=syncReadLoop(tvp); if (dataobj) return gvi(Et,3,gsym("OK"),dataobj,aplus_nl); else return syncErrorResult(errorSymbol, errorMessage); }
/* generate a test. set 'inv' to invert test. Stack entry is popped */ int gtst(int inv, int t) { int v, *p; v = vtop->r & VT_VALMASK; if (v == VT_CMP) { /* fast case : can jump directly since flags are set */ g(0x0f); t = psym((vtop->c.i - 16) ^ inv, t); } else if (v == VT_JMP || v == VT_JMPI) { /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ p = &vtop->c.i; while (*p != 0) p = (int *)(cur_text_section->data + *p); *p = t; t = vtop->c.i; } else { t = gjmp(t); gsym(vtop->c.i); } } else { if (is_float(vtop->type.t) || (vtop->type.t & VT_BTYPE) == VT_LLONG) { vpushi(0); gen_op(TOK_NE); } if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { /* constant jmp optimization */ if ((vtop->c.i != 0) != inv) t = gjmp(t); } else { v = gv(RC_INT); o(0x85); o(0xc0 + v * 9); g(0x0f); t = psym(0x85 ^ inv, t); } } vtop--; return t; }
// Generate a test. set 'inv' to invert test. Stack entry is popped. int gtst(int inv, int t) { int v, r, *p; v = vtop->r & VT_VALMASK; if (v == VT_CMP) { // Fast case: can jump directly since flags are set t = gjmp(t, vtop->c.i ^ inv); // jcc t } else if (v == VT_JMP || v == VT_JMPI) { // && or || optimization if ((v & 1) == inv) { // Insert vtop->c jump list in t p = &vtop->c.i; while (*p != 0) { p = &branch[*p].target; } *p = t; t = vtop->c.i; } else { t = gjmp(t, 0); gsym(vtop->c.i); } } else { if (is_float(vtop->type.t) || (vtop->type.t & VT_BTYPE) == VT_LLONG) { vpushi(0); gen_op(TOK_NE); } if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { // Constant jmp optimization if ((vtop->c.i != 0) != inv) t = gjmp(t, 0); } else { r = gv(RC_INT); o(0x85); // test r,r o(0xc0 + r * 9); t = gjmp(t, TOK_NE ^ inv); // jz/jnz t } } vtop--; return t; }
/* load 'r' from value 'sv' */ void load(int r, SValue *sv) { int v, t, ft, fc, fr; SValue v1; fr = sv->r; ft = sv->type.t; fc = sv->c.ul; v = fr & VT_VALMASK; if (fr & VT_LVAL) { if (v == VT_LLOCAL) { v1.type.t = VT_INT; v1.r = VT_LOCAL | VT_LVAL; v1.c.ul = fc; load(r, &v1); fr = r; } if ((ft & VT_BTYPE) == VT_FLOAT) { o(0xd9); /* flds */ r = 0; } else if ((ft & VT_BTYPE) == VT_DOUBLE) { o(0xdd); /* fldl */ r = 0; } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { o(0xdb); /* fldt */ r = 5; } else if ((ft & VT_TYPE) == VT_BYTE) { o(0xbe0f); /* movsbl */ } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { o(0xb60f); /* movzbl */ } else if ((ft & VT_TYPE) == VT_SHORT) { o(0xbf0f); /* movswl */ } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { o(0xb70f); /* movzwl */ } else { o(0x8b); /* movl */ } gen_modrm(r, fr, sv->sym, fc); } else { if (v == VT_CONST) { o(0xb8 + r); /* mov $xx, r */ gen_addr32(fr, sv->sym, fc); } else if (v == VT_LOCAL) { o(0x8d); /* lea xxx(%ebp), r */ gen_modrm(r, VT_LOCAL, sv->sym, fc); } else if (v == VT_CMP) { oad(0xb8 + r, 0); /* mov $0, r */ o(0x0f); /* setxx %br */ o(fc); o(0xc0 + r); } else if (v == VT_JMP || v == VT_JMPI) { t = v & 1; oad(0xb8 + r, t); /* mov $1, r */ o(0x05eb); /* jmp after */ gsym(fc); oad(0xb8 + r, t ^ 1); /* mov $0, r */ } else if (v != r) { o(0x89); o(0xc0 + r + v * 8); /* mov v, r */ } } }
void genpublic(char *name) { cgpublic(gsym(name)); }
void load(int r, SValue* sv) { int fr,ft,fc; int length; int align; int v,sign,t; SValue v1; pr("; load %d\n",r); pr("; type %d reg 0x%x extra 0x%x\n",sv->type.t,sv->r,sv->type.extra); fr = sv->r; ft = sv->type.t; fc = sv->c.ul; length = type_size(&sv->type, &align); if((ft & VT_BTYPE) == VT_LLONG) length = 2; // long longs are handled word-wise if(ll_workaround) length = 4; //pr("; load r 0x%x fr 0x%x ft 0x%x fc 0x%x\n",r,fr,ft,fc); #if 0 // FIXME: Does that make sense? if(fc>0) sign=0; else { sign = 1; fc = -fc; } #endif int base = -1; v = fr & VT_VALMASK; if(fr & VT_LVAL) { if(v == VT_LLOCAL) { v1.type.t = VT_PTR; v1.r = VT_LOCAL | VT_LVAL; v1.c.ul = sv->c.ul; load(base=10 /* lr */, &v1); fc=sign=0; v=VT_LOCAL; } else if(v == VT_CONST) { if(fr & VT_SYM) { // deref symbol + displacement char* sy = get_sym_str(sv->sym); if(is_float(ft)) { pr("; fld%d [%s + %d], tcc__f%d\n", length, sy, fc, r - TREG_F0); switch(length) { case 4: pr("lda.l %s + %d\nsta.b tcc__f%d\nlda.l %s + %d + 2\nsta.b tcc__f%dh\n", sy, fc, r - TREG_F0, sy, fc, r - TREG_F0); break; default: error("ICE 1"); } } else { pr("; ld%d [%s + %d], tcc__r%d\n", length, sy, fc, r); // FIXME: This implementation is moronic if(fc > 65535) error("index too big"); switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda.l %s + %d\nrep #$20\n", sy, fc); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nldx #%d\nlda.l %s,x\nsta.b tcc__r%d\n", r, fc, sy, r); break; case 2: pr("lda.l %s + %d\nsta.b tcc__r%d\n", sy, fc, r); break; case 4: pr("lda.l %s + %d\nsta.b tcc__r%d\nlda.l %s + %d + 2\nsta.b tcc__r%dh\n", sy, fc, r, sy, fc, r); break; default: error("ICE 1"); } } } else { // deref constant pointer //error("ld [%d],tcc__r%d\n",fc,r); pr("; deref constant ptr ld [%d],tcc__r%d\n", fc, r); if(is_float(ft)) { error("dereferencing constant float pointers unimplemented\n"); } else { switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda.l %d\nrep #$20\n", fc); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; case 2: pr("lda.l %d\nsta.b tcc__r%d\n", fc, r); break; case 4: pr("lda.l %d\nsta.b tcc__r%d\nlda.l %d + 2\nsta.b tcc__r%dh\n", fc, r, fc, r); break; default: error("ICE 1"); } } } return; } else if(v < VT_CONST) { // deref pointer in register base = v; fc = sign = 0; v = VT_LOCAL; } if(v == VT_LOCAL) { if(is_float(ft)) { if(base == -1) { pr("; fld%d [sp,%d],tcc__f%d\n", length, fc, r - TREG_F0); if(length != 4) error("ICE 2f"); fc = adjust_stack(fc, args_size + 2); pr("lda %d + __%s_locals + 1,s\nsta.b tcc__f%d\nlda %d + __%s_locals + 1,s\nsta.b tcc__f%dh\n", fc+args_size, current_fn, r - TREG_F0, fc+args_size+2, current_fn, r - TREG_F0); fc = restore_stack(fc); } else { pr("; fld%d [tcc__r%d,%d],tcc__f%d\n", length, base, fc, r - TREG_F0); if(length != 4) error("ICE 3f"); pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__f%d\niny\niny\nlda.b [tcc__r%d], y\nsta.b tcc__f%dh\n", fc, base, r - TREG_F0, base, r - TREG_F0); } } else { if(base == -1) { // value of local at fc pr("; ld%d [sp,%d],tcc__r%d\n",length,fc,r); //if(length == 2 && fc == -88 && r == 0) asm("int $3"); fc = adjust_stack(fc, args_size + 2); switch(length) { case 1: pr("lda.w #0\nsep #$20\nlda %d + __%s_locals + 1,s\nrep #$20\n", fc+args_size, current_fn); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nlda %d + __%s_locals + 1,s\nsta.b tcc__r%d\n", r, fc+args_size, current_fn, r); break; case 2: pr("lda %d + __%s_locals + 1,s\nsta.b tcc__r%d\n", fc+args_size, current_fn, r); break; case 4: pr("lda %d + __%s_locals + 1,s\nsta.b tcc__r%d\nlda %d + __%s_locals + 1,s\nsta.b tcc__r%dh\n", fc+args_size, current_fn, r, fc+args_size + 2, current_fn, r); break; default: error("ICE 2"); break; } fc = restore_stack(fc); } else { // value of array member r[fc] pr("; ld%d [tcc__r%d,%d],tcc__r%d\n",length, base, fc, r); switch(length) { case 1: pr("lda.w #0\n"); if(!fc) pr("sep #$20\nlda.b [tcc__r%d]\nrep #$20\n", base); else pr("ldy #%d\nsep #$20\nlda.b [tcc__r%d],y\nrep #$20\n", fc, base); if(!(ft & VT_UNSIGNED)) pr("xba\nxba\nbpl +\nora.w #$ff00\n+\n"); pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\n", r, fc, base, r); break; case 2: if(!fc) pr("lda.b [tcc__r%d]\nsta.b tcc__r%d\n", base, r); else pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\n", fc, base, r); break; case 4: pr("ldy #%d\nlda.b [tcc__r%d],y\nsta.b tcc__r%d\niny\niny\nlda.b [tcc__r%d],y\nsta.b tcc__r%dh\n", fc, base, r, base, r); break; default: error("ICE 3"); break; } } } return; } } else { // VT_LVAL if(v == VT_CONST) { if(fr & VT_SYM) { // symbolic constant //greloc(cur_text_section, sv->sym, ind, R_DATA_32); char* sy = get_sym_str(sv->sym); pr("; ld%d #%s + %d, tcc__r%d (type 0x%x)\n", length,sy, fc, r, ft); if(length != PTR_SIZE) pr("; FISHY! length <> PTR_SIZE! (may be an array)\n"); pr("lda.w #:%s\nsta.b tcc__r%dh\nlda.w #%s + %d\nsta.b tcc__r%d\n", sy, r, sy, fc, r); } else { // numeric constant pr("; ld%d #%d,tcc__r%d\n",length,sv->c.ul,r); if((ft & VT_BTYPE) == VT_BOOL) { sv->c.ul = sv->c.ul? 1: 0; } switch(length) { case 1: if (ft & VT_UNSIGNED) { pr("lda.w #%d\n", sv->c.ul & 0xff); } else { pr("lda.w #%d\n", ((short)((sv->c.ul & 0xff) << 8)) >> 8); } pr("sta.b tcc__r%d\n", r); break; //case 2: pr("stz.b tcc__r%dh\nlda.w #%d\nsta.b tcc__r%d\n", r, sv->c.ul & 0xffff, r); break; case 2: pr("lda.w #%d\nsta.b tcc__r%d\n", sv->c.ul & 0xffff, r); break; case 4: pr("lda.w #%d\nsta.b tcc__r%d\nlda.w #%d\nsta.b tcc__r%dh\n", sv->c.ul & 0xffff, r, sv->c.ul >> 16, r); break; default: error("ICE 4"); } } return; } else if(v == VT_LOCAL) { if(fr & VT_SYM) { error("symbol"); char* sy = get_sym_str(sv->sym); pr("; LOCAL ld%d #%s, tcc__r%d (type 0x%x)\n", length,sy, r, ft); } else { // local pointer pr("; ld%d #(sp) + %d,tcc__r%d (fr 0x%x ft 0x%x fc 0x%x)\n",length,sv->c.ul,r,fr,ft,fc); // pointer; have to ensure the upper word is correct (page 0) pr("stz.b tcc__r%dh\ntsa\nclc\nadc #(%d + __%s_locals + 1)\nsta.b tcc__r%d\n", r, sv->c.ul + args_size, current_fn, r); } return; } else if(v == VT_CMP) { error("cmp"); return; } else if(v == VT_JMP || v == VT_JMPI) { t = v & 1; // inverted or not pr("; jmpr(i) v 0x%x r 0x%x fc 0x%x\n",v,r,fc); pr("lda #%d\nbra +\n", t); gsym(fc); //pr("lda #%d\n+ stz tcc__r%dh\nsta tcc__r%d\n", t^1, r,r); pr("lda #%d\n+\nsta.b tcc__r%d\n", t^1, r); // stz rXh seems to be unnecessary (we only look at the lower word) return; } else if(v < VT_CONST) { // register value if(is_float(ft)) { //error("float 1"); v -= TREG_F0; r -= TREG_F0; pr("; fmov tcc__f%d, tcc__f%d\n", v, r); pr("lda.b tcc__f%d\nsta.b tcc__f%d\nlda.b tcc__f%dh\nsta.b tcc__f%dh\n", v, r, v, r); } else { pr("; mov tcc__r%d, tcc__r%d\n",v,r); pr("lda.b tcc__r%d\nsta.b tcc__r%d\nlda.b tcc__r%dh\nsta.b tcc__r%dh\n", v, r, v, r); } return; } }
// Load 'r' from value 'sv' void load(int r, SValue *sv) { int v, t, ft, fc, fr, a; SValue v1; fr = sv->r; ft = sv->type.t; fc = sv->c.ul; regs_used |= 1 << r; v = fr & VT_VALMASK; if (fr & VT_LVAL) { if (v == VT_LLOCAL) { v1.type.t = VT_INT; v1.r = VT_LOCAL | VT_LVAL; v1.c.ul = fc; load(r, &v1); fr = r; } if ((ft & VT_BTYPE) == VT_FLOAT) { o(0xd9); // flds r = 0; } else if ((ft & VT_BTYPE) == VT_DOUBLE) { o(0xdd); // fldl r = 0; } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { o(0xdb); // fldt r = 5; } else if ((ft & VT_TYPE) == VT_BYTE) { o(0xbe0f); // movsbl } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { o(0xb60f); // movzbl } else if ((ft & VT_TYPE) == VT_SHORT) { o(0xbf0f); // movswl } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { o(0xb70f); // movzwl } else { o(0x8b); // movl } gen_modrm(r, fr, sv->sym, fc); } else { if (v == VT_CONST) { if (fc == 0 && (fr & VT_SYM) == 0) { o(0x33); // xor r, r o(0xc0 + r + r * 8); } else { o(0xb8 + r); // mov $xx, r gen_addr32(fr, sv->sym, fc); } } else if (v == VT_LOCAL) { o(0x8d); // lea xxx(%ebp), r gen_modrm(r, VT_LOCAL, sv->sym, fc); } else if (v == VT_CMP) { o(0x0f); // setxx br o(fc); o(0xc0 + r); o(0x0f); // movzx r,br o(0xb6); o(0xc0 + r + r * 8); } else if (v == VT_JMP || v == VT_JMPI) { t = v & 1; oad(0xb8 + r, t); // mov $1, r a = gjmp(0, 0); // jmp after gsym(fc); oad(0xb8 + r, t ^ 1); // mov $0, r gsym(a); } else if (v != r) { o(0x89); o(0xc0 + r + v * 8); // mov v, r } } }
void gencall(int y) { gentext(); commit(); cgcall(gsym(Names[y])); load(); }
int cgload(void) { char *op = "mov"; int n = Q_val; char *s = gsym(Q_name); int q; switch (Q_type) { case addr_auto: ngen("%s\tcx,[bp%+d]", "lea", n); break; case addr_static: lgen("%s\tcx,offset %c%d", op, n); break; case addr_globl: sgen("%s\tcx,offset %s", op, s); break; case addr_label: lgen("%s\tcx,offset %c%d", op, n); break; case literal: ngen("%s\tcx,%d", op, n); break; case auto_byte: cgclear2(); ngen("%s\tcl,[bp%+d]", op, n); break; case auto_word: ngen("%s\tcx,[bp%+d]", op, n); break; case static_byte: cgclear2(); lgen("%s\tcl,%c%d", op, n); break; case static_word: lgen("%s\tcx,%c%d", op, n); break; case globl_byte: cgclear2(); sgen("%s\tcl,%s", op, s); break; case globl_word: sgen("%s\tcx,%s", op, s); break; case empty: cgpop2(); break; default: fatal("internal: bad type in cgsynth()"); } q = Q_type; Q_type = empty; return empty == q; }
int cgload(void) { char *op = "movl"; char *opb = "movb"; int n = Q_val; char *s = gsym(Q_name); int q; switch (Q_type) { case addr_auto: ngen("%s\t%d(%%ebp),%%ecx", "leal", n); break; case addr_static: lgen("%s\t$%c%d,%%ecx", op, n); break; case addr_globl: sgen("%s\t$%s,%%ecx", op, s); break; case addr_label: lgen("%s\t$%c%d,%%ecx", op, n); break; case literal: ngen("%s\t$%d,%%ecx", op, n); break; case auto_byte: cgclear2(); ngen("%s\t%d(%%ebp),%%cl", opb, n); break; case auto_word: ngen("%s\t%d(%%ebp),%%ecx", op, n); break; case static_byte: cgclear2(); lgen("%s\t%c%d,%%cl", opb, n); break; case static_word: lgen("%s\t%c%d,%%ecx", op, n); break; case globl_byte: cgclear2(); sgen("%s\t%s,%%cl", opb, s); break; case globl_word: sgen("%s\t%s,%%ecx", op, s); break; case empty: cgpop2(); break; default: fatal("internal: bad type in cgsynth()"); } q = Q_type; Q_type = empty; return empty == q; }
void geninc(int *lv, int inc, int pre) { int y, b; gentext(); y = lv[LVSYM]; if (needscale(lv[LVPRIM])) { genincptr(lv, inc, pre); return; } b = PCHAR == lv[LVPRIM]; commit(); if (!y && !pre) cgldinc(); if (!pre) { rvalue(lv); commit(); } if (!y) { if (pre) { if (inc) b ? cginc1ib() : cginc1iw(); else b ? cgdec1ib() : cgdec1iw(); } else { if (inc) b ? cginc2ib() : cginc2iw(); else b ? cgdec2ib() : cgdec2iw(); } } else if (CAUTO == symbols[y].stcl) { if (inc) b ? cginclb(symbols[y].value) : cginclw(symbols[y].value); else b ? cgdeclb(symbols[y].value) : cgdeclw(symbols[y].value); } else if (CLSTATC == symbols[y].stcl) { if (inc) b ? cgincsb(symbols[y].value) : cgincsw(symbols[y].value); else b ? cgdecsb(symbols[y].value) : cgdecsw(symbols[y].value); } else { if (inc) b ? cgincgb(gsym(symbols[y].name)) : cgincgw(gsym(symbols[y].name)); else b ? cgdecgb(gsym(symbols[y].name)) : cgdecgw(gsym(symbols[y].name)); } if (pre) rvalue(lv); }
void cgsynth(char *op) { int n = Q_val; char *s = gsym(Q_name); switch (Q_type) { case addr_auto: ngen("%s\t%d(%%ebp),%%ecx", "leal", n); sgen("%s\t%s,%%eax", op, "%ecx"); break; case addr_static: lgen("%s\t$%c%d,%%eax", op, n); break; case addr_globl: sgen("%s\t$%s,%%eax", op, s); break; case addr_label: lgen("%s\t$%c%d,%%eax", op, n); break; case literal: ngen("%s\t$%d,%%eax", op, n); break; case auto_word: ngen("%s\t%d(%%ebp),%%eax", op, n); break; case static_word: lgen("%s\t%c%d,%%eax", op, n); break; case globl_word: sgen("%s\t%s,%%eax", op, s); break; case auto_byte: case static_byte: case globl_byte: cgload(); ngen("%s\t%%ecx,%%eax", op, 0); break; case empty: cgpop2(); sgen("%s\t%s,%%eax", op, "%ecx"); break; default: fatal("internal: bad type in cgsynth()"); } Q_type = empty; }
void genstore(int op, int *lv, int *lv2) { int swapped = 1; if (NULL == lv) return; gentext(); if (ASSIGN != op) { if (lv[LVSYM]) { rvalue(lv); swapped = 0; } genasop(op, lv[LVPRIM], lv2[LVPRIM], swapped); } commit(); if (!lv[LVSYM]) { cgpopptr(); if (PCHAR == lv[LVPRIM]) cgstorib(); else cgstoriw(); } else if (CAUTO == symbols[lv[LVSYM]].stcl) { if (PCHAR == lv[LVPRIM]) cgstorlb(symbols[lv[LVSYM]].value); else cgstorlw(symbols[lv[LVSYM]].value); } else if (CLSTATC == symbols[lv[LVSYM]].stcl) { if (PCHAR == lv[LVPRIM]) cgstorsb(symbols[lv[LVSYM]].value); else cgstorsw(symbols[lv[LVSYM]].value); } else { if (PCHAR == lv[LVPRIM]) cgstorgb(gsym(symbols[lv[LVSYM]].name)); else cgstorgw(gsym(symbols[lv[LVSYM]].name)); } }
/* generate a test. set 'inv' to invert test. Stack entry is popped */ int gtst(int inv, int t) { int v, *p, c; v = vtop->r & VT_VALMASK; if (v == VT_CMP) { c = vtop->c.i ^ inv; switch(c) { case TOK_EQ: c = IL_OP_BEQ; break; case TOK_NE: c = IL_OP_BNE_UN; break; case TOK_LT: c = IL_OP_BLT; break; case TOK_LE: c = IL_OP_BLE; break; case TOK_GT: c = IL_OP_BGT; break; case TOK_GE: c = IL_OP_BGE; break; case TOK_ULT: c = IL_OP_BLT_UN; break; case TOK_ULE: c = IL_OP_BLE_UN; break; case TOK_UGT: c = IL_OP_BGT_UN; break; case TOK_UGE: c = IL_OP_BGE_UN; break; } t = out_opj(c, t); } else if (v == VT_JMP || v == VT_JMPI) { /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ p = &vtop->c.i; while (*p != 0) p = (int *)*p; *p = t; t = vtop->c.i; } else { t = gjmp(t); gsym(vtop->c.i); } } else { if (is_float(vtop->t)) { vpushi(0); gen_op(TOK_NE); } if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) { /* constant jmp optimization */ if ((vtop->c.i != 0) != inv) t = gjmp(t); } else { v = gv(RC_INT); t = out_opj(IL_OP_BRTRUE - inv, t); } } vtop--; return t; }
static void genincptr(int *lv, int inc, int pre) { int y; int size = objsize(deref(lv[LVPRIM]), TVARIABLE, 1); gentext(); y = lv[LVSYM]; commit(); if (!y && !pre) cgldinc(); if (!pre) { rvalue(lv); commit(); } if (!y) { if (pre) { if (inc) cginc1pi(size); else cgdec1pi(size); } else { if (inc) cginc2pi(size); else cgdec2pi(size); } } else if (CAUTO == symbols[y].stcl) { if (inc) cgincpl(symbols[y].value, size); else cgdecpl(symbols[y].value, size); } else if (CLSTATC == symbols[y].stcl) { if (inc) cgincps(symbols[y].value, size); else cgdecps(symbols[y].value, size); } else { if (inc) cgincpg(gsym(symbols[y].name), size); else cgdecpg(gsym(symbols[y].name), size); } if (pre) rvalue(lv); }
static A syncErrorResult(const C *sym_, const C *str_) { return gvi(Et,3,gsym("error"),gsym(sym_),gsv(0,str_)); }