* tccgen: re-allow long double constants for x87 cross sizeof (long double) may be 12 or 16 depending on host platform (i386/x86_64 on unix/windows). Except that it's 8 if the host is on windows and not gcc was used to compile tcc. * win64: fix builtin_va_start after VT_REF removal See also a8b83ce43a95fa519dacfe7690a3a0098af7909c * tcctest.c: remove outdated limitation for ll-bitfield test It always worked, there is no reason why it should not work in future. * libtcc1.c: exclude long double conversion on ARM * Makefile: remove CFLAGS from link recipes * lib/Makefile: use target DEFINES as passed from main Makefile * lib/armflush.c lib/va_list.c: factor out from libtcc1.c * arm-gen.c: disable "depreciated" warnings for now
Showing the changes to lib (4 of 9 files). Show all
Unified · Split
| @@ -17,61 +17,54 @@ XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include · 16 unmodified lines | |||
| 17 | XFLAGS = $(XFLAGS$(XCFG)) | 17 | XFLAGS = $(XFLAGS$(XCFG)) |
| 18 | XCFG = $(or $(findstring -win,$T),-unx) | 18 | XCFG = $(or $(findstring -win,$T),-unx) |
| 19 | 19 | ||
| 20 | ifeq ($(X),) | 20 | # using gcc ("make armlib-usegcc=no" to use tcc) |
| 21 | BCHECK_O = bcheck.o | 21 | armlib-usegcc ?= no |
| 22 | ifeq "$T" "arm" | ||
| 23 | XCC = $(CC) | ||
| 24 | XAR = $(AR) | ||
| 25 | XFLAGS = $(CFLAGS) -fPIC | ||
| 26 | endif | ||
| 27 | endif | ||
| 28 | 22 | ||
| 29 | ifdef CONFIG_OSX | 23 | ifeq "$($(X)$(T)lib-usegcc)" "yes" |
| 30 | XFLAGS += -D_ANSI_SOURCE | 24 | XCC = $(CC) |
| 25 | XAR = $(AR) | ||
| 26 | XFLAGS = $(CFLAGS) -fPIC | ||
| 31 | endif | 27 | endif |
| 32 | 28 | ||
| 29 | # only for native compiler | ||
| 30 | $(X)BCHECK_O = bcheck.o | ||
| 31 | |||
| 33 | ifeq ($(CONFIG_musl),yes) | 32 | ifeq ($(CONFIG_musl),yes) |
| 34 | BCHECK_O = | 33 | BCHECK_O = |
| 35 | endif | 34 | endif |
| 36 | 35 | ||
| 36 | ifdef CONFIG_OSX | ||
| 37 | XFLAGS += -D_ANSI_SOURCE | ||
| 38 | endif | ||
| 39 | |||
| 37 | I386_O = libtcc1.o alloca86.o alloca86-bt.o | 40 | I386_O = libtcc1.o alloca86.o alloca86-bt.o |
| 38 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o | 41 | X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o |
| 39 | ARM_O = libtcc1.o armeabi.o alloca-arm.o | 42 | ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o |
| 40 | ARM64_O = lib-arm64.o | 43 | ARM64_O = lib-arm64.o |
| 41 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o | 44 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 42 | 45 | ||
| 43 | OBJ-i386 = $(I386_O) $(BCHECK_O) | 46 | OBJ-i386 = $(I386_O) $(BCHECK_O) |
| 44 | TGT-i386 = -DTCC_TARGET_I386 | 47 | OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) |
| 45 | 48 | OBJ-x86_64-osx = $(X86_64_O) va_list.o | |
| 46 | OBJ-x86_64 = $(X86_64_O) $(BCHECK_O) | ||
| 47 | TGT-x86_64 = -DTCC_TARGET_X86_64 | ||
| 48 | |||
| 49 | OBJ-x86_64-osx = $(X86_64_O) | ||
| 50 | TGT-x86_64-osx = -DTCC_TARGET_X86_64 -DTCC_TARGET_MACHO | ||
| 51 | |||
| 52 | OBJ-arm = $(ARM_O) | ||
| 53 | TGT-arm = -DTCC_TARGET_ARM | ||
| 54 | |||
| 55 | OBJ-arm64 = $(ARM64_O) | ||
| 56 | TGT-arm64 = -DTCC_TARGET_ARM64 | ||
| 57 | |||
| 58 | OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) | 49 | OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) |
| 59 | TGT-i386-win32 = -DTCC_TARGET_I386 -DTCC_TARGET_PE | ||
| 60 | |||
| 61 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) | 50 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) |
| 62 | TGT-x86_64-win32 = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE | 51 | OBJ-arm64 = $(ARM64_O) |
| 63 | 52 | OBJ-arm = $(ARM_O) | |
| 53 | OBJ-arm-fpa = $(ARM_O) | ||
| 54 | OBJ-arm-fpa-ld = $(ARM_O) | ||
| 55 | OBJ-arm-vfp = $(ARM_O) | ||
| 56 | OBJ-arm-eabi = $(ARM_O) | ||
| 57 | OBJ-arm-eabihf = $(ARM_O) | ||
| 64 | OBJ-arm-wince = $(ARM_O) $(WIN_O) | 58 | OBJ-arm-wince = $(ARM_O) $(WIN_O) |
| 65 | TGT-arm-wince = -DTCC_TARGET_ARM -DTCC_TARGET_PE | ||
| 66 | 59 | ||
| 67 | $(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T)) | 60 | $(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T)) |
| 68 | $(XAR) rcs $@ $^ | 61 | $(XAR) rcs $@ $^ |
| 69 | 62 | ||
| 70 | $(X)%.o : %.c | 63 | $(X)%.o : %.c |
| 71 | $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) | 64 | $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) |
| 72 | 65 | ||
| 73 | $(X)%.o : %.S | 66 | $(X)%.o : %.S |
| 74 | $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) | 67 | $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) |
| 75 | 68 | ||
| 76 | $(X)crt1w.o : crt1.c | 69 | $(X)crt1w.o : crt1.c |
| 77 | $(X)wincrt1w.o : wincrt1.c | 70 | $(X)wincrt1w.o : wincrt1.c |
| @@ -0,0 +1,58 @@ | |||
| 1 | /* armflush.c - flush the instruction cache | ||
| 2 | |||
| 3 | __clear_cache is used in tccrun.c, It is a built-in | ||
| 4 | intrinsic with gcc. However tcc in order to compile | ||
| 5 | itself needs this function */ | ||
| 6 | |||
| 7 | #ifdef __TINYC__ | ||
| 8 | |||
| 9 | /* syscall wrapper */ | ||
| 10 | unsigned syscall(unsigned syscall_nr, ...); | ||
| 11 | |||
| 12 | /* arm-tcc supports only fake asm currently */ | ||
| 13 | __asm__( | ||
| 14 | ".global syscall\n" | ||
| 15 | "syscall:\n" | ||
| 16 | ".int 0xe92d4080\n" // push {r7, lr} | ||
| 17 | ".int 0xe1a07000\n" // mov r7, r0 | ||
| 18 | ".int 0xe1a00001\n" // mov r0, r1 | ||
| 19 | ".int 0xe1a01002\n" // mov r1, r2 | ||
| 20 | ".int 0xe1a02003\n" // mov r2, r3 | ||
| 21 | ".int 0xef000000\n" // svc 0x00000000 | ||
| 22 | ".int 0xe8bd8080\n" // pop {r7, pc} | ||
| 23 | ); | ||
| 24 | |||
| 25 | /* from unistd.h: */ | ||
| 26 | #if defined(__thumb__) || defined(__ARM_EABI__) | ||
| 27 | # define __NR_SYSCALL_BASE 0x0 | ||
| 28 | #else | ||
| 29 | # define __NR_SYSCALL_BASE 0x900000 | ||
| 30 | #endif | ||
| 31 | #define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000) | ||
| 32 | #define __ARM_NR_cacheflush (__ARM_NR_BASE+2) | ||
| 33 | |||
| 34 | #else | ||
| 35 | |||
| 36 | #define _GNU_SOURCE | ||
| 37 | #include <unistd.h> | ||
| 38 | #include <sys/syscall.h> | ||
| 39 | #include <stdio.h> | ||
| 40 | |||
| 41 | #endif | ||
| 42 | |||
| 43 | /* Flushing for tccrun */ | ||
| 44 | void __clear_cache(void *beginning, void *end) | ||
| 45 | { | ||
| 46 | /* __ARM_NR_cacheflush is kernel private and should not be used in user space. | ||
| 47 | * However, there is no ARM asm parser in tcc so we use it for now */ | ||
| 48 | #if 1 | ||
| 49 | syscall(__ARM_NR_cacheflush, beginning, end, 0); | ||
| 50 | #else | ||
| 51 | __asm__ ("push {r7}\n\t" | ||
| 52 | "mov r7, #0xf0002\n\t" | ||
| 53 | "mov r2, #0\n\t" | ||
| 54 | "swi 0\n\t" | ||
| 55 | "pop {r7}\n\t" | ||
| 56 | "ret"); | ||
| 57 | #endif | ||
| 58 | } | ||
| @@ -550,6 +550,13 @@ unsigned long long __fixunssfdi (float a1) · 549 unmodified lines | |||
| 550 | return 0; | 550 | return 0; |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | long long __fixsfdi (float a1) | ||
| 554 | { | ||
| 555 | long long ret; int s; | ||
| 556 | ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); | ||
| 557 | return s ? ret : -ret; | ||
| 558 | } | ||
| 559 | |||
| 553 | unsigned long long __fixunsdfdi (double a1) | 560 | unsigned long long __fixunsdfdi (double a1) |
| 554 | { | 561 | { |
| 555 | register union double_long dl1; | 562 | register union double_long dl1; |
| @@ -575,6 +582,14 @@ unsigned long long __fixunsdfdi (double a1) · 19 unmodified lines | |||
| 575 | return 0; | 582 | return 0; |
| 576 | } | 583 | } |
| 577 | 584 | ||
| 585 | long long __fixdfdi (double a1) | ||
| 586 | { | ||
| 587 | long long ret; int s; | ||
| 588 | ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); | ||
| 589 | return s ? ret : -ret; | ||
| 590 | } | ||
| 591 | |||
| 592 | #ifndef TCC_TARGET_ARM | ||
| 578 | unsigned long long __fixunsxfdi (long double a1) | 593 | unsigned long long __fixunsxfdi (long double a1) |
| 579 | { | 594 | { |
| 580 | register union ldouble_long dl1; | 595 | register union ldouble_long dl1; |
| @@ -598,121 +613,10 @@ unsigned long long __fixunsxfdi (long double a1) · 17 unmodified lines | |||
| 598 | return 0; | 613 | return 0; |
| 599 | } | 614 | } |
| 600 | 615 | ||
| 601 | long long __fixsfdi (float a1) | ||
| 602 | { | ||
| 603 | long long ret; int s; | ||
| 604 | ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); | ||
| 605 | return s ? ret : -ret; | ||
| 606 | } | ||
| 607 | |||
| 608 | long long __fixdfdi (double a1) | ||
| 609 | { | ||
| 610 | long long ret; int s; | ||
| 611 | ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); | ||
| 612 | return s ? ret : -ret; | ||
| 613 | } | ||
| 614 | |||
| 615 | long long __fixxfdi (long double a1) | 616 | long long __fixxfdi (long double a1) |
| 616 | { | 617 | { |
| 617 | long long ret; int s; | 618 | long long ret; int s; |
| 618 | ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); | 619 | ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); |
| 619 | return s ? ret : -ret; | 620 | return s ? ret : -ret; |
| 620 | } | 621 | } |
| 621 | 622 | #endif /* !ARM */ | |
| 622 | #if defined(TCC_TARGET_X86_64) && !defined(_WIN64) | ||
| 623 | |||
| 624 | #ifndef __TINYC__ | ||
| 625 | # include <stdlib.h> | ||
| 626 | # include <stdio.h> | ||
| 627 | # include <string.h> | ||
| 628 | # undef __va_start | ||
| 629 | # undef __va_arg | ||
| 630 | # undef __va_copy | ||
| 631 | # undef __va_end | ||
| 632 | #else | ||
| 633 | /* Avoid include files, they may not be available when cross compiling */ | ||
| 634 | extern void *memset(void *s, int c, __SIZE_TYPE__ n); | ||
| 635 | extern void abort(void); | ||
| 636 | #endif | ||
| 637 | |||
| 638 | /* This should be in sync with our include/stdarg.h */ | ||
| 639 | enum __va_arg_type { | ||
| 640 | __va_gen_reg, __va_float_reg, __va_stack | ||
| 641 | }; | ||
| 642 | |||
| 643 | /* GCC compatible definition of va_list. */ | ||
| 644 | typedef struct { | ||
| 645 | unsigned int gp_offset; | ||
| 646 | unsigned int fp_offset; | ||
| 647 | union { | ||
| 648 | unsigned int overflow_offset; | ||
| 649 | char *overflow_arg_area; | ||
| 650 | }; | ||
| 651 | char *reg_save_area; | ||
| 652 | } __va_list_struct; | ||
| 653 | |||
| 654 | void __va_start(__va_list_struct *ap, void *fp) | ||
| 655 | { | ||
| 656 | memset(ap, 0, sizeof(__va_list_struct)); | ||
| 657 | *ap = *(__va_list_struct *)((char *)fp - 16); | ||
| 658 | ap->overflow_arg_area = (char *)fp + ap->overflow_offset; | ||
| 659 | ap->reg_save_area = (char *)fp - 176 - 16; | ||
| 660 | } | ||
| 661 | |||
| 662 | void *__va_arg(__va_list_struct *ap, | ||
| 663 | enum __va_arg_type arg_type, | ||
| 664 | int size, int align) | ||
| 665 | { | ||
| 666 | size = (size + 7) & ~7; | ||
| 667 | align = (align + 7) & ~7; | ||
| 668 | switch (arg_type) { | ||
| 669 | case __va_gen_reg: | ||
| 670 | if (ap->gp_offset + size <= 48) { | ||
| 671 | ap->gp_offset += size; | ||
| 672 | return ap->reg_save_area + ap->gp_offset - size; | ||
| 673 | } | ||
| 674 | goto use_overflow_area; | ||
| 675 | |||
| 676 | case __va_float_reg: | ||
| 677 | if (ap->fp_offset < 128 + 48) { | ||
| 678 | ap->fp_offset += 16; | ||
| 679 | return ap->reg_save_area + ap->fp_offset - 16; | ||
| 680 | } | ||
| 681 | size = 8; | ||
| 682 | goto use_overflow_area; | ||
| 683 | |||
| 684 | case __va_stack: | ||
| 685 | use_overflow_area: | ||
| 686 | ap->overflow_arg_area += size; | ||
| 687 | ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); | ||
| 688 | return ap->overflow_arg_area - size; | ||
| 689 | |||
| 690 | default: /* should never happen */ | ||
| 691 | abort(); | ||
| 692 | } | ||
| 693 | } | ||
| 694 | #endif /* __x86_64__ */ | ||
| 695 | |||
| 696 | #if defined TCC_TARGET_ARM && !defined __TINYC__ | ||
| 697 | #define _GNU_SOURCE | ||
| 698 | #include <unistd.h> | ||
| 699 | #include <sys/syscall.h> | ||
| 700 | #include <stdio.h> | ||
| 701 | |||
| 702 | /* Flushing for tccrun */ | ||
| 703 | void __clear_cache(void *beginning, void *end) | ||
| 704 | { | ||
| 705 | /* __ARM_NR_cacheflush is kernel private and should not be used in user space. | ||
| 706 | * However, there is no ARM asm parser in tcc so we use it for now */ | ||
| 707 | #if 1 | ||
| 708 | syscall(__ARM_NR_cacheflush, beginning, end, 0); | ||
| 709 | #else | ||
| 710 | __asm__ ("push {r7}\n\t" | ||
| 711 | "mov r7, #0xf0002\n\t" | ||
| 712 | "mov r2, #0\n\t" | ||
| 713 | "swi 0\n\t" | ||
| 714 | "pop {r7}\n\t" | ||
| 715 | "ret"); | ||
| 716 | #endif | ||
| 717 | } | ||
| 718 | #endif /* arm */ | ||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* va_list.c - tinycc support for va_list on X86_64 */ | ||
| 2 | |||
| 3 | #if defined TCC_TARGET_X86_64 | ||
| 4 | |||
| 5 | /* Avoid include files, they may not be available when cross compiling */ | ||
| 6 | extern void *memset(void *s, int c, __SIZE_TYPE__ n); | ||
| 7 | extern void abort(void); | ||
| 8 | |||
| 9 | /* This should be in sync with our include/stdarg.h */ | ||
| 10 | enum __va_arg_type { | ||
| 11 | __va_gen_reg, __va_float_reg, __va_stack | ||
| 12 | }; | ||
| 13 | |||
| 14 | /* GCC compatible definition of va_list. */ | ||
| 15 | typedef struct { | ||
| 16 | unsigned int gp_offset; | ||
| 17 | unsigned int fp_offset; | ||
| 18 | union { | ||
| 19 | unsigned int overflow_offset; | ||
| 20 | char *overflow_arg_area; | ||
| 21 | }; | ||
| 22 | char *reg_save_area; | ||
| 23 | } __va_list_struct; | ||
| 24 | |||
| 25 | void __va_start(__va_list_struct *ap, void *fp) | ||
| 26 | { | ||
| 27 | memset(ap, 0, sizeof(__va_list_struct)); | ||
| 28 | *ap = *(__va_list_struct *)((char *)fp - 16); | ||
| 29 | ap->overflow_arg_area = (char *)fp + ap->overflow_offset; | ||
| 30 | ap->reg_save_area = (char *)fp - 176 - 16; | ||
| 31 | } | ||
| 32 | |||
| 33 | void *__va_arg(__va_list_struct *ap, | ||
| 34 | enum __va_arg_type arg_type, | ||
| 35 | int size, int align) | ||
| 36 | { | ||
| 37 | size = (size + 7) & ~7; | ||
| 38 | align = (align + 7) & ~7; | ||
| 39 | switch (arg_type) { | ||
| 40 | case __va_gen_reg: | ||
| 41 | if (ap->gp_offset + size <= 48) { | ||
| 42 | ap->gp_offset += size; | ||
| 43 | return ap->reg_save_area + ap->gp_offset - size; | ||
| 44 | } | ||
| 45 | goto use_overflow_area; | ||
| 46 | |||
| 47 | case __va_float_reg: | ||
| 48 | if (ap->fp_offset < 128 + 48) { | ||
| 49 | ap->fp_offset += 16; | ||
| 50 | return ap->reg_save_area + ap->fp_offset - 16; | ||
| 51 | } | ||
| 52 | size = 8; | ||
| 53 | goto use_overflow_area; | ||
| 54 | |||
| 55 | case __va_stack: | ||
| 56 | use_overflow_area: | ||
| 57 | ap->overflow_arg_area += size; | ||
| 58 | ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); | ||
| 59 | return ap->overflow_arg_area - size; | ||
| 60 | |||
| 61 | default: /* should never happen */ | ||
| 62 | abort(); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | #endif | ||