diff --git a/Makefile b/Makefile
index e492d350..947f7574 100644
--- a/Makefile
+++ b/Makefile
@@ -90,8 +90,10 @@ NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
 NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
 NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64
 NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS)
+NATIVE_DEFINES_$(CONFIG_Android) += -DTARGETOS_ANDROID
 NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE
 NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC
+NATIVE_DEFINES_$(CONFIG_new-dtags) += -DCONFIG_NEW_DTAGS
 NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0
 NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0
 NATIVE_DEFINES += $(NATIVE_DEFINES_yes) $(NATIVE_DEFINES_no_no)
diff --git a/configure b/configure
index cd96ea30..00879451 100755
--- a/configure
+++ b/configure
@@ -27,8 +27,7 @@ mandir=""
 infodir=""
 sysroot=""
 cross_prefix=""
-test -z "$CC" && CC="gcc"
-test -z "$cc" && cc="$CC"
+cc="gcc"
 ar="ar"
 bigendian="no"
 mingw32="no"
@@ -46,16 +45,20 @@ confvars=
 suggest="yes"
 gcc_major=0
 gcc_minor=0
-cc_name="$cc"
+cc_name="gcc"
 ar_set=
 darwin=
-cpu=
 cpuver=
 dwarf=
 
+# use CC from environment when set
+test -n "$CC" && cc="$CC"
+
 # OS specific
-cpu_sys=`uname -m`
+cpu=`uname -m`
+cpu_sys="$cpu"
 targetos=`uname`
+test "$(uname -o)" = "Android" && targetos=Android
 
 case $targetos in
   Darwin)
@@ -73,6 +76,20 @@ case $targetos in
   DragonFly|OpenBSD|FreeBSD|NetBSD)
     confvars="$confvars BSD ldl=no"
     ;;
+  Android)
+    confvars="$confvars Android pie new-dtags"
+    if test -n "$TERMUX_VERSION"; then
+      prefix="$PREFIX" # "/data/data/com.termux/files/usr"
+      sysroot="$PREFIX"
+      test "$cpu" = "aarch64" -o "$cpu" = "x86_64" && S="64" || S=""
+      tcc_sysincludepaths="{B}/include:{R}/include/\\\"CONFIG_TRIPLET\\\":{R}/include"
+      tcc_libpaths="{B}:{R}/lib:/system/lib${S}"
+      tcc_crtprefix="{R}/lib"
+      tcc_elfinterp="/system/bin/linker${S}"
+      use_triplet="yes"
+      tcc_switches="-Wl,-rpath=$sysroot/lib,-section-alignment=0x1000"
+    fi
+    ;;
   *)
     ;;
 esac
@@ -153,6 +170,8 @@ for opt do
   ;;
   --with-selinux) confvars="$confvars selinux"
   ;;
+  --tcc-switches=*) tcc_switches=`echo $opt | cut -d '=' -f 2-`
+  ;;
   --config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2)
   ;;
   --config-*) confvars="$confvars ${opt#--config-}"; suggest="no"
@@ -176,9 +195,6 @@ if test "$darwin" = "yes" -a "$cpu" = "x86_64" -a "$cpu_sys" = "arm64"; then
     LDFLAGS="$LDFLAGS -arch $cpu"
 fi
 
-# checking for cpu
-test -z "$cpu" && cpu="$cpu_sys"
-
 case "$cpu" in
   x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
     cpu="i386"
@@ -325,6 +341,7 @@ Advanced options (experts only):
   --crtprefix=...          specify locations of crt?.o, colon separated
   --elfinterp=...          specify elf interpreter
   --triplet=...            specify system library/include directory triplet
+  --tcc-switches=...       specify implicit switches passed to tcc
 
   --config-uClibc,-musl    enable system specific configurations
   --config-mingw32         build on windows using msys, busybox, etc.
@@ -349,8 +366,8 @@ if test -z "$cross_prefix" ; then
   fi
   if test "$mingw32" = "no" ; then
 
-      if test -z "$triplet"; then
-        if test -n "$_triplet" -a -f "/usr/lib/$_triplet/crti.o" ; then
+      if test -z "$triplet" -a -n "$_triplet"; then
+        if test -f "/usr/lib/$_triplet/crti.o" -o -n "$use_triplet" ; then
           triplet="$_triplet"
         fi
       fi
@@ -372,8 +389,7 @@ if test -z "$cross_prefix" ; then
 	   confvars="$confvars arm_eabihf arm_vfp"
 	elif test "${_triplet%eabi}" != "$_triplet" ; then
 	   confvars="$confvars arm_eabi arm_vfp"
