new file mode 100644
@@ -0,0 +1,54 @@
+CROSS_COMPILE ?= mips64el-unknown-linux-gnu-
+
+SIM = qemu-system-mips64el
+SIMFLAGS = -nographic -cpu mips64r2-generic -kernel
+
+AS = $(CROSS_COMPILE)as
+LD = $(CROSS_COMPILE)ld
+CC = $(CROSS_COMPILE)gcc
+AR = $(CROSS_COMPILE)ar
+NM = $(CROSS_COMPILE)nm
+STRIP = $(CROSS_COMPILE)strip
+RANLIB = $(CROSS_COMPILE)ranlib
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+
+VECTORS_OBJ ?= ./head.o ./printf.o
+
+HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \
+ -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \
+ -msym32 -DKBUILD_64BIT_SYM32 -I./
+
+CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin \
+ -pipe -march=mips64r2 -mgp64 -mdspr2 -static -Wa,--trap -msym32 \
+ -DKBUILD_64BIT_SYM32 -I./
+
+LDFLAGS = -T./mips_boot.lds -L./
+FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdspr2
+
+TESTCASES = synci.tst
+
+all: build
+
+head.o : head.S
+ $(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0xffffffff80200000" -c $< -o $@
+
+%.o : %.S
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.tst: %.o $(VECTORS_OBJ)
+ $(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@
+
+build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+
+check: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+ @for case in $(TESTCASES); do \
+ echo $(SIM) $(SIMFLAGS) ./$$case; \
+ $(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \
+ done
+
+clean:
+ $(Q)rm -f *.o *.tst *.a
new file mode 100644
@@ -0,0 +1,16 @@
+/*
+ * Startup Code for MIPS64 CPU-core
+ *
+ */
+.text
+.globl _start
+.align 4
+_start:
+ ori $2, $2, 0xffff
+ sll $2, $2, 16
+ ori $2, $2, 0xffff
+ mtc0 $2, $12, 0
+ jal main
+
+end:
+ b end
new file mode 100644
@@ -0,0 +1,22 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+extern int printf(const char *fmt, ...);
+extern unsigned long get_ticks(void);
+
+#define _read(source) \
+({ unsigned long __res; \
+ __asm__ __volatile__( \
+ "mfc0\t%0, " #source "\n\t" \
+ : "=r" (__res)); \
+ __res; \
+})
+
+#define __read(source) \
+({ unsigned long __res; \
+ __asm__ __volatile__( \
+ "move\t%0, " #source "\n\t" \
+ : "=r" (__res)); \
+ __res; \
+})
+
+#endif
new file mode 100644
@@ -0,0 +1,31 @@
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ . = 0xffffffff80100000;
+ . = ALIGN((1 << 13));
+ .text :
+ {
+ *(.text)
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ __init_begin = .;
+ . = ALIGN((1 << 12));
+ .init.text : AT(ADDR(.init.text) - 0)
+ {
+ *(.init.text)
+ }
+ .init.data : AT(ADDR(.init.data) - 0)
+ {
+ *(.init.data)
+ }
+ . = ALIGN((1 << 12));
+ __init_end = .;
+
+ . = ALIGN((1 << 13));
+ .data :
+ {
+ *(.data)
+ }
+}
new file mode 100644
@@ -0,0 +1,266 @@
+
+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));
+}
new file mode 100644
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main()
+{
+ unsigned long addr, tmp, result = 0;
+ unsigned int addi = 0x21ef0001; /* addi $15, $15, 1 */
+
+ __asm
+ ("move %1, $15\n\t"
+ "move $15, $0\n\t"
+ "dla %0, 1f\n\t"
+ "sw %3, 0(%0)\n\t"
+ "synci 0(%0)\n\t"
+ "nop\n\t"
+ "1:\n\t"
+ "nop\n\t"
+ "move %2, $15\n\t"
+ "move $15, %1\n\t"
+ : "+r"(addr), "+r"(tmp), "=r"(result)
+ : "r"(addi)
+ );
+
+ if (result == 0) {
+ printf("test failed, the copied instruction not run.\n");
+ } else if (result == 1) {
+ printf("test passed\n");
+ } else {
+ printf("unhandled\n");
+ }
+
+ return 0;
+}