Add MIPS ASE DSP testcases. Signed-off-by: Jia Liu <proljc@gmail.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
		
			
				
	
	
		
			267 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
typedef unsigned long va_list;
 | 
						|
 | 
						|
#define ACC    4
 | 
						|
#define __read(source)                    \
 | 
						|
({ va_list __res;                    \
 | 
						|
    __asm__ __volatile__(                \
 | 
						|
        "move\t%0, " #source "\n\t"        \
 | 
						|
        : "=r" (__res));            \
 | 
						|
    __res;                        \
 | 
						|
})
 | 
						|
 | 
						|
enum format_type {
 | 
						|
    FORMAT_TYPE_NONE,
 | 
						|
    FORMAT_TYPE_HEX,
 | 
						|
    FORMAT_TYPE_ULONG,
 | 
						|
    FORMAT_TYPE_FLOAT
 | 
						|
};
 | 
						|
 | 
						|
struct printf_spec {
 | 
						|
    char    type;
 | 
						|
};
 | 
						|
 | 
						|
static int format_decode(char *fmt, struct printf_spec *spec)
 | 
						|
{
 | 
						|
    char *start = fmt;
 | 
						|
 | 
						|
    for (; *fmt ; ++fmt) {
 | 
						|
        if (*fmt == '%') {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    switch (*++fmt) {
 | 
						|
    case 'x':
 | 
						|
        spec->type = FORMAT_TYPE_HEX;
 | 
						|
        break;
 | 
						|
 | 
						|
    case 'd':
 | 
						|
        spec->type = FORMAT_TYPE_ULONG;
 | 
						|
        break;
 | 
						|
 | 
						|
    case 'f':
 | 
						|
        spec->type = FORMAT_TYPE_FLOAT;
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        spec->type = FORMAT_TYPE_NONE;
 | 
						|
    }
 | 
						|
 | 
						|
    return ++fmt - start;
 | 
						|
}
 | 
						|
 | 
						|
void *memcpy(void *dest, void *src, int n)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char *s = src;
 | 
						|
    char *d = dest;
 | 
						|
 | 
						|
    for (i = 0; i < n; i++) {
 | 
						|
        d[i] = s[i];
 | 
						|
    }
 | 
						|
    return dest;
 | 
						|
}
 | 
						|
 | 
						|
char *number(char *buf, va_list num)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char *str = buf;
 | 
						|
    static char digits[16] = "0123456789abcdef";
 | 
						|
    str = str + sizeof(num) * 2;
 | 
						|
 | 
						|
    for (i = 0; i < sizeof(num) * 2; i++) {
 | 
						|
        *--str = digits[num & 15];
 | 
						|
        num >>= 4;
 | 
						|
    }
 | 
						|
 | 
						|
    return buf + sizeof(num) * 2;
 | 
						|
}
 | 
						|
 | 
						|
char *__number(char *buf, va_list num)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    va_list mm = num;
 | 
						|
    char *str = buf;
 | 
						|
 | 
						|
    if (!num) {
 | 
						|
        *str++ = '0';
 | 
						|
        return str;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; mm; mm = mm/10, i++) {
 | 
						|
        /* Do nothing. */
 | 
						|
    }
 | 
						|
 | 
						|
    str = str + i;
 | 
						|
 | 
						|
    while (num) {
 | 
						|
        *--str = num % 10 + 48;
 | 
						|
        num = num / 10;
 | 
						|
    }
 | 
						|
 | 
						|
    return str + i;
 | 
						|
}
 | 
						|
 | 
						|
