nanohub: remove -fshort-double

-fshort-double has been removed from recent gcc versions
and is not supported by clang.

Removed flag
Define a new CHRE_LOG entry point to handle sizeof(double) == 8
and leave the old to handle old chre apps that were compiled with
sizeof(double) == 4.
Add builtins to handle float -> double conversion (using gcc's
caused crashes)
Removed -lgcc from apps (we shouldn't be pulling in any functions from
libgcc.a) and added -nostdlib flag

Bug: 28938849
Test: nanoapps build/chreLog %f works same as before
Change-Id: I72a91dcfdfc2b0eba3211ac719381fcb0a0ae7ed
Signed-off-by: Ben Fennema <fennema@google.com>
diff --git a/firmware/app/app.mk b/firmware/app/app.mk
index 08c1a33..5272b29 100644
--- a/firmware/app/app.mk
+++ b/firmware/app/app.mk
@@ -158,7 +158,6 @@
 
 # Miscellaneous
 CFLAGS += -fno-strict-aliasing
-CFLAGS += -fshort-double
 CFLAGS += -fvisibility=hidden
 CFLAGS += -fno-unwind-tables
 CFLAGS += -fstack-reuse=all
@@ -171,10 +170,10 @@
 
 LDFLAGS := -T $(NANOHUB_DIR)/os/platform/$(PLATFORM)/lkr/app.lkr
 LDFLAGS += -nostartfiles
+LDFLAGS += -nostdlib
 LDFLAGS += -Wl,--gc-sections
 LDFLAGS += -Wl,-Map,$(OUT)/$(BIN).map
 LDFLAGS += -Wl,--cref
-STATIC_LIBS += -lgcc
 ifeq ($(BIN_MODE),static)
 LDFLAGS += -Bstatic
 LDFLAGS += -Wl,--emit-relocs
diff --git a/firmware/build/common_config.mk b/firmware/build/common_config.mk
index 581709e..990db3c 100644
--- a/firmware/build/common_config.mk
+++ b/firmware/build/common_config.mk
@@ -40,6 +40,7 @@
 
 LOCAL_LDFLAGS +=                        \
     -nostartfiles                       \
+    -nostdlib                           \
     -Wl,--gc-sections                   \
     -Wl,--no-undefined                  \
     -Wl,--no-allow-shlib-undefined      \
@@ -52,7 +53,6 @@
     -mfpu=fpv4-sp-d16 \
     -mno-thumb-interwork \
     -ffast-math \
-    -fshort-double \
     -fsingle-precision-constant \
     -DARM \
     -DUSE_NANOHUB_FLOAT_RUNTIME \
diff --git a/firmware/firmware.mk b/firmware/firmware.mk
index ffd06d8..eeda9b1 100644
--- a/firmware/firmware.mk
+++ b/firmware/firmware.mk
@@ -58,7 +58,7 @@
 FLAGS += -I../lib/include
 FLAGS += -I../inc
 
-FLAGS += -Wall -Werror -fshort-double
+FLAGS += -Wall -Werror
 #help avoid commmon embedded C mistakes
 FLAGS += -Wmissing-declarations -Wlogical-op -Waddress -Wempty-body -Wpointer-arith -Wenum-compare -Wdouble-promotion -Wfloat-equal -Wshadow -fno-strict-aliasing
 
diff --git a/firmware/lib/builtins/Android.mk b/firmware/lib/builtins/Android.mk
index c6a1e53..aa8663c 100644
--- a/firmware/lib/builtins/Android.mk
+++ b/firmware/lib/builtins/Android.mk
@@ -29,6 +29,8 @@
     moddi3.c                \
     udivmoddi4.c            \
     umoddi3.c               \
