From 25618c0430b58d1d5522091c83c89cdde83135f1 Mon Sep 17 00:00:00 2001 From: bellard Date: Thu, 13 Dec 2001 22:28:53 +0000 Subject: float parsing + long double --- i386-gen.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'i386-gen.c') diff --git a/i386-gen.c b/i386-gen.c index ef06fcb..40f1c2d 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -1,6 +1,22 @@ -/******************************************************/ -/* X86 code generator */ - +/* + * X86 code generator for TCC + * + * Copyright (c) 2001 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ /* number of available registers */ #define NB_REGS 4 @@ -38,6 +54,13 @@ int reg_classes[NB_REGS] = { are directly pushed on stack. */ //#define FUNC_STRUCT_PARAM_AS_PTR +/* pointer size, in bytes */ +#define PTR_SIZE 4 + +/* long double size and alignment, in bytes */ +#define LDOUBLE_SIZE 12 +#define LDOUBLE_ALIGN 4 + /* function call context */ typedef struct GFuncContext { int args_size; @@ -161,6 +184,9 @@ void load(int r, int ft, int fc) } 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)) @@ -214,12 +240,16 @@ void store(r, ft, fc) fr = ft & VT_VALMASK; bt = ft & VT_BTYPE; /* XXX: incorrect if reg to reg */ + /* XXX: should not flush float stack */ if (bt == VT_FLOAT) { o(0xd9); /* fstps */ r = 3; } else if (bt == VT_DOUBLE) { o(0xdd); /* fstpl */ r = 3; + } else if (bt == VT_LDOUBLE) { + o(0xdb); /* fstpt */ + r = 7; } else { if (bt == VT_SHORT) o(0x66); @@ -269,17 +299,24 @@ void gfunc_param(GFuncContext *c) vc = fc; vstore(); c->args_size += size; - } else if ((vt & VT_BTYPE) == VT_DOUBLE || + } else if ((vt & VT_BTYPE) == VT_LDOUBLE || + (vt & VT_BTYPE) == VT_DOUBLE || (vt & VT_BTYPE) == VT_FLOAT) { gv(); /* only one float register */ if ((vt & VT_BTYPE) == VT_FLOAT) size = 4; - else + else if ((vt & VT_BTYPE) == VT_DOUBLE) size = 8; + else + size = 12; oad(0xec81, size); /* sub $xxx, %esp */ - o(0x245cd9 + size - 4); /* fstp[s|l] 0(%esp) */ + if (size == 12) + o(0x7cdb); + else + o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */ + g(0x24); g(0x00); - c->args_size += 8; + c->args_size += size; } else { /* simple type (currently always same size) */ /* XXX: implicit cast ? */ @@ -345,6 +382,7 @@ int gtst(int inv, int t) if ((vc != 0) != inv) t = gjmp(t); } else { + /* XXX: floats */ v = gv(); o(0x85); o(0xc0 + v * 9); @@ -499,7 +537,7 @@ void gen_opf(int op) o(0x05 + a); gen_addr32(fc, ft); } else if (r == VT_LOCAL) { - oad(0x85 + a, fc); + oad(0x85 + a, fc); } else { g(0x00 + a + r); } @@ -512,14 +550,14 @@ void gen_opf(int op) void gen_cvtf(int t) { if ((vt & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) { - /* unsigned int to float/double */ + /* unsigned int to float/double/long double */ o(0x6a); /* push $0 */ g(0x00); o(0x50 + (vt & VT_VALMASK)); /* push r */ o(0x242cdf); /* fildll (%esp) */ o(0x08c483); /* add $8, %esp */ } else { - /* int to float/double */ + /* int to float/double/long double */ o(0x50 + (vt & VT_VALMASK)); /* push r */ o(0x2404db); /* fildl (%esp) */ o(0x04c483); /* add $4, %esp */ -- cgit v1.3.1