va_list modf(va_list args, va_list *integer, va_list *num)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    double dot_v = 0;
 | 
						|
    va_list E, DOT, DOT_V;
 | 
						|
 | 
						|
    if (!args) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0, args = args << 1 >> 1; i < 52; i++) {
 | 
						|
        if ((args >> i) & 0x1) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    *integer = 0;
 | 
						|
 | 
						|
    if ((args >> 56 != 0x3f) || (args >> 52 == 0x3ff)) {
 | 
						|
        E = (args >> 52) - 1023;
 | 
						|
        DOT = 52 - E - i;
 | 
						|
        DOT_V = args << (12 + E) >> (12 + E) >> i;
 | 
						|
        *integer = ((args << 12 >> 12) >> (i + DOT)) | (1 << E);
 | 
						|
    } else {
 | 
						|
        E = ~((args >> 52) - 1023) + 1;
 | 
						|
        DOT_V = args << 12 >> 12;
 | 
						|
 | 
						|
        dot_v += 1.0 / (1 << E);
 | 
						|
 | 
						|
        for (i = 1; i <= 16; i++) {
 | 
						|
            if ((DOT_V >> (52 - i)) & 0x1) {
 | 
						|
                dot_v += 1.0 / (1 << E + i);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 1, E = 0; i <= ACC; i++) {
 | 
						|
            dot_v *= 10;
 | 
						|
            if (!(va_list)dot_v) {
 | 
						|
                E++;
 | 
						|
            }
 | 
						|
    }
 | 
						|
 | 
						|
    *num = E;
 | 
						|
 | 
						|
    return dot_v;
 | 
						|
    }
 | 
						|
 | 
						|
    if (args & 0xf) {
 | 
						|
        for (i = 1; i <= 16; i++) {
 | 
						|
            if ((DOT_V >> (DOT - i)) & 0x1) {
 | 
						|
                dot_v += 1.0 / (1 << i);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 1, E = 0; i <= ACC; i++) {
 | 
						|
            dot_v *= 10;
 | 
						|
            if (!(va_list)dot_v) {
 | 
						|
                E++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        *num = E;
 | 
						|
 | 
						|
        return dot_v;
 | 
						|
    } else if (DOT) {
 | 
						|
        for (i = 1; i <= DOT; i++) {
 | 
						|
            if ((DOT_V >> (DOT - i)) & 0x1) {
 | 
						|
                dot_v += 1.0 / (1 << i);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 1; i <= ACC; i++) {
 | 
						|
            dot_v = dot_v * 10;
 | 
						|
        }
 | 
						|
 | 
						|
    return dot_v;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int vsnprintf(char *buf, int size, char *fmt, va_list args)
 | 
						|
{
 | 
						|
    char *str, *mm;
 | 
						|
    struct printf_spec spec = {0};
 | 
						|
 | 
						|
    str = mm = buf;
 | 
						|
 | 
						|
    while (*fmt) {
 | 
						|
        char *old_fmt = fmt;
 | 
						|
        int read = format_decode(fmt, &spec);
 | 
						|
 | 
						|
        fmt += read;
 | 
						|
 | 
						|
        switch (spec.type) {
 | 
						|
        case FORMAT_TYPE_NONE: {
 | 
						|
            memcpy(str, old_fmt, read);
 | 
						|
            str += read;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        case FORMAT_TYPE_HEX: {
 | 
						|
            memcpy(str, old_fmt, read);
 | 
						|
            str = number(str + read, args);
 | 
						|
            for (; *mm ; ++mm) {
 | 
						|
                if (*mm == '%') {
 | 
						|
                    *mm = '0';
 | 
						|
                break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        break;
 | 
						|
        }
 | 
						|
        case FORMAT_TYPE_ULONG: {
 | 
						|
            memcpy(str, old_fmt, read - 2);
 | 
						|
            str = __number(str + read - 2, args);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        case FORMAT_TYPE_FLOAT: {
 | 
						|
            va_list integer, dot_v, num;
 | 
						|
            dot_v = modf(args, &integer, &num);
 | 
						|
            memcpy(str, old_fmt, read - 2);
 | 
						|
            str += read - 2;
 | 
						|
            if ((args >> 63 & 0x1)) {
 | 
						|
                *str++ = '-';
 | 
						|
            }
 | 
						|
            str = __number(str, integer);
 | 
						|
            if (dot_v) {
 | 
						|
                *str++ = '.';
 | 
						|
                while (num--) {
 | 
						|
                    *str++ = '0';
 | 
						|
                }
 | 
						|
                str = __number(str, dot_v);
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    *str = '\0';
 | 
						|
 | 
						|
    return str - buf;
 | 
						|
}
 | 
						|
 | 
						|
static void serial_out(char *str)
 | 
						|
{
 | 
						|
    while (*str) {
 | 
						|
        *(char *)0xffffffffb80003f8 = *str++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int vprintf(char *fmt, va_list args)
 | 
						|
{
 | 
						|
    int printed_len = 0;
 | 
						|
    static char printf_buf[512];
 | 
						|
    printed_len = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
 | 
						|
    serial_out(printf_buf);
 | 
						|
    return printed_len;
 | 
						|
}
 | 
						|
 | 
						|
int printf(char *fmt, ...)
 | 
						|
{
 | 
						|
    return vprintf(fmt, __read($5));
 | 
						|
}
 |