aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2013-08-28 22:55:05 +0200
committergrischka <grischka>2013-08-28 22:55:05 +0200
commit73faaea227a53e365dd75f1dba7a5071c7b5e541 (patch)
treeb7ff7cfd171d27d24ec4ceb4df8cf98f3341fd82
parent69c2e7f96c95ba088657ce8bb9754c12c3e89397 (diff)
downloadtinycc-73faaea227a53e365dd75f1dba7a5071c7b5e541.tar.gz
tinycc-73faaea227a53e365dd75f1dba7a5071c7b5e541.tar.bz2
i386-gen: preserve fp control word in gen_cvt_ftoi
- Use runtime function for conversion - Also initialize fp with tcc -run on windows This fixes a bug where double x = 1.0; double y = 1.0000000000000001; double z = x < y ? 0 : sqrt (x*x - y*y); caused a bad sqrt because rounding precision for the x < y comparison was different to the one used within the sqrt function. This also fixes a bug where printf("%d, %d", (int)pow(10, 2), (int)pow(10, 2)); would print 100, 99 Unrelated: win32: document relative include & lib lookup win32: normalize_slashes: do not mirror silly gcc behavior This reverts part of commit 8a81f9e1036637e21a47e14fb56bf64133546890 winapi: add missing WINAPI decl. for some functions
-rw-r--r--i386-gen.c91
-rw-r--r--lib/libtcc1.c23
-rw-r--r--libtcc.c15
-rw-r--r--tcc.h1
-rw-r--r--tccpe.c22
-rw-r--r--tccrun.c2
-rw-r--r--tcctok.h4
-rw-r--r--win32/include/winapi/winbase.h12
-rw-r--r--win32/lib/crt1.c6
-rw-r--r--win32/lib/wincrt1.c2
-rw-r--r--win32/tcc-win32.txt6
11 files changed, 77 insertions, 107 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 844a482..0a6d4d3 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -338,6 +338,15 @@ static void gadd_sp(int val)
}
}
+static void gen_static_call(int v)
+{
+ Sym *sym;
+
+ sym = external_global_sym(v, &func_old_type, 0);
+ oad(0xe8, -4);
+ greloc(cur_text_section, sym, ind-4, R_386_PC32);
+}
+
/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
@@ -570,6 +579,12 @@ ST_FUNC void gfunc_prolog(CType *func_type)
func_bound_offset = lbounds_section->data_offset;
}
#endif
+
+#ifndef TCC_TARGET_PE
+ if (0 == strcmp(funcname, "main"))
+ gen_static_call(TOK___tcc_fpinit);
+#endif
+
}
/* generate function epilog */
@@ -582,7 +597,7 @@ ST_FUNC void gfunc_epilog(void)
&& func_bound_offset != lbounds_section->data_offset) {
int saved_ind;
int *bounds_ptr;
- Sym *sym, *sym_data;
+ Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
*bounds_ptr = 0;
@@ -594,20 +609,16 @@ ST_FUNC void gfunc_epilog(void)
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
- sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
- greloc(cur_text_section, sym,
- ind + 1, R_386_PC32);
- oad(0xe8, -4);
+ gen_static_call(TOK___bound_local_new);
+
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
- sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
- greloc(cur_text_section, sym,
- ind + 1, R_386_PC32);
- oad(0xe8, -4);
+ gen_static_call(TOK___bound_local_delete);
+
o(0x585a); /* restore returned value, if any */
}
#endif
@@ -626,10 +637,8 @@ ST_FUNC void gfunc_epilog(void)
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
#ifdef TCC_TARGET_PE
if (v >= 4096) {
- Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
oad(0xb8, v); /* mov stacksize, %eax */
- oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
- greloc(cur_text_section, sym, ind-4, R_386_PC32);
+ gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
} else
#endif
{
@@ -992,52 +1001,13 @@ ST_FUNC void gen_cvt_itof(int t)
/* XXX: handle long long case */
ST_FUNC void gen_cvt_ftoi(int t)
{
- int r, r2, size;
- Sym *sym;
- CType ushort_type;
-
- ushort_type.t = VT_SHORT | VT_UNSIGNED;
- ushort_type.ref = 0;
-
gv(RC_FLOAT);
- if (t != VT_INT)
- size = 8;
- else
- size = 4;
-
- o(0x2dd9); /* ldcw xxx */
- sym = external_global_sym(TOK___tcc_int_fpu_control,
- &ushort_type, VT_LVAL);
- greloc(cur_text_section, sym,
- ind, R_386_32);
- gen_le32(0);
-
- oad(0xec81, size); /* sub $xxx, %esp */
- if (size == 4)
- o(0x1cdb); /* fistpl */
- else
- o(0x3cdf); /* fistpll */
- o(0x24);
- o(0x2dd9); /* ldcw xxx */
- sym = external_global_sym(TOK___tcc_fpu_control,
- &ushort_type, VT_LVAL);
- greloc(cur_text_section, sym,
- ind, R_386_32);
- gen_le32(0);
-
- r = get_reg(RC_INT);
- o(0x58 + r); /* pop r */
- if (size == 8) {
- if (t == VT_LLONG) {
- vtop->r = r; /* mark reg as used */
- r2 = get_reg(RC_INT);
- o(0x58 + r2); /* pop r2 */
- vtop->r2 = r2;
- } else {
- o(0x04c483); /* add $4, %esp */
- }
- }
- vtop->r = r;
+ save_reg(TREG_EAX);
+ save_reg(TREG_EDX);
+ gen_static_call(TOK___tcc_cvt_ftol);
+ vtop->r = TREG_EAX; /* mark reg as used */
+ if (t == VT_LLONG)
+ vtop->r2 = TREG_EDX;
}
/* convert from one floating point type to another */
@@ -1060,18 +1030,13 @@ ST_FUNC void ggoto(void)
/* generate a bounded pointer addition */
ST_FUNC void gen_bounded_ptr_add(void)
{
- Sym *sym;
-
/* prepare fast i386 function call (args in eax and edx) */
gv2(RC_EAX, RC_EDX);
/* save all temporary registers */
vtop -= 2;
save_regs(0);
/* do a fast function call */
- sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
- greloc(cur_text_section, sym,
- ind + 1, R_386_PC32);
- oad(0xe8, -4);
+ gen_static_call(TOK___bound_ptr_add);
/* returned pointer is in eax */
vtop++;
vtop->r = TREG_EAX | VT_BOUNDED;
diff --git a/lib/libtcc1.c b/lib/libtcc1.c
index 53dbec4..a94a82d 100644
--- a/lib/libtcc1.c
+++ b/lib/libtcc1.c
@@ -478,13 +478,24 @@ long long __ashldi3(long long a, int b)
#endif
}
-#if defined(__i386__)
-/* FPU control word for rounding to nearest mode */
-unsigned short __tcc_fpu_control = 0x137f;
-/* FPU control word for round to zero mode for int conversion */
-unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
+#ifndef _WIN32
+void __tcc_fpinit(void)
+{
+ unsigned c = 0x137F;
+ __asm__ __volatile__ ("fldcw %0" : "=m" (c));
+}
#endif
-
+long long __tcc_cvt_ftol(long double x)
+{
+ unsigned c0, c1;
+ long long ret;
+ __asm__ __volatile__ ("fnstcw %0" : "=m" (c0));
+ c1 = c0 | 0x0C00;
+ __asm__ __volatile__ ("fldcw %0" : "=m" (c1));
+ __asm__ __volatile__ ("fistpll %0" : "=m" (ret));
+ __asm__ __volatile__ ("fldcw %0" : "=m" (c0));
+ return ret;
+}
#endif /* !__x86_64__ */
/* XXX: fix tcc's code generator to do this instead */
diff --git a/libtcc.c b/libtcc.c
index b10a2a7..3b018ae 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -78,21 +78,13 @@ ST_FUNC void asm_global_instr(void)
#endif
/********************************************************/
-
#ifdef _WIN32
-// GCC appears to use '/' for relative paths and '\\' for absolute paths on Windows
static char *normalize_slashes(char *path)
{
char *p;
- if (path[1] == ':') {
- for (p = path+2; *p; ++p)
- if (*p == '/')
- *p = '\\';
- } else {
- for (p = path; *p; ++p)
- if (*p == '\\')
- *p = '/';
- }
+ for (p = path; *p; ++p)
+ if (*p == '\\')
+ *p = '/';
return path;
}
@@ -1036,6 +1028,7 @@ LIBTCCAPI TCCState *tcc_new(void)
#ifdef TCC_TARGET_I386
s->seg_size = 32;
#endif
+ s->runtime_main = "main";
return s;
}
diff --git a/tcc.h b/tcc.h
index 859d4fd..c988e4f 100644
--- a/tcc.h
+++ b/tcc.h
@@ -665,6 +665,7 @@ struct TCCState {
#endif
#ifdef TCC_IS_NATIVE
+ const char *runtime_main;
/* for tcc_relocate */
void *runtime_mem;
# ifdef HAVE_SELINUX
diff --git a/tccpe.c b/tccpe.c
index 72c1572..05fed09 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -1726,7 +1726,6 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
const char *start_symbol;
- ADDR3264 addr = 0;
int pe_type = 0;
if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
@@ -1742,16 +1741,13 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
start_symbol =
TCC_OUTPUT_MEMORY == s1->output_type
- ? PE_GUI == pe_type ? "__runwinmain" : "_main"
+ ? PE_GUI == pe_type ? "__runwinmain" : "__runmain"
: PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
: PE_GUI == pe_type ? "__winstart" : "__start"
;
- if (!s1->leading_underscore || strchr(start_symbol, '@')) {
+ if (!s1->leading_underscore || strchr(start_symbol, '@'))
++start_symbol;
- if (start_symbol[0] != '_')
- start_symbol = NULL;
- }
/* grab the startup code from libtcc1 */
if (start_symbol)
@@ -1776,21 +1772,13 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
}
}
- if (TCC_OUTPUT_MEMORY == s1->output_type)
+ if (TCC_OUTPUT_MEMORY == s1->output_type) {
pe_type = PE_RUN;
-
- if (start_symbol) {
- addr = get_elf_sym_addr(s1, start_symbol, 1);
- if (PE_RUN == pe_type && addr)
- /* for -run GUI's, put '_runwinmain' instead of 'main' */
- add_elf_sym(symtab_section,
- addr, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
- text_section->sh_num, "main");
+ s1->runtime_main = start_symbol;
}
pe->type = pe_type;
- pe->start_addr = addr;
+ pe->start_addr = (DWORD)tcc_get_symbol_err(s1, start_symbol);
}
ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
diff --git a/tccrun.c b/tccrun.c
index d858ae6..b07ab0f 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -97,7 +97,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1;
- prog_main = tcc_get_symbol_err(s1, "main");
+ prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_debug) {
diff --git a/tcctok.h b/tcctok.h
index fde13dd..9b47a60 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -194,8 +194,8 @@
DEF(TOK__remu, "_remu")
#endif
#ifdef TCC_TARGET_I386
- DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
- DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
+ DEF(TOK___tcc_fpinit, "__tcc_fpinit")
+ DEF(TOK___tcc_cvt_ftol, "__tcc_cvt_ftol")
#endif
#ifdef TCC_ARM_EABI
DEF(TOK___ashrdi3, "__aeabi_lasr")
diff --git a/win32/include/winapi/winbase.h b/win32/include/winapi/winbase.h
index a5d9b17..4a38006 100644
--- a/win32/include/winapi/winbase.h
+++ b/win32/include/winapi/winbase.h
@@ -968,15 +968,15 @@ extern "C" {
LONG64 InterlockedExchangeAdd64(LONG64 volatile *Addend,LONG64 Value);
LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination,LONG64 ExChange,LONG64 Comperand);
#else
- LONG InterlockedIncrement(LONG volatile *lpAddend);
- LONG InterlockedDecrement(LONG volatile *lpAddend);
- LONG InterlockedExchange(LONG volatile *Target,LONG Value);
+ LONG WINAPI InterlockedIncrement(LONG volatile *lpAddend);
+ LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend);
+ LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value);
#define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value))
- LONG InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
- LONG InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
- LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
+ LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
+ LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
+ LONGLONG WINAPI InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
__CRT_INLINE LONGLONG InterlockedAnd64 (LONGLONG volatile *Destination,LONGLONG Value) {
LONGLONG Old;
diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c
index 3e1d17f..cde3910 100644
--- a/win32/lib/crt1.c
+++ b/win32/lib/crt1.c
@@ -31,4 +31,10 @@ int _start(void)
exit(ret);
}
+int _runmain(int argc, char **argv)
+{
+ _controlfp(0x10000, 0x30000);
+ return main(argc, argv, NULL);
+}
+
// =============================================
diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c
index 77e74b8..663fd33 100644
--- a/win32/lib/wincrt1.c
+++ b/win32/lib/wincrt1.c
@@ -59,6 +59,6 @@ int _runwinmain(int argc, char **argv)
szCmd = "";
else if (szCmd > p && szCmd[-1] == '\"')
--szCmd;
+ _controlfp(0x10000, 0x30000);
return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT);
}
-
diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt
index dc06b8f..1cb35c5 100644
--- a/win32/tcc-win32.txt
+++ b/win32/tcc-win32.txt
@@ -18,6 +18,12 @@
system PATH.
+ Include and library search paths
+ --------------------------------
+ On windows, the standard "include" and "lib" directories are searched
+ relatively from the location of the executables (tcc.exe, libtcc.dll).
+
+
Examples:
---------
Open a console window (DOS box) and 'cd' to the examples directory.