python-on-a-chip online compiler

Dependencies:   mbed TSI

/media/uploads/va009039/p14p-f446re.png

more info: python-on-a-chip

Revision:
0:65f1469d6bfb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/sli.c	Sat Mar 02 11:54:20 2013 +0000
@@ -0,0 +1,442 @@
+/*
+# This file is Copyright 2002 Dean Hall.
+# This file is part of the PyMite VM.
+# This file is licensed under the MIT License.
+# See the LICENSE file for details.
+*/
+
+
+#undef __FILE_ID__
+#define __FILE_ID__ 0x11
+
+
+/**
+ * \file
+ * \brief Standard Library Interface
+ *
+ * PyMite requires a few functions from a few different
+ * standard C libraries (memory, string, etc).
+ */
+
+
+#include "pm.h"
+
+
+/** use Duff's Device or simple for-loop for memcpy. */
+#define USE_DUFFS_DEVICE    0
+
+
+#if !HAVE_STRING_H
+
+void *
+sli_memcpy(unsigned char *to, unsigned char const *from, unsigned int n)
+{
+    unsigned char *tobak;
+
+    /* Store init value of to */
+    tobak = to;
+
+#if USE_DUFFS_DEVICE
+    if (n > 0)
+    {
+        switch (n & 0x7)
+            do
+            {
+            case 0:
+                *to++ = *from++;
+            case 7:
+                *to++ = *from++;
+            case 6:
+                *to++ = *from++;
+            case 5:
+                *to++ = *from++;
+            case 4:
+                *to++ = *from++;
+            case 3:
+                *to++ = *from++;
+            case 2:
+                *to++ = *from++;
+            case 1:
+                *to++ = *from++;
+            }
+            while ((n -= 8) > 0);
+    }
+#else
+    for (; n > 0; n--)
+    {
+        *to = *from;
+        from++;
+        to++;
+    }
+#endif /* USE_DUFFS_DEVICE */
+    return tobak;
+}
+
+
+int
+sli_strlen(char const *s)
+{
+    char const *si = s;
+    int len = 0;
+
+    while (*si++)
+    {
+        len++;
+    }
+    return len;
+}
+
+
+int
+sli_strcmp(char const *s1, char const *s2)
+{
+    /* While not at either strings' end and they're same */
+    while ((*s1 != C_NULL) && (*s2 != C_NULL) && (*s1 == *s2))
+    {
+        s1++;
+        s2++;
+    }
+
+    /* Return string difference */
+    return *s1 - *s2;
+}
+
+
+int
+sli_strncmp(char const *s1, char const *s2, unsigned int n)
+{
+    unsigned int i = 0;
+
+    if (n == 0)
+    {
+        return 0;
+    }
+
+    /* Scan n bytes in string */
+    for (i = 0; i < n; i++)
+    {
+        /* If bytes differ, return difference */
+        if (s1[i] != s2[i])
+        {
+            return s1[i] - s2[i];
+        }
+    }
+    return 0;
+}
+
+#endif /* HAVE_STRING_H */
+
+
+/*
+ * This function is moved outside of HAVE_STRING_H because the one in string.h
+ * will not accept a null value for the second arg
+ */
+void
+sli_memset(unsigned char *dest, char const val, unsigned int n)
+{
+    unsigned int i;
+
+    for (i = 0; i < n; i++)
+    {
+        *dest = (unsigned char)val;
+        dest++;
+    }
+}
+
+void
+sli_puts(uint8_t * s)
+{
+    uint8_t *ps = s;
+    uint8_t c;
+
+    c = *ps;
+    ps++;
+    while (c != '\0')
+    {
+        plat_putByte(c);
+        c = *ps;
+        ps++;
+    }
+}
+
+
+PmReturn_t
+sli_ltoa10(int32_t value, uint8_t *buf, uint8_t buflen)
+{
+    int32_t const decimal_places[] = { 1000000000, 100000000, 10000000, 1000000,
+                                       100000, 10000, 1000, 100, 10, 1 };
+    int32_t decimal_place;
+    int32_t number;
+    uint8_t c;
+    uint8_t printed_one = C_FALSE;
+    uint8_t i;
+    uint8_t j;
+    PmReturn_t retval = PM_RET_OK;
+
+    C_ASSERT(buflen >= 12);
+
+    number = value;
+    if (number == 0)
+    {
+        buf[0] = '0';
+        buf[1] = '\0';
+        return retval;
+    }
+
+    /* Special case (can't convert it to positive value) */
+    if (number == -2147483648)
+    {
+        sli_memcpy(buf, (unsigned char *)"-2147483648", 11);
+        return PM_RET_OK;
+    }
+
+    j = 0;
+    if (number < 0)
+    {
+        buf[0] = '-';
+        j++;
+        number = -number;
+    }
+
+    for (i = 0; i < 10; i++)
+    {
+        decimal_place = decimal_places[i];
+        c = '0';
+        while (number >= decimal_place)
+        {
+            number -= decimal_place;
+            c++;
+        }
+        if ((c != '0') || printed_one)
+        {
+            buf[j++] = c;
+            printed_one = C_TRUE;
+        }
+    }
+    buf[j] = '\0';
+
+    return retval;
+}
+
+char const * const hexChars = "0123456789abcdef";
+
+/* MUST show leading zeros because callers don't keep track */
+PmReturn_t
+sli_btoa16(uint8_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase)
+{
+    C_ASSERT(buflen >= 3);
+
+    if (upperCase) upperCase = 'A' - 'a';
+
+    buf[0] = (value >> 4) > 9 
+             ? hexChars[value >> 4] + upperCase
+             : hexChars[value >> 4];
+    buf[1] = (value & 0x0F) > 9
+             ? hexChars[value & 0x0F] + upperCase
+             : hexChars[value & 0x0F];
+    buf[2] = '\0';
+
+    return PM_RET_OK;
+}
+
+
+/* Does NOT show leading zeroes */
+PmReturn_t
+sli_ltoa16(int32_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase)
+{
+    int8_t i;
+    uint8_t j = 0;
+    uint8_t showZero = C_FALSE;
+    uint8_t nibble;
+
+    C_ASSERT(buflen >= 9);
+
+    if (upperCase) upperCase = 'A' - 'a';
+
+    for (i = 28; i >= 0; i -= 4)
+    {
+        nibble = ((value >> i) & 0xF);
+        if ((nibble == 0) && !showZero) continue;
+        buf[j++] = (nibble > 9) 
+                   ? hexChars[nibble] + upperCase
+                   : hexChars[nibble];
+        showZero = C_TRUE;
+    }
+    buf[j] = '\0';
+
+    return PM_RET_OK;
+}
+
+
+PmReturn_t
+sli_ptoa16(intptr_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase)
+{
+    PmReturn_t retval;
+    int8_t i;
+    int8_t j;
+
+    C_ASSERT(buflen >= 2 * sizeof(intptr_t) + 1);
+
+    /* Print the hex value, most significant byte first */
+    for (j = 0, i = 8 * sizeof(intptr_t) - 8; i >= 0; i -= 8, j += 2)
+    {
+        retval = sli_btoa16((value >> i) & 0xFF, &buf[j], buflen - j, upperCase);
+        PM_BREAK_IF_ERROR(retval);
+    }
+
+    return retval;
+}
+
+
+typedef union {
+    int32_t L;
+    float F;
+} LF_t;
+
+
+/* The buf MUST be at least 15 bytes long */
+PmReturn_t
+sli_ftoa(float f, uint8_t *buf, uint8_t buflen)
+{
+    uint32_t mantissa, int_part, frac_part;
+    int16_t exp2;
+    LF_t x;
+    uint8_t *p;
+    int8_t adj = 0;
+    PmReturn_t retval = PM_RET_OK;
+
+    C_ASSERT(buflen >= 15);
+
+    if (f == 0.0)
+    {
+        buf[0] = '0';
+        buf[1] = '.';
+        buf[2] = '0';
+        buf[3] = '\0';
+        return PM_RET_OK;
+    }
+    x.F = f;
+
+    exp2 = (0xFF & (x.L >> 23)) - 127;
+    mantissa = (x.L & 0xFFFFFF) | 0x800000;
+    frac_part = 0;
+    int_part = 0;
+    p = buf;
+
+    /* Adjust large exponents using the approximation: 2**10 == k*10**3 */
+    while (exp2 >= 31)
+    {
+        /* Reduce the binary exponent here (incr the decimal exponent below) */
+        exp2 -=  10;
+        adj++;
+
+        /*
+         * To use the approximation above, the mantissa must be multiplied by k
+         * where k = 1.024 ~= (1 + 12583/(2**19))
+         * Divide first to avoid integer overflow (the mantissa is 24 bits)
+         */
+        mantissa += ((mantissa >> 6) * 12583) >> 13;
+    }
+
+    if (exp2 < -23)
+    {
+        // Unable to handle large negative exponents at this time
+        *p++ = '?';
+        return PM_RET_OK;
+    }
+    else if (exp2 >= 23)
+    {
+        int_part = mantissa << (exp2 - 23);
+    }
+    else if (exp2 >= 0)
+    {
+        int_part = mantissa >> (23 - exp2);
+        frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF;
+    }
+    else /* if (exp2 < 0) */
+    {
+        frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1);
+    }
+
+    if (x.L < 0)
+    {
+        *p++ = '-';
+    }
+
+    if (int_part == 0)
+    {
+        *p++ = '0';
+    }
+    else
+    {
+        retval = sli_ltoa10(int_part, p, buflen - (p - buf));
+        PM_RETURN_IF_ERROR(retval);
+        while (*p) p++;
+    }
+    *p++ = '.';
+
+    if (frac_part == 0)
+    {
+        *p++ = '0';
+    }
+    else
+    {
+        char m, max;
+
+        max = buflen - (p - buf) - 1;
+        if (max > 6)
+        {
+            max = 6;
+        }
+
+        /* Print fractional part */
+        for (m = 0; m < max; m++)
+        {
+            frac_part *= 10;
+            *p++ = '0' + (frac_part >> 24);
+            frac_part &= 0xFFFFFF;
+        }
+
+        /* Remove ending zeroes */
+        //for (--p; p[0] == '0' && p[-1] != '.'; --p);
+        //++p;
+    }
+
+    /*
+     * If the exponent is large (adjustment took place above),
+     * normalize the string to scientific notation
+     */
+    if (adj != 0)
+    {
+        uint8_t i;
+
+        /* Shift chars to make room for the new decimal point */
+        i = (p - buf + 1);
+        i = (i > (buflen - 1)) ? buflen - 1 : i;
+        for (; i > 1; i--)
+        {
+            buf[i] = buf[i-1];
+        }
+
+        /* Find the index of the old decimal point */
+        for (i = 6; (buf[i] != '.') && (i < 15); i++);
+
+        /* Set the new decimal point (normalized) */
+        buf[1] = '.';
+
+        /*
+         * Adjust the decimal exponent (3 decimal places for every 10 bits)
+         * and add the amount for the normalization
+         */
+        p = &buf[8];
+        *p++ = 'e';
+        *p++ = '+';
+        retval = sli_ltoa10(3 * adj + (i - 2), p, buflen - (p - buf));
+        PM_RETURN_IF_ERROR(retval);
+        while (*p) p++;
+    }
+
+    *p = '\0';
+
+    return PM_RET_OK;
+}