-	fi
-	if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
+	elif grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
 	   confvars="$confvars arm_vfp"
 	fi
       fi
@@ -496,6 +512,7 @@ print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
 print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
 print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
 print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
+print_mak CONFIG_TCC_SWITCHES "$tcc_switches"
 print_mak CONFIG_LDDIR "$tcc_lddir"
 print_mak CONFIG_TRIPLET "$triplet"
 print_mak TCC_CPU_VERSION "$cpuver" num
diff --git a/conftest.c b/conftest.c
index e8e1220a..ad7275cf 100644
--- a/conftest.c
+++ b/conftest.c
@@ -21,6 +21,8 @@ const char *platform_macros[] = {
     "__OpenBSD__",          "TARGETOS_OpenBSD",
     "__NetBSD__",           "TARGETOS_NetBSD",
     "__linux__",            "TARGETOS_Linux",
+    "__ANDROID__",          "TARGETOS_ANDROID",
+
     "__SIZEOF_POINTER__",   "PTR_SIZE",
     "__SIZEOF_LONG__",      "LONG_SIZE",
     0
@@ -206,15 +208,21 @@ int main(int argc, char **argv)
 # define TRIPLET_OS "unknown"
 #endif
 
+#if defined __ANDROID__
+# define ABI_PREFIX "android"
+#else
+# define ABI_PREFIX "gnu"
+#endif
+
 /* Define calling convention and ABI */
 #if defined (__ARM_EABI__)
 # if defined (__ARM_PCS_VFP)
-#  define TRIPLET_ABI "gnueabihf"
+#  define TRIPLET_ABI ABI_PREFIX"eabihf"
 # else
-#  define TRIPLET_ABI "gnueabi"
+#  define TRIPLET_ABI ABI_PREFIX"eabi"
 # endif
 #else
-# define TRIPLET_ABI "gnu"
+# define TRIPLET_ABI ABI_PREFIX
 #endif
 
 #if defined _WIN32
diff --git a/include/tccdefs.h b/include/tccdefs.h
index 83e3c388..585dfa20 100644
--- a/include/tccdefs.h
+++ b/include/tccdefs.h
@@ -125,6 +125,13 @@
     #define __FINITE_MATH_ONLY__ 1
     #define _FORTIFY_SOURCE 0
 
+#elif defined __ANDROID__
+    #define  BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
+    #define  __PRETTY_FUNCTION__ __FUNCTION__
+    #define __has_builtin(x) 0
+    #define _Nonnull
+    #define _Nullable
+
 #else
     /* Linux */
 
diff --git a/lib/bcheck.c b/lib/bcheck.c
index 729f0b5d..9216d0f7 100644
--- a/lib/bcheck.c
+++ b/lib/bcheck.c
@@ -161,7 +161,7 @@ static pthread_spinlock_t bounds_spin;
 #define HAVE_TLS_FUNC          (1)
 #define HAVE_TLS_VAR           (0)
 #endif
-#ifdef TCC_MUSL
+#if defined TCC_MUSL || defined __ANDROID__
 # undef HAVE_CTYPE
 #endif
 #endif
@@ -1174,7 +1174,8 @@ void __attribute__((destructor)) __bound_exit(void)
 
     if (inited) {
 #if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \
-    !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+    !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
+    !defined(__ANDROID__)
         if (print_heap) {
             extern void __libc_freeres (void);
             __libc_freeres ();
diff --git a/libtcc.c b/libtcc.c
index 652f5129..66baaa82 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -496,6 +496,8 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *
                 c = p[1], p += 2;
                 if (c == 'B')
                     cstr_cat(&str, s->tcc_lib_path, -1);
+                if (c == 'R')
+                    cstr_cat(&str, CONFIG_SYSROOT, -1);
                 if (c == 'f' && file) {
                     /* substitute current file's dir */
                     const char *f = file->true_filename;
@@ -810,7 +812,9 @@ LIBTCCAPI TCCState *tcc_new(void)
 #ifdef TCC_TARGET_ARM
     s->float_abi = ARM_FLOAT_ABI;
 #endif
-
+#ifdef CONFIG_NEW_DTAGS
+    s->enable_new_dtags = 1;
+#endif
     s->ppfp = stdout;
     /* might be used in error() before preprocess_start() */
     s->include_stack_ptr = s->include_stack;
@@ -943,6 +947,11 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
             tcc_add_crt(s, "crtbeginS.o");
         else
             tcc_add_crt(s, "crtbegin.o");
+#elif defined TARGETOS_ANDROID
+        if (output_type != TCC_OUTPUT_DLL)
+            tcc_add_crt(s, "crtbegin_dynamic.o");
+        else
+            tcc_add_crt(s, "crtbegin_so.o");
 #else
         if (output_type != TCC_OUTPUT_DLL)
             tcc_add_crt(s, "crt1.o");
diff --git a/tcc.c b/tcc.c
index 2569e2a4..fe530e39 100644
--- a/tcc.c
+++ b/tcc.c
@@ -281,6 +281,9 @@ int main(int argc0, char **argv0)
 redo:
     argc = argc0, argv = argv0;
     s = s1 = tcc_new();
+#ifdef CONFIG_TCC_SWITCHES
+    tcc_set_options(s, CONFIG_TCC_SWITCHES);
+#endif
     opt = tcc_parse_args(s, &argc, &argv, 1);
 
     if (n == 0) {
diff --git a/tccelf.c b/tccelf.c
index e6d5bc0f..532785f3 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -857,7 +857,7 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
 #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
                 /* dlsym() needs the undecorated name.  */
                 void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]);
-#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
+#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID
 		if (addr == NULL) {
 		    int i;
 		    for (i = 0; i < s1->nb_loaded_dlls; i++)
@@ -1526,6 +1526,11 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
 # if !TARGETOS_OpenBSD
             tcc_add_crt(s1, "crtn.o");
 # endif
+#elif TARGETOS_ANDROID
+	    if (s1->output_type == TCC_OUTPUT_DLL)
+                tcc_add_crt(s1, "crtend_so.o");
+            else
+                tcc_add_crt(s1, "crtend_android.o");
 #else
             tcc_add_crt(s1, "crtn.o");
 #endif
@@ -2272,22 +2277,15 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
     ehdr.e_ident[4] = ELFCLASSW;
     ehdr.e_ident[5] = ELFDATA2LSB;
     ehdr.e_ident[6] = EV_CURRENT;
+
 #if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
     ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
-#endif
-#ifdef TCC_TARGET_ARM
-#ifdef TCC_ARM_EABI
-    ehdr.e_ident[EI_OSABI] = 0;
-    ehdr.e_flags = EF_ARM_EABI_VER4;
-    if (file_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL))
-        ehdr.e_flags |= EF_ARM_HASENTRY;
-    if (s1->float_abi == ARM_HARD_FLOAT)
-        ehdr.e_flags |= EF_ARM_VFP_FLOAT;
-    else
-        ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
-#else
+#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI
+    ehdr.e_flags = EF_ARM_EABI_VER5;
+    ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT
+        ? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT;
+#elif defined TCC_TARGET_ARM
     ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
-#endif
 #elif defined TCC_TARGET_RISCV64
     ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
 #endif
diff --git a/tccgen.c b/tccgen.c
index 55242099..1a3daff7 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -8266,7 +8266,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
                 sym = type.ref;
                 if (sym->f.func_type == FUNC_OLD && l == VT_CONST)
                     decl0(VT_CMP, 0, sym);
-#ifdef TCC_TARGET_MACHO
+#if defined TCC_TARGET_MACHO || defined TARGETOS_ANDROID
                 if (sym->f.func_alwinl
                     && ((type.t & (VT_EXTERN | VT_INLINE))
                         == (VT_EXTERN | VT_INLINE))) {
diff --git a/tccpp.c b/tccpp.c
index 31c3a2b3..e033a29b 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -3713,6 +3713,9 @@ static const char * const target_os_defs =
 # else
     "__linux__\0"
     "__linux\0"
+#  if TARGETOS_ANDROID
+    "__ANDROID__\0"
+#  endif
 # endif
     "__unix__\0"
     "__unix\0"
@@ -3724,17 +3727,22 @@ static void putdef(CString *cs, const char *p)
     cstr_printf(cs, "#define %s%s\n", p, &" 1"[!!strchr(p, ' ')*2]);
 }
 
+static void putdefs(CString *cs, const char *p)
+{
+    while (*p)
+        putdef(cs, p), p = strchr(p, 0) + 1;
+}
+
 static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
 {
     int a, b, c;
-    const char *defs[] = { target_machine_defs, target_os_defs, NULL };
-    const char *p;
 
     sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
     cstr_printf(cs, "#define __TINYC__ %d\n", a*10000 + b*100 + c);
-    for (a = 0; defs[a]; ++a)
-        for (p = defs[a]; *p; p = strchr(p, 0) + 1)
-            putdef(cs, p);
+
+    putdefs(cs, target_machine_defs);
+    putdefs(cs, target_os_defs);
+
 #ifdef TCC_TARGET_ARM
     if (s1->float_abi == ARM_HARD_FLOAT)
       putdef(cs, "__ARM_PCS_VFP");
diff --git a/tccrun.c b/tccrun.c
index 40326495..826e52ca 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -390,7 +390,7 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
         tcc_error("mprotect failed: did you mean to configure --with-selinux?");
 
 /* XXX: BSD sometimes dump core with bad system call */
-# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64
+# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
     if (mode == 0 || mode == 3) {
         void __clear_cache(void *beginning, void *end);
         __clear_cache(ptr, (char *)ptr + length);
diff --git a/tests/Makefile b/tests/Makefile
index aec40544..2405e954 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -35,8 +35,8 @@ endif
 ifeq (,$(filter arm64 i386 x86_64,$(ARCH)))
  TESTS := $(filter-out vla_test-run,$(TESTS))
 endif
-ifeq ($(CONFIG_arm_eabi),yes)
- TESTS := $(filter-out test3,$(TESTS))
+ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--)
+ TESTS := $(filter-out test3 test1b,$(TESTS))
 endif
 ifeq (,$(filter i386 x86_64,$(ARCH)))
  TESTS := $(filter-out asm-c-connect-test,$(TESTS))
@@ -250,7 +250,7 @@ abitest-% : abitest-%.exe
 	./$< $(TCCFLAGS)
 
 abitest: abitest-cc
-ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
+ifneq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--)
 abitest: abitest-tcc
 endif
 
@@ -261,6 +261,8 @@ vla_test-run: vla_test$(EXESUF)
 	@echo ------------ $@ ------------
 	./vla_test$(EXESUF)
 
+.PHONY: abitest vla_test
+
 asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c
 	$(TCC) -o $@ $^
 
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 5848ab80..51eea486 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -21,14 +21,19 @@
 typedef __SIZE_TYPE__ uintptr_t;
 #endif
 
-#if defined(_WIN32) || \
-    (defined(__arm__) && \
-     (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)))
+#if defined(_WIN32) \
+    || (defined(__arm__) \
+        && (defined(__FreeBSD__) \
+         || defined(__OpenBSD__) \
+         || defined(__NetBSD__) \
+         || defined __ANDROID__))
 #define LONG_LONG_FORMAT "%lld"
 #define ULONG_LONG_FORMAT "%llu"
+#define XLONG_LONG_FORMAT "%llx"
 #else
 #define LONG_LONG_FORMAT "%Ld"
 #define ULONG_LONG_FORMAT "%Lu"
+#define XLONG_LONG_FORMAT "%Lx"
 #endif
 
 // MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC
@@ -2265,7 +2270,7 @@ double ftab1[3] = { 1.2, 3.4, -5.6 };
 
 void float_test(void)
 {
-#if !defined(__arm__) || defined(__ARM_PCS_VFP)
+#if !defined(__arm__) || defined(__ARM_PCS_VFP) || defined __ANDROID__
     volatile float fa, fb;
     volatile double da, db;
     int a;
@@ -2531,7 +2536,7 @@ void longlong_test(void)
     b = 0x12345678;
     a = -1;
     c = a + b;
-    printf("%Lx\n", c);
+    printf(XLONG_LONG_FORMAT"\n", c);
 #endif
 
     /* long long reg spill test */
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index 776c7276..44c28fe3 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -9,7 +9,7 @@ TESTS = $(patsubst %.c,%.test,\
 
 # some tests do not pass on all platforms, remove them for now
 SKIP = 34_array_assignment.test # array assignment is not in C standard
-ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
+ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--)
  SKIP += 22_floating_point.test
 endif
 ifdef CONFIG_OSX
@@ -27,12 +27,12 @@ ifeq (,$(filter i386 x86_64,$(ARCH)))
  SKIP += 125_atomic_misc.test # currently only x86 supported
 endif
 ifeq ($(CONFIG_backtrace),no)
- SKIP += 112_backtrace.test
  SKIP += 113_btdll.test
  CONFIG_bcheck = no
 # no bcheck without backtrace
 endif
 ifeq ($(CONFIG_bcheck),no)
+ SKIP += 112_backtrace.test
  SKIP += 114_bound_signal.test
  SKIP += 115_bound_setjmp.test
  SKIP += 116_bound_setjmp2.test