+    aeabi_f2d.c             \
+    aeabi_llsl.c            \
 
 LOCAL_C_INCLUDES = $(LOCAL_PATH)
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
diff --git a/firmware/lib/builtins/aeabi_f2d.c b/firmware/lib/builtins/aeabi_f2d.c
new file mode 100644
index 0000000..b4984d9
--- /dev/null
+++ b/firmware/lib/builtins/aeabi_f2d.c
@@ -0,0 +1,19 @@
+//===-- lib/extendsfdf2.c - single -> double conversion -----------*- C -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+
+#define SRC_SINGLE
+#define DST_DOUBLE
+#include "fp_extend_impl.inc"
+
+double __aeabi_f2d(float a);
+
+double __aeabi_f2d(float a) {
+    return __extendXfYf2__(a);
+}
diff --git a/firmware/lib/builtins/aeabi_llsl.c b/firmware/lib/builtins/aeabi_llsl.c
new file mode 100644
index 0000000..529c0ae
--- /dev/null
+++ b/firmware/lib/builtins/aeabi_llsl.c
@@ -0,0 +1,43 @@
+/* ====-- ashldi3.c - Implement __ashldi3 -----------------------------------===
+ *
+ *                     The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __ashldi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Returns: a << b */
+
+/* Precondition:  0 <= b < bits_in_dword */
+
+di_int __aeabi_llsl(di_int a, si_int b);
+
+di_int
+__aeabi_llsl(di_int a, si_int b)
+{
+    const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
+    dwords input;
+    dwords result;
+    input.all = a;
+    if (b & bits_in_word)  /* bits_in_word <= b < bits_in_dword */
+    {
+        result.s.low = 0;
+        result.s.high = input.s.low << (b - bits_in_word);
+    }
+    else  /* 0 <= b < bits_in_word */
+    {
+        if (b == 0)
+            return a;
+        result.s.low  = input.s.low << b;
+        result.s.high = (input.s.high << b) | (input.s.low >> (bits_in_word - b));
+    }
+    return result.all;
+}
diff --git a/firmware/lib/builtins/fp_extend.h b/firmware/lib/builtins/fp_extend.h
new file mode 100644
index 0000000..bff285a
--- /dev/null
+++ b/firmware/lib/builtins/fp_extend.h
@@ -0,0 +1,89 @@
+//===-lib/fp_extend.h - low precision -> high precision conversion -*- C -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Set source and destination setting
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FP_EXTEND_HEADER
+#define FP_EXTEND_HEADER
+
+#include "int_lib.h"
+
+#if defined SRC_SINGLE
+typedef float src_t;
+typedef su_int src_rep_t;
+#define SRC_REP_C(c) c ## UL
+static const int srcSigBits = 23;
+#define src_rep_t_clz __builtin_clz
+
+#elif defined SRC_DOUBLE
+typedef double src_t;
+typedef du_int src_rep_t;
+#define SRC_REP_C(c) c ## ULL
+static const int srcSigBits = 52;
+static __inline int src_rep_t_clz(src_rep_t a) {
+#if defined __LP64__
+    return __builtin_clzl(a);
+#else
+    if (a & REP_C(0xffffffff00000000))
+        return __builtin_clz(a >> 32);
+    else
+        return 32 + __builtin_clz(a & REP_C(0xffffffff));
+#endif
+}
+
+#elif defined SRC_HALF
+typedef uint16_t src_t;
+typedef uint16_t src_rep_t;
+#define SRC_REP_C UINT16_C
+static const int srcSigBits = 10;
+#define src_rep_t_clz __builtin_clz
+
+#else
+#error Source should be half, single, or double precision!
+#endif //end source precision
+
+#if defined DST_SINGLE
+typedef float dst_t;
+typedef su_int dst_rep_t;
+#define DST_REP_C(c) c ## UL
+static const int dstSigBits = 23;
+
+#elif defined DST_DOUBLE
+typedef double dst_t;
+typedef du_int dst_rep_t;
+#define DST_REP_C(c) c ## ULL
+static const int dstSigBits = 52;
+
+#elif defined DST_QUAD
+typedef long double dst_t;
+typedef __uint128_t dst_rep_t;
+#define DST_REP_C (__uint128_t)
+static const int dstSigBits = 112;
+
+#else
+#error Destination should be single, double, or quad precision!
+#endif //end destination precision
+
+// End of specialization parameters.  Two helper routines for conversion to and
+// from the representation of floating-point data as integer values follow.
+
+static __inline src_rep_t srcToRep(src_t x) {
+    const union { src_t f; src_rep_t i; } rep = {.f = x};
+    return rep.i;
+}
+
+static __inline dst_t dstFromRep(dst_rep_t x) {
+    const union { dst_t f; dst_rep_t i; } rep = {.i = x};
+    return rep.f;
+}
+// End helper routines.  Conversion implementation follows.
+
+#endif //FP_EXTEND_HEADER
diff --git a/firmware/lib/builtins/fp_extend_impl.inc b/firmware/lib/builtins/fp_extend_impl.inc
new file mode 100644
index 0000000..b785cc7
--- /dev/null
+++ b/firmware/lib/builtins/fp_extend_impl.inc
@@ -0,0 +1,108 @@
+//=-lib/fp_extend_impl.inc - low precision -> high precision conversion -*-- -//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a fairly generic conversion from a narrower to a wider
+// IEEE-754 floating-point type.  The constants and types defined following the
+// includes below parameterize the conversion.
+//
+// It does not support types that don't use the usual IEEE-754 interchange
+// formats; specifically, some work would be needed to adapt it to
+// (for example) the Intel 80-bit format or PowerPC double-double format.
+//
+// Note please, however, that this implementation is only intended to support
+// *widening* operations; if you need to convert to a *narrower* floating-point
+// type (e.g. double -> float), then this routine will not do what you want it
+// to.
+//
+// It also requires that integer types at least as large as both formats
+// are available on the target platform; this may pose a problem when trying
+// to add support for quad on some 32-bit systems, for example.  You also may
+// run into trouble finding an appropriate CLZ function for wide source types;
+// you will likely need to roll your own on some platforms.
+//
+// Finally, the following assumptions are made:
+//
+// 1. floating-point types and integer types have the same endianness on the
+//    target platform
+//
+// 2. quiet NaNs, if supported, are indicated by the leading bit of the
+//    significand field being set
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_extend.h"
+
+static __inline dst_t __extendXfYf2__(src_t a) {
+    // Various constants whose values follow from the type parameters.
+    // Any reasonable optimizer will fold and propagate all of these.
+    const int srcBits = sizeof(src_t)*CHAR_BIT;
+    const int srcExpBits = srcBits - srcSigBits - 1;
+    const int srcInfExp = (1 << srcExpBits) - 1;
+    const int srcExpBias = srcInfExp >> 1;
+
+    const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits;
+    const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits;
+    const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits);
+    const src_rep_t srcAbsMask = srcSignMask - 1;
+    const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1);
+    const src_rep_t srcNaNCode = srcQNaN - 1;
+
+    const int dstBits = sizeof(dst_t)*CHAR_BIT;
+    const int dstExpBits = dstBits - dstSigBits - 1;
+    const int dstInfExp = (1 << dstExpBits) - 1;
+    const int dstExpBias = dstInfExp >> 1;
+
+    const dst_rep_t dstMinNormal = DST_REP_C(1) << dstSigBits;
+
+    // Break a into a sign and representation of the absolute value
+    const src_rep_t aRep = srcToRep(a);
+    const src_rep_t aAbs = aRep & srcAbsMask;
+    const src_rep_t sign = aRep & srcSignMask;
+    dst_rep_t absResult;
+
+    // If sizeof(src_rep_t) < sizeof(int), the subtraction result is promoted
+    // to (signed) int.  To avoid that, explicitly cast to src_rep_t.
+    if ((src_rep_t)(aAbs - srcMinNormal) < srcInfinity - srcMinNormal) {
+        // a is a normal number.
+        // Extend to the destination type by shifting the significand and
+        // exponent into the proper position and rebiasing the exponent.
+        absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits);
+        absResult += (dst_rep_t)(dstExpBias - srcExpBias) << dstSigBits;
+    }
+
+    else if (aAbs >= srcInfinity) {
+        // a is NaN or infinity.
+        // Conjure the result by beginning with infinity, then setting the qNaN
+        // bit (if needed) and right-aligning the rest of the trailing NaN
+        // payload field.
+        absResult = (dst_rep_t)dstInfExp << dstSigBits;
+        absResult |= (dst_rep_t)(aAbs & srcQNaN) << (dstSigBits - srcSigBits);
+        absResult |= (dst_rep_t)(aAbs & srcNaNCode) << (dstSigBits - srcSigBits);
+    }
+
+    else if (aAbs) {
+        // a is denormal.
+        // renormalize the significand and clear the leading bit, then insert
+        // the correct adjusted exponent in the destination type.
+        const int scale = src_rep_t_clz(aAbs) - src_rep_t_clz(srcMinNormal);
+        absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits + scale);
+        absResult ^= dstMinNormal;
+        const int resultExponent = dstExpBias - srcExpBias - scale + 1;
+        absResult |= (dst_rep_t)resultExponent << dstSigBits;
+    }
+
+    else {
+        // a is zero.
+        absResult = 0;
+    }
+
+    // Apply the signbit to (dst_t)abs(a).
+    const dst_rep_t result = absResult | (dst_rep_t)sign << (dstBits - srcBits);
+    return dstFromRep(result);
+}
diff --git a/firmware/lib/builtins/int_lib.h b/firmware/lib/builtins/int_lib.h
index 2840710..3d968a8 100644
--- a/firmware/lib/builtins/int_lib.h
+++ b/firmware/lib/builtins/int_lib.h
@@ -19,11 +19,23 @@
 #define CHAR_BIT 8
 
 typedef unsigned su_int;
