aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* fix asmtest (somehow), update Makefilesgrischka2009-07-183-9/+14
|
* bcheck: restore malloc hooks when donegrischka2009-07-184-29/+39
|
* configure: support DESTDIR for RPM packagers etc.grischka2009-07-181-7/+8
| | | | Suggested by Shlomi Fish
* win32: guard va_list typedefgrischka2009-06-171-0/+3
|
* accept option -x <lang>grischka2009-06-171-0/+4
|
* win32: structure return GCC compatible (ret 4 with cdecl)grischka2009-06-171-0/+11
|
* error messages: print "error: ..."grischka2009-06-171-0/+2
|
* tcc_preprocess: add gcc-style include-depth flagsgrischka2009-06-171-7/+22
| | | | | | | | | # 1 "main.c" # 1 "include/stdio.h" 1 # 123 "include/stdio.h" 3 # 10 "main.c" 2 flags: 1: level++; 3: same-level 2: level--
* incompatible function ptr assignment: just warngrischka2009-06-171-3/+2
| | | | | void fn_1(int i) {} void (*fn_2)(char*) = fn_1;
* allow redefinition of func_old_type functionsgrischka2009-06-171-4/+7
| | | | | | | void *memcpy(void*, const void*, unsigned); This gave an error if memcpy() has been used before implicitely, e.g. for structure passing etc.
* trying to fix the bug of unclean FPU st(0)Soloist Deng2009-06-171-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Date: Mon, 8 Jun 2009 19:06:56 +0800 From: Soloist Deng <soloist.deng-gmail-com> Subject: [Tinycc-devel] trying to fix the bug of unclean FPU st(0) Hi all: I am using tcc-0.9.25, and the FPU bug brought a big trouble to me. I read the source and tried to fix it. Below is my solution. There are two places where program(`o(0xd9dd)') will generates `fstp %st(1)': vpop() in tccgen.c:689 and save_reg() in tccgen.c:210. We should first change both of them to `o(0xd8dd) // fstp %st(0)'. But these changes are not enough. Let's check the following code. void foo() { double var = 2.7; var++; } Using the changed tcc will generate following machine code: .text:08000000 public foo .text:08000000 foo proc near .text:08000000 .text:08000000 var_18 = qword ptr -18h .text:08000000 var_10 = qword ptr -10h .text:08000000 var_8 = qword ptr -8 .text:08000000 .text:08000000 push ebp .text:08000001 mov ebp, esp .text:08000003 sub esp, 18h .text:08000009 nop .text:0800000A fld L_0 .text:08000010 fst [ebp+var_8] .text:08000013 fstp st(0) .text:08000015 fld [ebp+var_8] .text:08000018 fst [ebp+var_10] .text:0800001B fstp st(0) .text:0800001D fst [ebp+var_18] .text:08000020 fstp st(0) .text:08000022 fld L_1 .text:08000028 fadd [ebp+var_10] .text:0800002B fst [ebp+var_8] .text:0800002E fstp st(0) .text:08000030 leave .text:08000031 retn .text:08000031 foo endp .text:08000031 .text:08000031 _text ends -------------------------------------------------- .data:08000040 ; Segment type: Pure data .data:08000040 ; Segment permissions: Read/Write .data:08000040 ; Segment alignment '32byte' can not be represented in assembly .data:08000040 _data segment page public 'DATA' use32 .data:08000040 assume cs:_data .data:08000040 ;org 8000040h .data:08000040 L_0 dq 400599999999999Ah .data:08000048 L_1 dq 3FF0000000000000h .data:08000048 _data ends Please notice the code snippet from 0800000A to 08000020 // double var = 2.7; load constant to st(0) .text:0800000A fld L_0 // double var = 2.7; store st(0) to `var' .text:08000010 fst [ebp+var_8] // double var = 2.7; poping st(0) will empty the floating registers stack .text:08000013 fstp st(0) After that ,tcc will call `void inc(int post, int c)" in tccgen.c:2150, and produce 08000015 to 0800001B through the calling chain (inc ->gv_dup) // load from `var' to st(0) .text:08000015 fld [ebp+var_8] // store st(0) to a temporary location .text:08000018 fst [ebp+var_10] // poping st(0) will empty the floating registers stack .text:0800001B fstp st(0) And the calling chain (gen_op('+')->gen_opif('+')->gen_opf('+')->gv(rc=2)->get_reg(rc=2)->save_reg(r=3)) will produce 0800001D to 08000020 . // store st(0) to a temporary location, but floating stack is empty! .text:0800001D fst [ebp+var_18] // poping st(0) will empty the floating registers stack .text:08000020 fstp st(0) The `0800001D fst [ebp+var_18]' will store st(0) to a memory location, but st(0) is empty. That will cause FPU invalid operation exception(#IE). Why does tcc do that? Please read `gv_dup' called by `inc' carefully. Notice these lines: (1): r = gv(rc); (2): r1 = get_reg(rc); (3): sv.r = r; sv.c.ul = 0; (4) load(r1, &sv); /* move r to r1 */ (5) vdup(); /* duplicates value */ (6) vtop->r = r1; (1) let the vtop occupy TREG_ST0, and `r' will be TREG_ST0. (2) try to get a free floating register,but tcc assume there is only one, so it wil force vtop goto memory and assign `r1' with TREG_ST0. When executing (3), it will do nothing because `r' equals `r1'. (5) duplicates vtop. Then (6) let the new vtop occupy TREG_ST0, but this will cause problem because the old vtop has been moved to memory, so the new duplicated vtop does not reside in TREG_ST0 but also in memory after that. TREG_ST0 is not occupied but freely availabe now. `gen_op('+')' need at least one oprand in register, so it will incorrectly think TREG_ST0 is occupied by vtop and produce instructions(0800001D and 08000020) to store it to a temporary memory location. According program above, if `r' == `r1' it is impossible for the old vtop to still occupy the `r' register . And `load' will do nothing too at this condition. So the `gv_dup' can not promise the semantics that old vtop in one register and the new duplicated vtop in another register at the same time. I changed (6) to if (r != r1) { vtop->r = r1; } Then the new generated machine code will be : .text:08000000 push ebp .text:08000001 mov ebp, esp .text:08000003 sub esp, 10h .text:08000009 nop .text:0800000A fld L_0 .text:08000010 fst [ebp+var_8] .text:08000013 fstp st(0) .text:08000015 fld [ebp+var_8] .text:08000018 fst [ebp+var_10] .text:0800001B fstp st(0) .text:0800001D fld L_1 .text:08000023 fadd [ebp+var_10] .text:08000026 fst [ebp+var_8] .text:08000029 fstp st(0) .text:0800002B leave .text:0800002C retn It works well, and will clean the floating registers stack when return. Finally, I want to know there is any potential problem of this fixing ? soloist
* use static declaration from prototypegrischka2009-06-171-3/+8
| | | | | | | | static int func(); ... int func() { } As result, func needs to be static.
* unions: initzialize only one fieldgrischka2009-06-171-0/+18
| | | | | | | | | | | struct { union { int a,b; }; int c; } sss = { 1,2 }; This had previously assigned 1,2 to a,b and 0 to c which is wrong.
* tccelf: accept BSS symbol with same name from other modulegrischka2009-06-171-1/+2
| | | | ... such as 'int baz;' in two files at the same time
* pass constness from structs to membersSam Watkins2009-06-161-0/+3
|
* x86-64: Align return value of alloca by 16.Shinichiro Hamaji2009-06-111-2/+2
|
* x86-64: Add alloca.Shinichiro Hamaji2009-06-092-0/+37
|
* drop alloca #definegrischka2009-05-1610-37/+27
| | | | | | | (Because GNU's alloca.h unconditionally #undef's alloca) Also, remove gcc specific sections in headers. and instead change tests such that gcc does not use them.
* ulibc: #define TCC_UCLIBC and load elf_interpgrischka2009-05-163-5/+12
|
* update Changelog, bump version: 0.9.25grischka2009-05-113-4/+7
|
* fix "cached include" optimizationgrischka2009-05-111-53/+58
| | | | | | | comparing the filenames as in the #include statement can be ambiguous if including files are in different directories. Now caches and checks the really opened filename instead.
* ARM: fix big immediate offset constructionDaniel Glöckner2009-05-111-6/+6
| | | | | | | | The loop constructs to iterate over the non-overlapping, even positions of two or three bytes in a word were broken. This patch fixes the loops. It has been verified to generate the 72 combinations for two and the 80 combinations for three bytes.
* fix build with msvcgrischka2009-05-112-17/+9
|
* fix unused/uninitalized warningsgrischka2009-05-112-0/+4
|
* fix warnings with tcc_add/get_symbolgrischka2009-05-112-2/+2
|
* enable making tcc using libtccgrischka2009-05-113-29/+32
|
* move static prototypes to libtcc.cgrischka2009-05-114-154/+180
|
* move some global variables into TCCStategrischka2009-05-119-86/+91
|
* make tcc from tcc.c and libtcc from libtcc.cgrischka2009-05-054-10/+2
|
* move minor things from libtcc.c to other filesgrischka2009-05-054-307/+314
|
* move global variables to libtcc.cgrischka2009-05-052-109/+111
|
* move libtcc interface and helper functions to libtcc.cgrischka2009-05-052-2281/+2283
|
* move parser/generator to tccgen.cgrischka2009-05-052-5102/+5103
|
* move preprocessor to tccpp.cgrischka2009-05-052-2642/+2644
|
* move declarations to tcc.hgrischka2009-05-052-935/+938
|
* new files: tcc.h libtcc.c tccpp.c tccgen.cgrischka2009-05-055-1/+82
|
* cleanup makefilesgrischka2009-04-192-72/+82
|
* enable backtrace only when it's supportedgrischka2009-04-181-8/+15
|
* Return value of exit should be void.Shinichiro Hamaji2009-04-181-1/+1
|
* Fixes for tests/Makefile.Shinichiro Hamaji2009-04-181-3/+3
| | | | | - On x86-64, we need $(TARGET) in RUN_TCC. - s/RuN_TCC/RUN_TCC/
* fix makefiles etc for subdirsgrischka2009-04-1813-272/+313
|
* new subdirs: include, lib, testsgrischka2009-04-1816-6/+0
|
* win32: readme.txt->tcc-win32.txt, update tcc-docgrischka2009-04-185-136/+177
|
* mute strange difference in tcctestgrischka2009-04-181-0/+3
|
* libtcc: add support to be build as DLLgrischka2009-04-181-20/+26
|
* libtcc: new api tcc_set_lib_pathgrischka2009-04-184-12/+26
|
* tcc_relocate: return error and remove unused codegrischka2009-04-181-18/+5
|
* Call relocate_sym() before we return the offset, so user doesn't need to ↵Shinichiro Hamaji2009-04-181-5/+5
| | | | check the return value twice.
* tcc -E: fix pasting empty tokensgrischka2009-04-181-23/+13
| | | | | | | | | | | /* test case */ #define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) }; tcc -E: xpected result: int j[] = { 123, 45, 67, 89, 10, 11, 12, };
* tcc -E: preserve spaces, alternative solutiongrischka2009-04-181-43/+73
| | | | | | | | | | | | /* test case */ #define STR(x) #x #define MKSTR(x) STR(x) MKSTR(-A-) MKSTR(+ B +) tcc -E: expected result: "-A-" "+ B +"