* 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 | 17 | XFLAGS = $(XFLAGS$(XCFG)) |
| 18 | 18 | XCFG = $(or $(findstring -win,$T),-unx) |
| 19 | 19 | |
| 20 | −ifeq ($(X),) | |
| 21 | − BCHECK_O = bcheck.o | |
| 22 | − ifeq "$T" "arm" | |
| 23 | − XCC = $(CC) | |
| 24 | − XAR = $(AR) | |
| 25 | − XFLAGS = $(CFLAGS) -fPIC | |
| 26 | − endif | |
| 27 | −endif | |
| 20 | +# using gcc ("make armlib-usegcc=no" to use tcc) | |
| 21 | +armlib-usegcc ?= no | |
| 28 | 22 | |
| 29 | −ifdef CONFIG_OSX | |
| 30 | − XFLAGS += -D_ANSI_SOURCE | |
| 23 | +ifeq "$($(X)$(T)lib-usegcc)" "yes" | |
| 24 | + XCC = $(CC) | |
| 25 | + XAR = $(AR) | |
| 26 | + XFLAGS = $(CFLAGS) -fPIC | |
| 31 | 27 | endif |
| 32 | 28 | |
| 29 | +# only for native compiler | |
| 30 | +$(X)BCHECK_O = bcheck.o | |
| 31 | + | |
| 33 | 32 | ifeq ($(CONFIG_musl),yes) |
| 34 | 33 | BCHECK_O = |
| 35 | 34 | endif |
| 36 | 35 | |
| 36 | +ifdef CONFIG_OSX | |
| 37 | + XFLAGS += -D_ANSI_SOURCE | |
| 38 | +endif | |
| 39 | + | |
| 37 | 40 | I386_O = libtcc1.o alloca86.o alloca86-bt.o |
| 38 | 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 | 43 | ARM64_O = lib-arm64.o |
| 41 | 44 | WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o |
| 42 | 45 | |
| 43 | 46 | OBJ-i386 = $(I386_O) $(BCHECK_O) |
| 44 | −TGT-i386 = -DTCC_TARGET_I386 | |
| 45 | − | |
| 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 | − | |
| 47 | +OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) | |
| 48 | +OBJ-x86_64-osx = $(X86_64_O) va_list.o | |
| 58 | 49 | OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) |
| 59 | −TGT-i386-win32 = -DTCC_TARGET_I386 -DTCC_TARGET_PE | |
| 60 | − | |
| 61 | 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 | |
| 63 | − | |
| 51 | +OBJ-arm64 = $(ARM64_O) | |
| 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 | 58 | OBJ-arm-wince = $(ARM_O) $(WIN_O) |
| 65 | −TGT-arm-wince = -DTCC_TARGET_ARM -DTCC_TARGET_PE | |
| 66 | 59 | |
| 67 | 60 | $(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T)) |
| 68 | 61 | $(XAR) rcs $@ $^ |
| 69 | 62 | |
| 70 | 63 | $(X)%.o : %.c |
| 71 | − $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) | |
| 64 | + $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) | |
| 72 | 65 | |
| 73 | 66 | $(X)%.o : %.S |
| 74 | − $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) | |
| 67 | + $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) | |
| 75 | 68 | |
| 76 | 69 | $(X)crt1w.o : crt1.c |
| 77 | 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 | 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 | 560 | unsigned long long __fixunsdfdi (double a1) |
| 554 | 561 | { |
| 555 | 562 | register union double_long dl1; |
| @@ -575,6 +582,14 @@ unsigned long long __fixunsdfdi (double a1) · 19 unmodified lines | ||
| 575 | 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 | 593 | unsigned long long __fixunsxfdi (long double a1) |
| 579 | 594 | { |
| 580 | 595 | register union ldouble_long dl1; |
| @@ -598,121 +613,10 @@ unsigned long long __fixunsxfdi (long double a1) · 17 unmodified lines | ||
| 598 | 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 | 616 | long long __fixxfdi (long double a1) |
| 616 | 617 | { |
| 617 | 618 | long long ret; int s; |
| 618 | 619 | ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); |
| 619 | 620 | return s ? ret : -ret; |
| 620 | 621 | } |
| 621 | − | |
| 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 */ | |
| 622 | +#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 | |