mips64: Add timer and longjump support

Also correct types.h for mips64 which could never be hit
as _mips was part of the previous ifdef.

Change-Id: Id0435c8fc960c5d25c43129b9d9f1606e39ba8e3
Signed-off-by: Carl Smith <carl.smith@alliedtelesis.co.nz>
diff --git a/src/vppinfra/longjmp.S b/src/vppinfra/longjmp.S
index d4dd4c7..6468dba 100644
--- a/src/vppinfra/longjmp.S
+++ b/src/vppinfra/longjmp.S
@@ -580,6 +580,80 @@
 clib_calljmp:	
 1:	B	.S1     1b
 	
+#elif defined(_mips) && __mips == 64
+
+	.global clib_setjmp
+	.align 8
+	.type clib_setjmp, %function
+clib_setjmp:
+	sd $ra, 0($a0)
+	sd $sp, 8($a0)
+	sd $gp, 16($a0)
+	sd $16, 24($a0)
+	sd $17, 32($a0)
+	sd $18, 40($a0)
+	sd $19, 48($a0)
+	sd $20, 56($a0)
+	sd $21, 64($a0)
+	sd $22, 72($a0)
+	sd $23, 80($a0)
+	sd $30, 88($a0)
+	move $v0, $a1
+	jr $ra
+	nop
+
+	.global clib_longjmp
+	.align 8
+	.type clib_longjmp, @function
+clib_longjmp:
+	move $v0, $a1
+	bne $v0, $0, 1f
+	nop
+	daddu $v0, $v0, 1
+1:
+	ld $ra, 0($a0)
+	ld $sp, 8($a0)
+	ld $gp, 16($a0)
+	ld $16, 24($a0)
+	ld $17, 32($a0)
+	ld $18, 40($a0)
+	ld $19, 48($a0)
+	ld $20, 56($a0)
+	ld $21, 64($a0)
+	ld $22, 72($a0)
+	ld $23, 80($a0)
+	ld $30, 88($a0)
+	jr $ra
+	nop
+
+	.global clib_calljmp
+	.align 8
+	.type clib_calljmp, %function
+clib_calljmp:
+	/* Force 16 byte alignment of the new stack */
+	li $t1, -16
+	and $t0, $a2, $t1
+	/* Save old ra/gp/sp on new stack */
+	daddiu $t0, $t0, (-24)
+	sd $ra, 0($t0)
+	sd $gp, 8($t0)
+	sd $sp, 16($t0)
+	/* Switch stacks */
+	move $sp, $t0
+	/* Away we go */
+	move $t9, $a0
+	move $a0, $a1
+	jalr $t9
+	nop
+	/* Switch back to old ra/gp/sp */
+	move $t0, $sp
+	ld $ra, 0($t0)
+	ld $gp, 8($t0)
+	ld $sp, 16($t0)
+	/* Return to caller */
+	jr $ra
+	nop
+
 #elif defined (__aarch64__)
 /*
    Copyright (c) 2011, 2012 ARM Ltd
diff --git a/src/vppinfra/longjmp.h b/src/vppinfra/longjmp.h
index 8d83203..67c650a 100644
--- a/src/vppinfra/longjmp.h
+++ b/src/vppinfra/longjmp.h
@@ -93,6 +93,8 @@
 
 #elif defined(__aarch64__)
 #define CLIB_ARCH_LONGJMP_REGS (22)
+#elif defined(_mips) && __mips == 64
+#define CLIB_ARCH_LONGJMP_REGS (12)
 #else
 #error "unknown machine"
 #endif
diff --git a/src/vppinfra/time.h b/src/vppinfra/time.h
index 39bc188..ced9677 100644
--- a/src/vppinfra/time.h
+++ b/src/vppinfra/time.h
@@ -174,6 +174,16 @@
   return ((u64) h << 32) | l;
 }
 
+#elif defined(_mips) && __mips == 64
+
+always_inline u64
+clib_cpu_time_now (void)
+{
+  u64 result;
+  asm volatile ("rdhwr %0,$31\n":"=r" (result));
+  return result;
+}
+
 #else
 #error "don't know how to read CPU time stamp"
 
diff --git a/src/vppinfra/types.h b/src/vppinfra/types.h
index 5fd3783..c5e7f09 100644
--- a/src/vppinfra/types.h
+++ b/src/vppinfra/types.h
@@ -64,7 +64,7 @@
 #endif
 #endif
 
-#if (defined(i386) || defined(_mips) || defined(powerpc) || defined (__SPU__) || defined(__sparc__) || defined(__arm__) || defined (__xtensa__) || defined(__TMS320C6X__))
+#if (defined(i386) || (defined(_mips) && __mips != 64) || defined(powerpc) || defined (__SPU__) || defined(__sparc__) || defined(__arm__) || defined (__xtensa__) || defined(__TMS320C6X__))
 typedef signed int i32;
 typedef signed long long i64;
 
@@ -73,16 +73,16 @@
 typedef unsigned long long u64;
 #endif /* CLIB_AVOID_CLASH_WITH_LINUX_TYPES */
 
-#elif defined(_mips) && __mips == 64
-#define log2_uword_bits 6
-#define clib_address_bits _MIPS_SZPTR
-
-#elif defined(alpha) || defined(__x86_64__) || defined (__powerpc64__) || defined (__aarch64__)
+#elif defined(alpha) || (defined(_mips) && __mips == 64) || defined(__x86_64__) || defined (__powerpc64__) || defined (__aarch64__)
 typedef signed int i32;
 typedef signed long i64;
 
 #define log2_uword_bits 6
+#if defined(_mips)
+#define clib_address_bits _MIPS_SZPTR
+#else
 #define clib_address_bits 64
+#endif
 
 #ifndef CLIB_AVOID_CLASH_WITH_LINUX_TYPES
 typedef unsigned int u32;