fixed floating poing compare - use LVAL type - optimized bound checking

tcc-xref
bellard 2002-07-13 15:55:16 +00:00
parent 30766d3cd1
commit 264dbcfed2
1 changed files with 57 additions and 40 deletions

View File

@ -207,16 +207,17 @@ void load(int r, SValue *sv)
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) { } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
o(0xdb); /* fldt */ o(0xdb); /* fldt */
r = 5; r = 5;
} else if ((ft & VT_TYPE) == VT_BYTE) } else if ((ft & VT_TYPE) == VT_BYTE) {
o(0xbe0f); /* movsbl */ o(0xbe0f); /* movsbl */
else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
o(0xb60f); /* movzbl */ o(0xb60f); /* movzbl */
else if ((ft & VT_TYPE) == VT_SHORT) } else if ((ft & VT_TYPE) == VT_SHORT) {
o(0xbf0f); /* movswl */ o(0xbf0f); /* movswl */
else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
o(0xb70f); /* movzwl */ o(0xb70f); /* movzwl */
else } else {
o(0x8b); /* movl */ o(0x8b); /* movl */
}
gen_modrm(r, fr, fc); gen_modrm(r, fr, fc);
} else { } else {
if (v == VT_CONST) { if (v == VT_CONST) {
@ -303,7 +304,7 @@ void gfunc_param(GFuncContext *c)
r = get_reg(RC_INT); r = get_reg(RC_INT);
o(0x89); /* mov %esp, r */ o(0x89); /* mov %esp, r */
o(0xe0 + r); o(0xe0 + r);
vset(VT_INT, r, 0); vset(vtop->t, r | VT_LVAL, 0);
vswap(); vswap();
vstore(); vstore();
c->args_size += size; c->args_size += size;
@ -655,11 +656,22 @@ void gen_opf(int op)
gv(RC_FLOAT); gv(RC_FLOAT);
vswap(); vswap();
} }
swapped = 0;
/* swap the stack if needed so that t1 is the register and t2 is
the memory reference */
if (vtop[-1].r & VT_LVAL) {
vswap();
swapped = 1;
}
if (op >= TOK_ULT && op <= TOK_GT) { if (op >= TOK_ULT && op <= TOK_GT) {
/* load on stack second operand */ /* load on stack second operand */
load(REG_ST0, vtop); load(REG_ST0, vtop);
save_reg(REG_EAX); /* eax is used by FP comparison code */ save_reg(REG_EAX); /* eax is used by FP comparison code */
if (op == TOK_GE || op == TOK_GT) if (op == TOK_GE || op == TOK_GT)
swapped = !swapped;
else if (op == TOK_EQ || op == TOK_NE)
swapped = 0;
if (swapped)
o(0xc9d9); /* fxch %st(1) */ o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */ o(0xe9da); /* fucompp */
o(0xe0df); /* fnstsw %ax */ o(0xe0df); /* fnstsw %ax */
@ -681,13 +693,6 @@ void gen_opf(int op)
vtop->r = VT_CMP; vtop->r = VT_CMP;
vtop->c.i = op; vtop->c.i = op;
} else { } else {
swapped = 0;
/* swap the stack if needed so that t1 is the register and t2 is
the memory reference */
if (vtop[-1].r & VT_LVAL) {
vswap();
swapped = 1;
}
/* no memory reference possible for long double operations */ /* no memory reference possible for long double operations */
if ((vtop->t & VT_BTYPE) == VT_LDOUBLE) { if ((vtop->t & VT_BTYPE) == VT_LDOUBLE) {
load(REG_ST0, vtop); load(REG_ST0, vtop);
@ -821,45 +826,57 @@ void gen_cvt_ftof(int t)
/* bound check support functions */ /* bound check support functions */
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* generate first part of bounded pointer addition */
void gen_bounded_ptr_add1(void) /* generate a bounded pointer addition */
void gen_bounded_ptr_add(void)
{ {
int addr;
/* prepare fast i386 function call (args in eax and edx) */ /* prepare fast i386 function call (args in eax and edx) */
gv2(RC_EAX, RC_EDX); gv2(RC_EAX, RC_EDX);
/* save all temporary registers */ /* save all temporary registers */
vtop--; vtop -= 2;
vtop->r = VT_CONST; save_regs(0);
save_regs(0); /* do a fast function call */
addr = ind;
oad(0xe8, (int)__bound_ptr_add - ind - 5);
/* returned pointer is in eax */
vtop++;
vtop->r = REG_EAX | VT_BOUNDED;
vtop->c.ul = addr; /* address of bounding function call point */
} }
/* if deref is true, then also test dereferencing */ /* patch pointer addition in vtop so that pointer dereferencing is
void gen_bounded_ptr_add2(int deref) also tested */
void gen_bounded_ptr_deref(void)
{ {
void *func; void *func;
int size, align; int size, align, addr;
if (deref) { size = 0;
/* XXX: put that code in generic part of tcc */
if (!is_float(vtop->t)) {
if (vtop->r & VT_LVAL_BYTE)
size = 1;
else if (vtop->r & VT_LVAL_SHORT)
size = 2;
}
if (!size)
size = type_size(vtop->t, &align); size = type_size(vtop->t, &align);
switch(size) { switch(size) {
case 1: func = __bound_ptr_indir1; break; case 1: func = __bound_ptr_indir1; break;
case 2: func = __bound_ptr_indir2; break; case 2: func = __bound_ptr_indir2; break;
case 4: func = __bound_ptr_indir4; break; case 4: func = __bound_ptr_indir4; break;
case 8: func = __bound_ptr_indir8; break; case 8: func = __bound_ptr_indir8; break;
case 12: func = __bound_ptr_indir12; break; case 12: func = __bound_ptr_indir12; break;
case 16: func = __bound_ptr_indir16; break; case 16: func = __bound_ptr_indir16; break;
default: default:
error("unhandled size when derefencing bounded pointer"); error("unhandled size when derefencing bounded pointer");
func = NULL; func = NULL;
break; break;
}
} else {
func = __bound_ptr_add;
} }
/* do a fast function call */ addr = vtop->c.ul;
oad(0xe8, (int)func - ind - 5); *(int *)(addr + 1) = (int)func - addr - 5;
/* return pointer is there */
vtop->r = REG_EAX;
} }
#endif #endif