/* 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; }
/* 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, 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 } } }
/* 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; }