Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Copy some software code from the original Milkymist SoC.

Libbase should keep its RAM usage to a minimum as it is meant to
be executed before the SDRAM is up and running. (Having lots of
code is OK though as we XIP from the flash)
  • Loading branch information...
commit 1a4a6eb445a51eb8953ba5285ca07be9d70b7572 1 parent b5cb108
Sébastien Bourdeauducq sbourdeauducq authored
Showing with 5,360 additions and 0 deletions.
  1. +45 −0 software/include.mak
  2. +24 −0 software/include/base/assert.h
  3. +35 −0 software/include/base/board.h
  4. +34 −0 software/include/base/console.h
  5. +68 −0 software/include/base/ctype.h
  6. +39 −0 software/include/base/endian.h
  7. +62 −0 software/include/base/irq.h
  8. +25 −0 software/include/base/limits.h
  9. +43 −0 software/include/base/stdarg.h
  10. +29 −0 software/include/base/stdio.h
  11. +55 −0 software/include/base/stdlib.h
  12. +39 −0 software/include/base/string.h
  13. +26 −0 software/include/base/system.h
  14. +29 −0 software/include/base/uart.h
  15. +6 −0 software/include/base/version.h
  16. +31 −0 software/include/extra/blockdev.h
  17. +24 −0 software/include/extra/crc.h
  18. +28 −0 software/include/extra/fatfs.h
  19. +34 −0 software/include/hw/capabilities.h
  20. +27 −0 software/include/hw/common.h
  21. +34 −0 software/include/hw/flash.h
  22. +35 −0 software/include/hw/gpio.h
  23. +23 −0 software/include/hw/interrupts.h
  24. +55 −0 software/include/hw/sysctl.h
  25. +39 −0 software/include/hw/uart.h
  26. +15 −0 software/libbase/Makefile
  27. +84 −0 software/libbase/atof.c
  28. +87 −0 software/libbase/board.c
  29. +108 −0 software/libbase/console.c
  30. +53 −0 software/libbase/divsi3.c
  31. +577 −0 software/libbase/libc.c
  32. +126 −0 software/libbase/milieu.h
  33. +125 −0 software/libbase/softfloat-glue.c
  34. +646 −0 software/libbase/softfloat-macros.h
  35. +125 −0 software/libbase/softfloat-specialize.h
  36. +1,030 −0 software/libbase/softfloat.c
  37. +119 −0 software/libbase/softfloat.h
  38. +82 −0 software/libbase/system.c
  39. +125 −0 software/libbase/uart.c
  40. +328 −0 software/libbase/vsnprintf.c
  41. +273 −0 software/libextra/blockdev.c
  42. +47 −0 software/libextra/crc16.c
  43. +81 −0 software/libextra/crc32.c
  44. +440 −0 software/libextra/fatfs.c