+typedef int si_int;
+
 typedef unsigned long long du_int;
 typedef long long di_int;
 
 typedef union
 {
+    di_int all;
+    struct
+    {
+        su_int low;
+        si_int high;
+    } s;
+} dwords;
+
+typedef union
+{
     du_int all;
     struct
     {
diff --git a/firmware/lib/lib.mk b/firmware/lib/lib.mk
index e964f16..41d84ee 100644
--- a/firmware/lib/lib.mk
+++ b/firmware/lib/lib.mk
@@ -75,11 +75,13 @@
 
 BUILTINS_PATH := $(NANOHUB_DIR)/lib/builtins
 
-#SRCS += $(BUILTINS_PATH)/aeabi_ldivmod.S
-#SRCS += $(BUILTINS_PATH)/aeabi_uldivmod.S
+SRCS += $(BUILTINS_PATH)/aeabi_ldivmod.S
+SRCS += $(BUILTINS_PATH)/aeabi_uldivmod.S
 SRCS += $(BUILTINS_PATH)/divdi3.c
 SRCS += $(BUILTINS_PATH)/divmoddi4.c
 SRCS += $(BUILTINS_PATH)/moddi3.c
 SRCS += $(BUILTINS_PATH)/udivmoddi4.c
 SRCS += $(BUILTINS_PATH)/umoddi3.c
+SRCS += $(BUILTINS_PATH)/aeabi_f2d.c
+SRCS += $(BUILTINS_PATH)/aeabi_llsl.c
 CFLAGS += -I$(BUILTINS_PATH)
diff --git a/firmware/os/core/nanohub_chre.c b/firmware/os/core/nanohub_chre.c
index 2e156f2..6dd32d6 100644
--- a/firmware/os/core/nanohub_chre.c
+++ b/firmware/os/core/nanohub_chre.c
@@ -30,6 +30,7 @@
 #include <syscall.h>
 #include <timer.h>
 #include <util.h>
+#include <printf.h>
 
 #include <chre.h>
 #include <chreApi.h>
@@ -74,12 +75,26 @@
     va_list innerArgs;
     enum chreLogLevel level = va_arg(args, int /* enums promoted to ints in va_args in C */);
     const static char levels[] = "EWIDV";
-    char clevel = level > CHRE_LOG_DEBUG || level < 0 ? 'V' : levels[level];
+    char clevel = (level > CHRE_LOG_DEBUG || level < 0) ? 'V' : levels[level];
     const char *str = va_arg(args, const char*);
     uintptr_t inner = va_arg(args, uintptr_t);
 
     va_copy(innerArgs, INTEGER_TO_VA_LIST(inner));
-    osLogv(clevel, str, innerArgs);
+    osLogv(clevel, PRINTF_FLAG_CHRE, str, innerArgs);
+    va_end(innerArgs);
+}
+
+static void osChreApiLogLogvOld(uintptr_t *retValP, va_list args)
+{
+    va_list innerArgs;
+    enum chreLogLevel level = va_arg(args, int /* enums promoted to ints in va_args in C */);
+    const static char levels[] = "EWIDV";
+    char clevel = (level > CHRE_LOG_DEBUG || level < 0) ? 'V' : levels[level];
+    const char *str = va_arg(args, const char*);
+    uintptr_t inner = va_arg(args, uintptr_t);
+
+    va_copy(innerArgs, INTEGER_TO_VA_LIST(inner));
+    osLogv(clevel, PRINTF_FLAG_CHRE | PRINTF_FLAG_SHORT_DOUBLE, str, innerArgs);
     va_end(innerArgs);
 }
 
@@ -409,6 +424,7 @@
 static const struct SyscallTable chreMainApiTable = {
     .numEntries = SYSCALL_CHRE_MAIN_API_LAST,
     .entry = {
+        [SYSCALL_CHRE_MAIN_API_LOG_OLD]                 = { .func = osChreApiLogLogvOld },
         [SYSCALL_CHRE_MAIN_API_LOG]                     = { .func = osChreApiLogLogv },
         [SYSCALL_CHRE_MAIN_API_GET_APP_ID]              = { .func = osChreApiGetAppId },
         [SYSCALL_CHRE_MAIN_API_GET_INST_ID]             = { .func = osChreApiGetInstanceId },
diff --git a/firmware/os/core/osApi.c b/firmware/os/core/osApi.c
index c0206b6..1716f09 100644
--- a/firmware/os/core/osApi.c
+++ b/firmware/os/core/osApi.c
@@ -89,7 +89,7 @@
     const char *str = va_arg(args, const char*);
     va_list innerArgs;
     va_copy(innerArgs, INTEGER_TO_VA_LIST(va_arg(args, uintptr_t)));
-    osLogv((char)level, str, innerArgs);
+    osLogv((char)level, 0, str, innerArgs);
     va_end(innerArgs);
 }
 
diff --git a/firmware/os/core/printf.c b/firmware/os/core/printf.c
index 2192653..53e91d4 100644
--- a/firmware/os/core/printf.c
+++ b/firmware/os/core/printf.c
@@ -185,7 +185,7 @@
     return *(*fmtP)++;
 }
 
-uint32_t cvprintf(printf_write_c putc_f, void* userData, const char* fmtStr, va_list vl)
+uint32_t cvprintf(printf_write_c putc_f, uint32_t flags, void* userData, const char* fmtStr, va_list vl)
 {
 
     char c, t;
@@ -404,21 +404,37 @@
 #undef GET_UVAL64
 #undef GET_SVAL64
 
-                case 'f':
-                case 'g':
+                case 'F':
 
-                    if (useLongDouble) {
-                        ldbl = va_arg(vl, long double);
-                        data.number = *(uint64_t *)(&ldbl);
+                    data.flags |= FLAG_CAPS;
+
+                case 'f':
+
+                    if (flags & PRINTF_FLAG_CHRE) {
+                        if (flags & PRINTF_FLAG_SHORT_DOUBLE) {
+                            if (useLongDouble) {
+                                dbl = va_arg(vl, double);
+                                data.number = *(uint64_t *)(&dbl);
+                            } else {
+                                // just grab the 32-bits
+                                data.number = va_arg(vl, uint32_t);
+                            }
+                        } else {
+                            if (useLongDouble) {
+                                ldbl = va_arg(vl, long double);
+                                data.number = *(uint64_t *)(&ldbl);
+                            } else {
+                                dbl = va_arg(vl, double);
+                                data.number = *(uint64_t *)(&dbl);
+                            }
+                        }
+                        data.base = 16;
+                        data.flags |= FLAG_ALT;
+                        data.posChar = '\0';
+                        numPrinted += StrPrvPrintfEx_number(putc_f, &data, &bail);
                     } else {
-                        dbl = va_arg(vl, double);
-                        data.number = *(uint32_t *)(&dbl);
+                        bail = true;
                     }
-                    data.base = 16;
-                    data.flags &= ~FLAG_CAPS;
-                    data.flags |= FLAG_ALT;
-                    data.posChar = '\0';
-                    numPrinted += StrPrvPrintfEx_number(putc_f, &data, &bail);
                     if (bail)
                         goto out;
                     break;
diff --git a/firmware/os/core/seos.c b/firmware/os/core/seos.c
index 55a680c..f220dc3 100644
--- a/firmware/os/core/seos.c
+++ b/firmware/os/core/seos.c
@@ -1360,12 +1360,12 @@
     return false;
 }
 
-void osLogv(char clevel, const char *str, va_list vl)
+void osLogv(char clevel, uint32_t flags, const char *str, va_list vl)
 {
     void *userData = platLogAllocUserData();
 
     platLogPutcharF(userData, clevel);
-    cvprintf(platLogPutcharF, userData, str, vl);
+    cvprintf(platLogPutcharF, flags, userData, str, vl);
 
     platLogFlush(userData);
 }
@@ -1375,7 +1375,7 @@
     va_list vl;
 
     va_start(vl, str);
-    osLogv((char)level, str, vl);
+    osLogv((char)level, 0, str, vl);
     va_end(vl);
 }
 
diff --git a/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c b/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c
index d58a99c..9e10ec4 100644
--- a/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c
+++ b/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c
@@ -4096,7 +4096,7 @@
     uint32_t ret;
 
     va_start(vl, fmtStr);
-    ret = cvprintf(writeF, writeD, fmtStr, vl);
+    ret = cvprintf(writeF, 0, writeD, fmtStr, vl);
     va_end(vl);
 
     return ret;
diff --git a/firmware/os/inc/chreApi.h b/firmware/os/inc/chreApi.h
index ef43429..f494236 100644
--- a/firmware/os/inc/chreApi.h
+++ b/firmware/os/inc/chreApi.h
@@ -40,7 +40,7 @@
 
 #define SYSCALL_CHRE_MAIN_API_GET_APP_ID             0 // (void) -> uint64_t
 #define SYSCALL_CHRE_MAIN_API_GET_INST_ID            1 // (void) -> uint32_t
-#define SYSCALL_CHRE_MAIN_API_LOG                    2 // (enum LogLevel, const char *, uintptr_t) -> void
+#define SYSCALL_CHRE_MAIN_API_LOG_OLD                2 // (enum LogLevel, const char *, uintptr_t) -> void
 #define SYSCALL_CHRE_MAIN_API_GET_TIME               3 // (void) -> uint64_t
 #define SYSCALL_CHRE_MAIN_API_TIMER_SET              4 // (uint64_t, const void *, bool) -> uint32_t
 #define SYSCALL_CHRE_MAIN_API_TIMER_CANCEL           5 // (uint32_t) -> bool
@@ -56,7 +56,8 @@
 #define SYSCALL_CHRE_MAIN_API_GET_OS_API_VERSION    15 //
 #define SYSCALL_CHRE_MAIN_API_GET_OS_VERSION        16 //
 #define SYSCALL_CHRE_MAIN_API_GET_PLATFORM_ID       17 //
-#define SYSCALL_CHRE_MAIN_API_LAST                  18 // always last. holes are allowed, but not immediately before this
+#define SYSCALL_CHRE_MAIN_API_LOG                   18 // (enum LogLevel, const char *, uintptr_t) -> void
+#define SYSCALL_CHRE_MAIN_API_LAST                  19 // always last. holes are allowed, but not immediately before this
 
 //called by os entry point to export the api
 void osChreApiExport(void);
diff --git a/firmware/os/inc/printf.h b/firmware/os/inc/printf.h
index f3c26cd..9d44166 100644
--- a/firmware/os/inc/printf.h
+++ b/firmware/os/inc/printf.h
@@ -25,9 +25,12 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-typedef bool (*printf_write_c)(void* userData, char c);		//callback can return false anytime to abort  printing immediately
+#define PRINTF_FLAG_CHRE            0x00000001
+#define PRINTF_FLAG_SHORT_DOUBLE    0x00000002
 
-uint32_t cvprintf(printf_write_c writeF, void* writeD, const char* fmtStr, va_list vl);
+typedef bool (*printf_write_c)(void* userData, char c);		//callback can return false anytime to abort printing immediately
+
+uint32_t cvprintf(printf_write_c writeF, uint32_t flags, void* writeD, const char* fmtStr, va_list vl);
 
 #ifdef __cplusplus
 }