45 software/include.mak
View
@@ -0,0 +1,45 @@
+# Mico32 toolchain
+#
+CROSS_COMPILER=lm32-rtems4.11-
+
+CC_normal := $(CROSS_COMPILER)gcc
+AR_normal := $(CROSS_COMPILER)ar
+AS_normal := $(CROSS_COMPILER)as
+LD_normal := $(CROSS_COMPILER)ld
+OBJCOPY_normal := $(CROSS_COMPILER)objcopy
+RANLIB_normal := $(CROSS_COMPILER)ranlib
+
+CC_quiet = @echo " CC " $@ && $(CROSS_COMPILER)gcc
+AR_quiet = @echo " AR " $@ && $(CROSS_COMPILER)ar
+AS_quiet = @echo " AS " $@ && $(CROSS_COMPILER)as
+LD_quiet = @echo " LD " $@ && $(CROSS_COMPILER)ld
+OBJCOPY_quiet = @echo " OBJCOPY " $@ && $(CROSS_COMPILER)objcopy
+RANLIB_quiet = @echo " RANLIB " $@ && $(CROSS_COMPILER)ranlib
+
+ifeq ($(V),1)
+ CC = $(CC_normal)
+ AR = $(AR_normal)
+ AS = $(AS_normal)
+ LD = $(LD_normal)
+ OBJCOPY = $(OBJCOPY_normal)
+ RANLIB = $(RANLIB_normal)
+else
+ CC = $(CC_quiet)
+ AR = $(AR_quiet)
+ AS = $(AS_quiet)
+ LD = $(LD_quiet)
+ OBJCOPY = $(OBJCOPY_quiet)
+ RANLIB = $(RANLIB_quiet)
+endif
+
+# Toolchain options
+#
+INCLUDES_NOLIBC ?= -nostdinc -I$(MMDIR)/software/include/base
+INCLUDES = $(INCLUDES_NOLIBC) -I$(MMDIR)/software/include -I$(MMDIR)/tools
+ASFLAGS = $(INCLUDES) -nostdinc
+# later: -Wmissing-prototypes
+CFLAGS = -O9 -Wall -Wstrict-prototypes -Wold-style-definition -Wshadow \
+ -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled \
+ -msign-extend-enabled -fno-builtin -fsigned-char \
+ -fsingle-precision-constant $(INCLUDES)
+LDFLAGS = -nostdlib -nodefaultlibs
24 software/include/base/assert.h
View
@@ -0,0 +1,24 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ * Copyright (C) Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASSERT_H
+#define __ASSERT_H
+
+#define assert(x)
+
+#endif /* __ASSERT_H */
35 software/include/base/board.h
View
@@ -0,0 +1,35 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BOARD_H
+#define __BOARD_H
+
+#define BOARD_NAME_LEN 32
+
+struct board_desc {
+ unsigned short int id;
+ char name[BOARD_NAME_LEN];
+ unsigned int ethernet_phyadr;
+};
+
+const struct board_desc *get_board_desc_id(unsigned short int id);
+const struct board_desc *get_board_desc(void);
+int get_pcb_revision(void);
+void get_soc_version(unsigned int *major, unsigned int *minor, unsigned int *subminor, unsigned int *rc);
+void get_soc_version_formatted(char *version);
+
+#endif /* __BOARD_H */
34 software/include/base/console.h
View
@@ -0,0 +1,34 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CONSOLE_H
+#define __CONSOLE_H
+
+typedef void (*console_write_hook)(char);
+typedef char (*console_read_hook)(void);
+typedef int (*console_read_nonblock_hook)(void);
+
+void console_set_write_hook(console_write_hook h);
+void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn);
+
+char readchar(void);
+int readchar_nonblock(void);
+
+int puts(const char *s);
+void putsnonl(const char *s);
+
+#endif /* __CONSOLE_H */
68 software/include/base/ctype.h
View
@@ -0,0 +1,68 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CTYPE_H
+#define __CTYPE_H
+
+static inline int isdigit(char c)
+{
+ return (c >= '0') && (c <= '9');
+}
+
+static inline int isxdigit(char c)
+{
+ return isdigit(c) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F'));
+}
+
+static inline int isupper(char c)
+{
+ return (c >= 'A') && (c <= 'Z');
+}
+
+static inline int islower(char c)
+{
+ return (c >= 'a') && (c <= 'z');
+}
+
+static inline unsigned char tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+static inline char isspace(unsigned char c)
+{
+ if(c == ' '
+ || c == '\f'
+ || c == '\n'
+ || c == '\r'
+ || c == '\t'
+ || c == '\v')
+ return 1;
+
+ return 0;
+}
+
+#endif /* __CTYPE_H */
39 software/include/base/endian.h
View
@@ -0,0 +1,39 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ENDIAN_H
+#define __ENDIAN_H
+
+#define __LITTLE_ENDIAN 0
+#define __BIG_ENDIAN 1
+#define __BYTE_ORDER __BIG_ENDIAN
+
+static inline unsigned int le32toh(unsigned int val)
+{
+ return (val & 0xff) << 24 |
+ (val & 0xff00) << 8 |
+ (val & 0xff0000) >> 8 |
+ (val & 0xff000000) >> 24;
+}
+
+static inline unsigned short le16toh(unsigned short val)
+{
+ return (val & 0xff) << 8 |
+ (val & 0xff00) >> 8;
+}
+
+#endif /* __ENDIAN_H */
62 software/include/base/irq.h
View
@@ -0,0 +1,62 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+static inline void irq_enable(unsigned int en)
+{
+ __asm__ __volatile__("wcsr IE, %0" : : "r" (en));
+}
+
+static inline unsigned int irq_getmask(void)
+{
+ unsigned int mask;
+ __asm__ __volatile__("rcsr %0, IM" : "=r" (mask));
+ return mask;
+}
+
+static inline void irq_setmask(unsigned int mask)
+{
+ __asm__ __volatile__("wcsr IM, %0" : : "r" (mask));
+}
+
+static inline unsigned int irq_pending(void)
+{
+ unsigned int pending;
+ __asm__ __volatile__("rcsr %0, IP" : "=r" (pending));
+ return pending;
+}
+
+static inline void irq_ack(unsigned int mask)
+{
+ __asm__ __volatile__("wcsr IP, %0" : : "r" (mask));
+}
+
+static inline unsigned int irq_getie(void)
+{
+ unsigned int ie;
+ __asm__ __volatile__("rcsr %0, IE" : "=r" (ie));
+ return ie;
+}
+
+static inline void irq_setie(unsigned int ie)
+{
+ __asm__ __volatile__("wcsr IE, %0" : : "r" (ie));
+}
+
+#endif /* __IRQ_H */
25 software/include/base/limits.h
View
@@ -0,0 +1,25 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ * Copyright (C) Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIMITS_H
+#define __LIMITS_H
+
+#define INT_MIN ((((unsigned long)-1) >> 1) + 1)
+#define INT_MAX (((unsigned long)-1) >> 1)
+
+#endif /* __LIMITS_H */
43 software/include/base/stdarg.h
View
@@ -0,0 +1,43 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ * Copyright (C) Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __STDARG_H
+#define __STDARG_H
+
+#include <stdlib.h>
+
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))
+#define va_start(v,l) __builtin_va_start((v),l)
+#else
+#define va_start(v,l) __builtin_stdarg_start((v),l)
+#endif
+
+#define va_arg(ap, type) \
+ __builtin_va_arg((ap), type)
+
+#define va_end(ap) \
+ __builtin_va_end(ap)
+
+#define va_list \
+ __builtin_va_list
+
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vsprintf(char *buf, const char *fmt, va_list args);
+
+#endif /* __STDARG_H */
29 software/include/base/stdio.h
View
@@ -0,0 +1,29 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __STDIO_H
+#define __STDIO_H
+
+#include <stdlib.h>
+
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+int scnprintf(char *buf, size_t size, const char *fmt, ...);
+int sprintf(char *buf, const char *fmt, ...);
+
+int printf(const char *fmt, ...);
+
+#endif /* __STDIO_H */
55 software/include/base/stdlib.h
View
@@ -0,0 +1,55 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
+ * Copyright (C) Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __STDLIB_H
+#define __STDLIB_H
+
+#define PRINTF_ZEROPAD 1 /* pad with zero */
+#define PRINTF_SIGN 2 /* unsigned/signed long */
+#define PRINTF_PLUS 4 /* show plus */
+#define PRINTF_SPACE 8 /* space if plus */
+#define PRINTF_LEFT 16 /* left justified */
+#define PRINTF_SPECIAL 32 /* 0x */
+#define PRINTF_LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+typedef int size_t;
+typedef int ptrdiff_t;
+
+#define NULL ((void *)0)
+
+#define likely(x) x
+#define unlikely(x) x
+
+#define abs(x) ((x) > 0 ? (x) : -(x))
+
+unsigned long strtoul(const char *nptr, char **endptr, int base);
+int skip_atoi(const char **s);
+static inline int atoi(const char *nptr) {
+ return strtoul(nptr, NULL, 0);
+}
+static inline long atol(const char *nptr) {
+ return (long)atoi(nptr);
+}
+char *number(char *buf, char *end, unsigned long num, int base, int size, int precision, int type);
+long strtol(const char *nptr, char **endptr, int base);
+float atof(const char *s);
+
+unsigned int rand(void);
+void abort(void);
+
+#endif /* __STDLIB_H */
39 software/include/base/string.h
View
@@ -0,0 +1,39 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ * Copyright (C) Linus Torvalds and Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __STRING_H
+#define __STRING_H
+
+#include <stdlib.h>
+
+char *strchr(const char *s, int c);
+char *strrchr(const char *s, int c);
+char *strnchr(const char *s, size_t count, int c);
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, size_t count);
+int strcmp(const char *cs, const char *ct);
+int strncmp(const char *cs, const char *ct, size_t count);
+size_t strlen(const char *s);
+size_t strnlen(const char *s, size_t count);
+int memcmp(const void *cs, const void *ct, size_t count);
+void *memset(void *s, int c, size_t count);
+void *memcpy(void *to, const void *from, size_t n);
+void *memmove(void *dest, const void *src, size_t count);
+char *strstr(const char *s1, const char *s2);
+
+#endif /* __STRING_H */
26 software/include/base/system.h
View
@@ -0,0 +1,26 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SYSTEM_H
+#define __SYSTEM_H
+
+void flush_cpu_icache(void);
+void flush_cpu_dcache(void);
+__attribute__((noreturn)) void reboot(void);
+__attribute__((noreturn)) void reconf(void);
+
+#endif /* __SYSTEM_H */
29 software/include/base/uart.h
View
@@ -0,0 +1,29 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __UART_H
+#define __UART_H
+
+void uart_init(void);
+void uart_isr(void);
+void uart_sync(void);
+
+void uart_write(char c);
+char uart_read(void);
+int uart_read_nonblock(void);
+
+#endif
6 software/include/base/version.h
View
@@ -0,0 +1,6 @@
+#ifndef __VERSION_H
+#define __VERSION_H
+
+#define VERSION "2.0-X"
+
+#endif /* __VERSION_H */
31 software/include/extra/blockdev.h
View
@@ -0,0 +1,31 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BLOCKDEV_H
+#define __BLOCKDEV_H
+
+enum {
+ BLOCKDEV_MEMORY_CARD
+};
+
+int bd_init(int devnr);
+int bd_readblock(unsigned int block, void *buffer);
+void bd_done(void);
+
+int bd_has_part_table(int devnr);
+
+#endif /* __BLOCKDEV_H */
24 software/include/extra/crc.h
View
@@ -0,0 +1,24 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CRC_H
+#define __CRC_H
+
+unsigned short crc16(const unsigned char *buffer, int len);
+unsigned int crc32(const unsigned char *buffer, unsigned int len);
+
+#endif
28 software/include/extra/fatfs.h
View
@@ -0,0 +1,28 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FATFS_H
+#define __FATFS_H
+
+typedef int (*fatfs_dir_callback)(const char *, const char *, void *);
+
+int fatfs_init(int devnr);
+int fatfs_list_files(fatfs_dir_callback cb, void *param);
+int fatfs_load(const char *filename, char *buffer, int size, int *realsize);
+void fatfs_done(void);
+
+#endif /* __FATFS_H */
34 software/include/hw/capabilities.h
View
@@ -0,0 +1,34 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_CAPABILITIES
+#define __HW_CAPABILITIES
+
+#define CAP_MEMORYCARD (0x00000001)
+#define CAP_AC97 (0x00000002)
+#define CAP_PFPU (0x00000004)
+#define CAP_TMU (0x00000008)
+#define CAP_ETHERNET (0x00000010)
+#define CAP_FMLMETER (0x00000020)
+#define CAP_VIDEOIN (0x00000040)
+#define CAP_MIDI (0x00000080)
+#define CAP_DMX (0x00000100)
+#define CAP_IR (0x00000200)
+#define CAP_USB (0x00000400)
+#define CAP_MEMTEST (0x00000800)
+
+#endif /* __HW_CAPABILITIES */
27 software/include/hw/common.h
View
@@ -0,0 +1,27 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_COMMON_H
+#define __HW_COMMON_H
+
+#ifdef __ASSEMBLER__
+#define MMPTR(x) x
+#else
+#define MMPTR(x) (*((volatile unsigned int *)(x)))
+#endif
+
+#endif
34 software/include/hw/flash.h
View
@@ -0,0 +1,34 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_FLASH_H
+#define __HW_FLASH_H
+
+#define FLASH_OFFSET_STANDBY_BITSTREAM (0x00000000) /* 640k */
+
+#define FLASH_OFFSET_RESCUE_BITSTREAM (0x000A0000) /* 1536k */
+#define FLASH_OFFSET_RESCUE_BIOS (0x00220000) /* 128k */
+#define FLASH_OFFSET_MAC_ADDRESS (0x002200E0) /* within rescue BIOS */
+#define FLASH_OFFSET_RESCUE_SPLASH (0x00240000) /* 640k */
+#define FLASH_OFFSET_RESCUE_APP (0x002E0000) /* 4096k */
+
+#define FLASH_OFFSET_REGULAR_BITSTREAM (0x006E0000) /* 1536k */
+#define FLASH_OFFSET_REGULAR_BIOS (0x00860000) /* 128k */
+#define FLASH_OFFSET_REGULAR_SPLASH (0x00880000) /* 640k */
+#define FLASH_OFFSET_REGULAR_APP (0x00920000) /* remaining space (23424k) */
+
+#endif /* __HW_FLASH_H */
35 software/include/hw/gpio.h
View
@@ -0,0 +1,35 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_GPIO_H
+#define __HW_GPIO_H
+
+/* Inputs */
+#define GPIO_BTN1 (0x00000001)
+#define GPIO_BTN2 (0x00000002)
+#define GPIO_BTN3 (0x00000004)
+
+#define GPIO_PCBREV0 (0x00000008)
+#define GPIO_PCBREV1 (0x00000010)
+#define GPIO_PCBREV2 (0x00000020)
+#define GPIO_PCBREV3 (0x00000040)
+
+/* Outputs */
+#define GPIO_LED1 (0x00000001)
+#define GPIO_LED2 (0x00000002)
+
+#endif /* __HW_GPIO_H */
23 software/include/hw/interrupts.h
View
@@ -0,0 +1,23 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_INTERRUPTS_H
+#define __HW_INTERRUPTS_H
+
+#define IRQ_UART (0x00000001) /* 0 */
+
+#endif /* __HW_INTERRUPTS_H */
55 software/include/hw/sysctl.h
View
@@ -0,0 +1,55 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_SYSCTL_H
+#define __HW_SYSCTL_H
+
+#include <hw/common.h>
+
+#define CSR_GPIO_IN MMPTR(0xe0001000)
+#define CSR_GPIO_OUT MMPTR(0xe0001004)
+#define CSR_GPIO_INTEN MMPTR(0xe0001008)
+
+#define CSR_TIMER0_CONTROL MMPTR(0xe0001010)
+#define CSR_TIMER0_COMPARE MMPTR(0xe0001014)
+#define CSR_TIMER0_COUNTER MMPTR(0xe0001018)
+
+#define CSR_TIMER1_CONTROL MMPTR(0xe0001020)
+#define CSR_TIMER1_COMPARE MMPTR(0xe0001024)
+#define CSR_TIMER1_COUNTER MMPTR(0xe0001028)
+
+#define TIMER_ENABLE (0x01)
+#define TIMER_AUTORESTART (0x02)
+
+#define CSR_ICAP MMPTR(0xe0001040)
+
+#define ICAP_READY (0x01)
+
+#define ICAP_CE (0x10000)
+#define ICAP_WRITE (0x20000)
+
+#define CSR_DBG_SCRATCHPAD MMPTR(0xe0001050)
+#define CSR_DBG_CTRL MMPTR(0xe0001054)
+
+#define DBG_CTRL_GDB_ROM_LOCK (0x01)
+#define DBG_CTRL_BUS_ERR_EN (0x02)
+
+#define CSR_FREQUENCY MMPTR(0xe0001074)
+#define CSR_CAPABILITIES MMPTR(0xe0001078)
+#define CSR_SYSTEM_ID MMPTR(0xe000107c)
+
+#endif /* __HW_SYSCTL_H */
39 software/include/hw/uart.h
View
@@ -0,0 +1,39 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_UART_H
+#define __HW_UART_H
+
+#include <hw/common.h>
+
+#define CSR_UART_RXTX MMPTR(0xe0000000)
+#define CSR_UART_DIVISOR MMPTR(0xe0000004)
+#define CSR_UART_STAT MMPTR(0xe0000008)
+#define CSR_UART_CTRL MMPTR(0xe000000c)
+#define CSR_UART_DEBUG MMPTR(0xe0000010)
+
+#define UART_STAT_THRE (0x1)
+#define UART_STAT_RX_EVT (0x2)
+#define UART_STAT_TX_EVT (0x4)
+
+#define UART_CTRL_RX_INT (0x1)
+#define UART_CTRL_TX_INT (0x2)
+#define UART_CTRL_THRU (0x4)
+
+#define UART_DEBUG_BREAK_EN (0x1)
+
+#endif /* __HW_UART_H */
15 software/libbase/Makefile
View
@@ -0,0 +1,15 @@
+MMDIR=../..
+include $(MMDIR)/software/include.mak
+
+OBJECTS=divsi3.o libc.o console.o system.o board.o uart.o softfloat.o softfloat-glue.o vsnprintf.o atof.o
+
+all: libbase.a
+
+libbase.a: $(OBJECTS)
+ $(AR) clr libbase.a $(OBJECTS)
+ $(RANLIB) libbase.a
+
+.PHONY: clean
+
+clean:
+ rm -f *.o libbase.a .*~ *~ Makefile.bak
84 software/libbase/atof.c
View
@@ -0,0 +1,84 @@
+/* atof.c: converts an ASCII string to float
+
+ Copyright (C) 2003 Jesus Calvino-Fraga, jesusc@ieee.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+float atof(const char * s)
+{
+ float value, fraction;
+ char iexp;
+ char sign;
+
+ //Skip leading blanks
+ while (isspace(*s)) s++;
+
+ //Get the sign
+ if (*s == '-')
+ {
+ sign=1;
+ s++;
+ }
+ else
+ {
+ sign=0;
+ if (*s == '+') s++;
+ }
+
+ //Get the integer part
+ for (value=0.0f; isdigit(*s); s++)
+ {
+ value=10.0f*value+(*s-'0');
+ }
+
+ //Get the fraction
+ if (*s == '.')
+ {
+ s++;
+ for (fraction=0.1f; isdigit(*s); s++)
+ {
+ value+=(*s-'0')*fraction;
+ fraction*=0.1f;
+ }
+ }
+
+ //Finally, the exponent (not very efficient, but enough for now)
+ if (toupper(*s)=='E')
+ {
+ s++;
+ iexp=(char)atoi(s);
+ {
+ while(iexp!=0)
+ {
+ if(iexp<0)
+ {
+ value*=0.1f;
+ iexp++;
+ }
+ else
+ {
+ value*=10.0f;
+ iexp--;
+ }
+ }
+ }
+ }
+
+ if(sign) value*=-1.0f;
+ return (value);
+}
87 software/libbase/board.c
View
@@ -0,0 +1,87 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <hw/sysctl.h>
+#include <hw/gpio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <board.h>
+
+static const struct board_desc boards[1] = {
+ {
+ .id = 0x4D31, /* M1 */
+ .name = "Milkymist One",
+ .ethernet_phyadr = 1
+ },
+};
+
+const struct board_desc *get_board_desc_id(unsigned short int id)
+{
+ unsigned int i;
+
+ for(i=0;i<sizeof(boards)/sizeof(boards[0]);i++)
+ if(boards[i].id == id)
+ return &boards[i];
+ return NULL;
+}
+
+const struct board_desc *get_board_desc(void)
+{
+ return get_board_desc_id(CSR_SYSTEM_ID & 0xffff);
+}
+
+int get_pcb_revision(void)
+{
+ int r;
+ unsigned int io;
+
+ io = CSR_GPIO_IN;
+ r = 0;
+ if(io & GPIO_PCBREV0)
+ r |= 0x1;
+ if(io & GPIO_PCBREV1)
+ r |= 0x2;
+ if(io & GPIO_PCBREV2)
+ r |= 0x4;
+ if(io & GPIO_PCBREV3)
+ r |= 0x8;
+ return r;
+}
+
+void get_soc_version(unsigned int *major, unsigned int *minor, unsigned int *subminor, unsigned int *rc)
+{
+ unsigned int id;
+
+ id = CSR_SYSTEM_ID;
+ *major = (id & 0xf0000000) >> 28;
+ *minor = (id & 0x0f000000) >> 24;
+ *subminor = (id & 0x00f00000) >> 20;
+ *rc = (id & 0x000f0000) >> 16;
+}
+
+void get_soc_version_formatted(char *version)
+{
+ unsigned int major, minor, subminor, rc;
+
+ get_soc_version(&major, &minor, &subminor, &rc);
+
+ version += sprintf(version, "%u.%u", major, minor);
+ if(subminor != 0)
+ version += sprintf(version, ".%u", subminor);
+ if(rc != 0)
+ sprintf(version, "RC%u", rc);
+}
108 software/libbase/console.c
View
@@ -0,0 +1,108 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <uart.h>
+#include <console.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <irq.h>
+#include <hw/interrupts.h>
+
+static console_write_hook write_hook;
+static console_read_hook read_hook;
+static console_read_nonblock_hook read_nonblock_hook;
+
+void console_set_write_hook(console_write_hook h)
+{
+ write_hook = h;
+}
+
+void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn)
+{
+ read_hook = r;
+ read_nonblock_hook = rn;
+}
+
+static void writechar(char c)
+{
+ uart_write(c);
+ if(write_hook != NULL)
+ write_hook(c);
+}
+
+char readchar(void)
+{
+ while(1) {
+ if(uart_read_nonblock())
+ return uart_read();
+ if((read_nonblock_hook != NULL) && read_nonblock_hook())
+ return read_hook();
+ }
+}
+
+int readchar_nonblock(void)
+{
+ return (uart_read_nonblock()
+ || ((read_nonblock_hook != NULL) && read_nonblock_hook()));
+}
+
+int puts(const char *s)
+{
+ unsigned int oldmask;
+
+ oldmask = irq_getmask();
+ irq_setmask(IRQ_UART); // HACK: prevent UART data loss
+
+ while(*s) {
+ writechar(*s);
+ s++;
+ }
+ writechar('\n');
+
+ irq_setmask(oldmask);
+ return 1;
+}
+
+void putsnonl(const char *s)
+{
+ unsigned int oldmask;
+
+ oldmask = irq_getmask();
+ irq_setmask(IRQ_UART); // HACK: prevent UART data loss
+
+ while(*s) {
+ writechar(*s);
+ s++;
+ }
+
+ irq_setmask(oldmask);
+}
+
+int printf(const char *fmt, ...)
+{
+ va_list args;
+ int len;
+ char outbuf[256];
+
+ va_start(args, fmt);
+ len = vscnprintf(outbuf, sizeof(outbuf), fmt, args);
+ va_end(args);
+ outbuf[len] = 0;
+ putsnonl(outbuf);
+
+ return len;
+}
53 software/libbase/divsi3.c
View
@@ -0,0 +1,53 @@
+#define divnorm(num, den, sign) \
+{ \
+ if(num < 0) \
+ { \
+ num = -num; \
+ sign = 1; \
+ } \
+ else \
+ { \
+ sign = 0; \
+ } \
+ \
+ if(den < 0) \
+ { \
+ den = - den; \
+ sign = 1 - sign; \
+ } \
+}
+
+#define exitdiv(sign, res) if (sign) { res = - res;} return res;
+
+long __divsi3 (long numerator, long denominator)
+{
+ int sign;
+ long dividend;
+
+ divnorm(numerator, denominator, sign);
+
+ dividend = (unsigned int)numerator/(unsigned int)denominator;
+ exitdiv(sign, dividend);
+}
+
+long __modsi3 (long numerator, long denominator)
+{
+ int sign;
+ long res;
+
+ if(numerator < 0) {
+ numerator = -numerator;
+ sign = 1;
+ } else
+ sign = 0;
+
+ if(denominator < 0)
+ denominator = -denominator;
+
+ res = (unsigned int)numerator % (unsigned int)denominator;
+
+ if(sign)
+ return -res;
+ else
+ return res;
+}
577 software/libbase/libc.c
View
@@ -0,0 +1,577 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
+ * Copyright (C) Linus Torvalds and Linux kernel developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char *strchr(const char *s, int c)
+{
+ for (; *s != (char)c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *)s;
+}
+
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char *strrchr(const char *s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+
+/**
+ * strnchr - Find a character in a length limited string
+ * @s: The string to be searched
+ * @count: The number of characters to be searched
+ * @c: The character to search for
+ */
+char *strnchr(const char *s, size_t count, int c)
+{
+ for (; count-- && *s != '\0'; ++s)
+ if (*s == (char)c)
+ return (char *)s;
+ return NULL;
+}
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char *strcpy(char *dest, const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * The result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ *
+ * In the case where the length of @src is less than that of
+ * count, the remainder of @dest will be padded with %NUL.
+ *
+ */
+char *strncpy(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ while (count) {
+ if ((*tmp = *src) != 0)
+ src++;
+ tmp++;
+ count--;
+ }
+ return dest;
+}
+
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char *cs, const char *ct)
+{
+ signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+ return __res;
+}
+
+/**
+ * strncmp - Compare two strings using the first characters only
+ * @cs: One string
+ * @ct: Another string
+ * @count: Number of characters
+ */
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+ signed char __res;
+ size_t n;
+
+ n = 0;
+ __res = 0;
+ while (n < count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ n++;
+ }
+ return __res;
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char *s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char *s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ */
+void *memset(void *s, int c, size_t count)
+{
+ char *xs = s;
+
+ while (count--)
+ *xs++ = c;
+ return s;
+}
+
+/**
+ * memcpy - Copies one area of memory to another
+ * @dest: Destination
+ * @src: Source
+ * @n: The size to copy.
+ */
+void *memcpy(void *to, const void *from, size_t n)
+{
+ void *xto = to;
+ size_t temp;
+
+ if(!n)
+ return xto;
+ if((long)to & 1) {
+ char *cto = to;
+ const char *cfrom = from;
+ *cto++ = *cfrom++;
+ to = cto;
+ from = cfrom;
+ n--;
+ }
+ if(n > 2 && (long)to & 2) {
+ short *sto = to;
+ const short *sfrom = from;
+ *sto++ = *sfrom++;
+ to = sto;
+ from = sfrom;
+ n -= 2;
+ }
+ temp = n >> 2;
+ if(temp) {
+ long *lto = to;
+ const long *lfrom = from;
+ for(; temp; temp--)
+ *lto++ = *lfrom++;
+ to = lto;
+ from = lfrom;
+ }
+ if(n & 2) {
+ short *sto = to;
+ const short *sfrom = from;
+ *sto++ = *sfrom++;
+ to = sto;
+ from = sfrom;
+ }
+ if(n & 1) {
+ char *cto = to;
+ const char *cfrom = from;
+ *cto = *cfrom;
+ }
+ return xto;
+}
+
+/**
+ * memmove - Copies one area of memory to another, overlap possible
+ * @dest: Destination
+ * @src: Source
+ * @n: The size to copy.
+ */
+void *memmove(void *dest, const void *src, size_t count)
+{
+ char *tmp, *s;
+
+ if(dest <= src) {
+ tmp = (char *) dest;
+ s = (char *) src;
+ while(count--)
+ *tmp++ = *s++;
+ } else {
+ tmp = (char *)dest + count;
+ s = (char *)src + count;
+ while(count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char *strstr(const char *s1, const char *s2)
+{
+ size_t l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *)s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+
+/**
+ * strtoul - convert a string to an unsigned long
+ * @nptr: The start of the string
+ * @endptr: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*nptr == '0') {
+ base = 8;
+ nptr++;
+ if ((toupper(*nptr) == 'X') && isxdigit(nptr[1])) {
+ nptr++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (nptr[0] == '0' && toupper(nptr[1]) == 'X')
+ nptr += 2;
+ }
+ while (isxdigit(*nptr) &&
+ (value = isdigit(*nptr) ? *nptr-'0' : toupper(*nptr)-'A'+10) < base) {
+ result = result*base + value;
+ nptr++;
+ }
+ if (endptr)
+ *endptr = (char *)nptr;
+ return result;
+}
+
+/**
+ * strtol - convert a string to a signed long
+ * @nptr: The start of the string
+ * @endptr: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long strtol(const char *nptr, char **endptr, int base)
+{
+ if(*nptr=='-')
+ return -strtoul(nptr+1,endptr,base);
+ return strtoul(nptr,endptr,base);
+}
+
+int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+char *number(char *buf, char *end, unsigned long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits;
+ static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & PRINTF_LARGE) ? large_digits : small_digits;
+ if (type & PRINTF_LEFT)
+ type &= ~PRINTF_ZEROPAD;
+ if (base < 2 || base > 36)
+ return NULL;
+ c = (type & PRINTF_ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & PRINTF_SIGN) {
+ if ((signed long) num < 0) {
+ sign = '-';
+ num = - (signed long) num;
+ size--;
+ } else if (type & PRINTF_PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & PRINTF_SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & PRINTF_SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0) {
+ tmp[i++] = digits[num % base];
+ num = num / base;
+ }
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(PRINTF_ZEROPAD+PRINTF_LEFT))) {
+ while(size-->0) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf < end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & PRINTF_SPECIAL) {
+ if (base==8) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ if (buf < end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & PRINTF_LEFT)) {
+ while (size-- > 0) {
+ if (buf < end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf < end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+ * vscnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which have been written into
+ * the @buf not including the trailing '\0'. If @size is <= 0 the function
+ * returns 0.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want scnprintf() instead.
+ */
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int i;
+
+ i=vsnprintf(buf,size,fmt,args);
+ return (i >= size) ? (size - 1) : i;
+}
+
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing null,
+ * as per ISO C99. If the return is greater than or equal to
+ * @size, the resulting string is truncated.
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * scnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters written into @buf not including
+ * the trailing '\0'. If @size is <= 0 the function returns 0.
+ */
+
+int scnprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, size, fmt, args);
+ va_end(args);
+ return (i >= size) ? (size - 1) : i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
+ * buffer overflows.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf() instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, INT_MAX, fmt, args);
+}
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf. Use snprintf() or scnprintf() in order to avoid
+ * buffer overflows.
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf, INT_MAX, fmt, args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * rand - Returns a pseudo random number
+ */
+
+static unsigned int seed;
+unsigned int rand(void)
+{
+ seed = 129 * seed + 907633385;
+ return seed;
+}
+
+void abort(void)
+{
+ printf("Aborted.");
+ while(1);
+}
126 software/libbase/milieu.h
View
@@ -0,0 +1,126 @@
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://http.cs.berkeley.edu/~jhauser/
+arithmetic/softfloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these three paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+#define BIGENDIAN
+
+/*
+-------------------------------------------------------------------------------
+The macro `BITS64' can be defined to indicate that 64-bit integer types are
+supported by the compiler.
+-------------------------------------------------------------------------------
+*/
+//#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified. For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits. The `flag' type must be able to hold either a 0 or 1. For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef int uint8;
+typedef int int8;
+typedef int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef unsigned long long int bits64;
+typedef signed long long int sbits64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified. For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned char bits8;
+typedef signed char sbits8;
+typedef unsigned short int bits16;
+typedef signed short int sbits16;
+typedef unsigned int bits32;
+typedef signed int sbits32;
+#ifdef BITS64
+typedef unsigned long long int uint64;
+typedef signed long long int int64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and if
+necessary ``marks'' the literal as having a 64-bit integer type. For
+example, the Gnu C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+defined as the identity macro: `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined. If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE extern inline
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
+
125 software/libbase/softfloat-glue.c
View
@@ -0,0 +1,125 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "softfloat.h"
+
+/*
+ * 'Equal' wrapper. This returns 0 if the numbers are equal, or (1 | -1)
+ * otherwise. So we need to invert the output.
+ */
+int __eqsf2(float32 a, float32 b)
+{
+ return !float32_eq(a, b);
+}
+
+/*
+ * 'Not Equal' wrapper. This returns -1 or 1 (say, 1!) if the numbers are
+ * not equal, 0 otherwise. However no not equal call is provided, so we have
+ * to use an 'equal' call and invert the result. The result is already
+ * inverted though! Confusing?!
+ */
+int __nesf2(float32 a, float32 b)
+{
+ return !float32_eq(a, b);
+}
+
+/*
+ * 'Greater Than' wrapper. This returns 1 if the number is greater, 0
+ * or -1 otherwise. Unfortunately, no such function exists. We have to
+ * instead compare the numbers using the 'less than' calls in order to
+ * make up our mind. This means that we can call 'less than or equal' and
+ * invert the result.
+ */
+int __gtsf2(float32 a, float32 b)
+{
+ return !float32_le(a, b);
+}
+
+/*
+ * 'Greater Than or Equal' wrapper. We emulate this by inverting the result
+ * of a 'less than' call.
+ */
+int __gesf2(float32 a, float32 b)
+{
+ return !float32_lt(a, b);
+}
+
+/*
+ * 'Less Than' wrapper.
+ */
+int __ltsf2(float32 a, float32 b)
+{
+ return float32_lt(a, b);
+}
+
+/*
+ * 'Less Than or Equal' wrapper. A 0 must turn into a 1, and a 1 into a 0.
+ */
+int __lesf2(float32 a, float32 b)
+{
+ return !float32_le(a, b);
+}
+
+/*
+ * Float negate... This isn't provided by the library, but it's hardly the
+ * hardest function in the world to write... :) In fact, because of the
+ * position in the registers of arguments, the double precision version can
+ * go here too ;-)
+ */
+float32 __negsf2(float32 x)
+{
+ return x ^ 0x80000000;
+}
+
+/*
+ * 32-bit operations.
+ */
+float32 __addsf3(float32 a, float32 b)
+{
+ return float32_add(a, b);
+}
+
+float32 __subsf3(float32 a, float32 b)
+{
+ return float32_sub(a, b);
+}
+
+float32 __mulsf3(float32 a, float32 b)
+{
+ return float32_mul(a, b);
+}
+
+float32 __divsf3(float32 a, float32 b)
+{
+ return float32_div(a, b);
+}
+
+float32 __floatsisf(int x)
+{
+ return int32_to_float32(x);
+}
+
+int __fixsfsi(float32 x)
+{
+ return float32_to_int32_round_to_zero(x);
+}
+
+unsigned int __fixunssfsi(float32 x)
+{
+ return float32_to_int32_round_to_zero(x); // XXX
+}
+
646 software/libbase/softfloat-macros.h
View
@@ -0,0 +1,646 @@
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/softfloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these three paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'. If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1. The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 32, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
+{
+ bits32 z;
+
+ if ( count == 0 ) {
+ z = a;
+ }
+ else if ( count < 32 ) {
+ z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
+ }
+ else {
+ z = ( a != 0 );
+ }
+ *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' can be arbitrarily large; in particular, if `count' is greater
+than 64, the result will be 0. The result is broken into two 32-bit pieces
+which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64Right(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z0, z1;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 32 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ z1 = ( count < 64 ) ? ( a0>>( count & 31 ) ) : 0;
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. If any nonzero bits are shifted off, they
+are ``jammed'' into the least significant bit of the result by setting the
+least significant bit to 1. The value of `count' can be arbitrarily large;
+in particular, if `count' is greater than 64, the result will be either 0
+or 1, depending on whether the concatenation of `a0' and `a1' is zero or
+nonzero. The result is broken into two 32-bit pieces which are stored at
+the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64RightJamming(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z0, z1;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 32 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 32 ) {
+ z1 = a0 | ( a1 != 0 );
+ }
+ else if ( count < 64 ) {
+ z1 = ( a0>>( count & 31 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
+ }
+ else {
+ z1 = ( ( a0 | a1 ) != 0 );
+ }
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
+by 32 _plus_ the number of bits given in `count'. The shifted result is
+at most 64 nonzero bits; these are broken into two 32-bit pieces which are
+stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
+off form a third 32-bit result as follows: The _last_ bit shifted off is
+the most-significant bit of the extra result, and the other 31 bits of the
+extra result are all zero if and only if _all_but_the_last_ bits shifted off
+were all zero. This extra result is stored in the location pointed to by
+`z2Ptr'. The value of `count' can be arbitrarily large.
+ (This routine makes more sense if `a0', `a1', and `a2' are considered
+to form a fixed-point value with binary point between `a1' and `a2'. This
+fixed-point value is shifted right by the number of bits given in `count',
+and the integer part of the result is returned at the locations pointed to
+by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
+corrupted as described above, and is returned at the location pointed to by
+`z2Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64ExtraRightJamming(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ int16 count,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z2 = a2;
+ z1 = a1;
+ z0 = a0;
+ }
+ else {
+ if ( count < 32 ) {
+ z2 = a1<<negCount;
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 32 ) {
+ z2 = a1;
+ z1 = a0;
+ }
+ else {
+ a2 |= a1;
+ if ( count < 64 ) {
+ z2 = a0<<negCount;
+ z1 = a0>>( count & 31 );
+ }
+ else {
+ z2 = ( count == 64 ) ? a0 : ( a0 != 0 );
+ z1 = 0;
+ }
+ }
+ z0 = 0;
+ }
+ z2 |= ( a2 != 0 );
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' must be less than 32. The result is broken into two 32-bit
+pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift64Left(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+
+ *z1Ptr = a1<<count;
+ *z0Ptr =
+ ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 31 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left by
+the number of bits given in `count'. Any bits shifted off are lost. The
+value of `count' must be less than 32. The result is broken into three
+32-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift96Left(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ int16 count,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 negCount;
+
+ z2 = a2<<count;
+ z1 = a1<<count;
+ z0 = a0<<count;
+ if ( 0 < count ) {
+ negCount = ( ( - count ) & 31 );
+ z1 |= a2>>negCount;
+ z0 |= a1>>negCount;
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
+value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
+any carry out is lost. The result is broken into two 32-bit pieces which
+are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add64(
+ bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z1;
+
+ z1 = a1 + b1;
+ *z1Ptr = z1;
+ *z0Ptr = a0 + b0 + ( z1 < a1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
+96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
+modulo 2^96, so any carry out is lost. The result is broken into three
+32-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add96(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ bits32 b0,
+ bits32 b1,
+ bits32 b2,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 carry0, carry1;
+
+ z2 = a2 + b2;
+ carry1 = ( z2 < a2 );
+ z1 = a1 + b1;
+ carry0 = ( z1 < a1 );
+ z0 = a0 + b0;
+ z1 += carry1;
+ z0 += ( z1 < carry1 );
+ z0 += carry0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
+64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
+2^64, so any borrow out (carry out) is lost. The result is broken into two
+32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
+`z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub64(
+ bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+
+ *z1Ptr = a1 - b1;
+ *z0Ptr = a0 - b0 - ( a1 < b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
+the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
+is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
+into three 32-bit pieces which are stored at the locations pointed to by
+`z0Ptr', `z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub96(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ bits32 b0,
+ bits32 b1,
+ bits32 b2,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 borrow0, borrow1;
+
+ z2 = a2 - b2;
+ borrow1 = ( a2 < b2 );
+ z1 = a1 - b1;
+ borrow0 = ( a1 < b1 );
+ z0 = a0 - b0;
+ z0 -= ( z1 < borrow1 );
+ z1 -= borrow1;
+ z0 -= borrow0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
+into two 32-bit pieces which are stored at the locations pointed to by
+`z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void mul32To64( bits32 a, bits32 b, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits16 aHigh, aLow, bHigh, bLow;
+ bits32 z0, zMiddleA, zMiddleB, z1;
+
+ aLow = a;
+ aHigh = a>>16;
+ bLow = b;
+ bHigh = b>>16;
+ z1 = ( (bits32) aLow ) * bLow;
+ zMiddleA = ( (bits32) aLow ) * bHigh;
+ zMiddleB = ( (bits32) aHigh ) * bLow;
+ z0 = ( (bits32) aHigh ) * bHigh;
+ zMiddleA += zMiddleB;
+ z0 += ( ( (bits32) ( zMiddleA < zMiddleB ) )<<16 ) + ( zMiddleA>>16 );
+ zMiddleA <<= 16;
+ z1 += zMiddleA;
+ z0 += ( z1 < zMiddleA );
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b' to
+obtain a 96-bit product. The product is broken into three 32-bit pieces
+which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
+`z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul64By32To96(
+ bits32 a0,
+ bits32 a1,
+ bits32 b,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2, more1;
+
+ mul32To64( a1, b, &z1, &z2 );
+ mul32To64( a0, b, &z0, &more1 );
+ add64( z0, more1, 0, z1, &z0, &z1 );
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
+64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
+product. The product is broken into four 32-bit pieces which are stored at
+the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul64To128(
+ bits32 a0,
+ bits32 a1,
+ bits32 b0,
+ bits32 b1,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr,
+ bits32 *z3Ptr
+ )
+{
+ bits32 z0, z1, z2, z3;
+ bits32 more1, more2;
+
+ mul32To64( a1, b1, &z2, &z3 );
+ mul32To64( a1, b0, &z1, &more2 );
+ add64( z1, more2, 0, z2, &z1, &z2 );
+ mul32To64( a0, b0, &z0, &more1 );
+ add64( z0, more1, 0, z1, &z0, &z1 );
+ mul32To64( a0, b1, &more1, &more2 );
+ add64( more1, more2, 0, z2, &more1, &z2 );
+ add64( z0, z1, 0, more1, &z0, &z1 );
+ *z3Ptr = z3;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the 32-bit integer quotient obtained by dividing
+`b' into the 64-bit value formed by concatenating `a0' and `a1'. The divisor
+`b' must be at least 2^31. If q is the exact quotient truncated toward
+zero, the approximation returned lies between q and q + 2 inclusive. If
+the exact quotient q is larger than 32 bits, the maximum positive 32-bit
+unsigned integer is returned.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateDiv64To32( bits32 a0, bits32 a1, bits32 b )
+{
+ bits32 b0, b1;
+ bits32 rem0, rem1, term0, term1;
+ bits32 z;
+
+ if ( b <= a0 ) return 0xFFFFFFFF;
+ b0 = b>>16;
+ z = ( b0<<16 <= a0 ) ? 0xFFFF0000 : ( a0 / b0 )<<16;
+ mul32To64( b, z, &term0, &term1 );
+ sub64( a0, a1, term0, term1, &rem0, &rem1 );
+ while ( ( (sbits32) rem0 ) < 0 ) {
+ z -= 0x10000;
+ b1 = b<<16;
+ add64( rem0, rem1, b0, b1, &rem0, &rem1 );
+ }
+ rem0 = ( rem0<<16 ) | ( rem1>>16 );
+ z |= ( b0<<16 <= rem0 ) ? 0xFFFF : rem0 / b0;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the square root of the 32-bit significand given
+by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
+`aExp' (the least significant bit) is 1, the integer returned approximates
+2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
+is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
+case, the approximation returned lies strictly within +/-2 of the exact
+value.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateSqrt32( int16 aExp, bits32 a )
+{
+ static const bits16 sqrtOddAdjustments[] = {
+ 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,