diff --git a/firmware/os/inc/seos.h b/firmware/os/inc/seos.h
index 5a8c866..f10108a 100644
--- a/firmware/os/inc/seos.h
+++ b/firmware/os/inc/seos.h
@@ -276,7 +276,7 @@
     LOG_DEBUG = 'D',
 };
 
-void osLogv(char clevel, const char *str, va_list vl);
+void osLogv(char clevel, uint32_t flags, const char *str, va_list vl);
 void osLog(enum LogLevel level, const char *str, ...) PRINTF_ATTRIBUTE(2, 3);
 
 #ifndef INTERNAL_APP_INIT
diff --git a/firmware/os/platform/stm32/stm32.mk b/firmware/os/platform/stm32/stm32.mk
index 103ca3d..60c55a9 100644
--- a/firmware/os/platform/stm32/stm32.mk
+++ b/firmware/os/platform/stm32/stm32.mk
@@ -26,7 +26,7 @@
 DELIVERABLES += showsizes
 FLAGS += -I. -fno-unwind-tables -fstack-reuse=all -ffunction-sections -fdata-sections
 FLAGS += -Wl,--gc-sections -nostartfiles
-FLAGS_os += -nostdlib
+FLAGS += -nostdlib
 
 #platform bootloader
 SRCS_bl += os/platform/$(PLATFORM)/bl.c