Browse Source

all: import mips64 and spim64 support from bitbucket.org/cherry9/4c (thanks Cherry Zhang)

David du Colombier 2 years ago
parent
commit
038c5e6f25
100 changed files with 5831 additions and 1295 deletions
  1. 73 0
      mips64/include/ape/float.h
  2. 78 0
      mips64/include/ape/math.h
  3. 20 0
      mips64/include/ape/stdarg.h
  4. 52 0
      mips64/include/ape/ureg.h
  5. 71 0
      mips64/include/u.h
  6. 44 0
      mips64/include/ureg.h
  7. 9 0
      mips64/mkfile
  8. 2 0
      rc/bin/xa
  9. 2 0
      rc/bin/xc
  10. 2 0
      rc/bin/xl
  11. 73 0
      spim64/include/ape/float.h
  12. 78 0
      spim64/include/ape/math.h
  13. 20 0
      spim64/include/ape/stdarg.h
  14. 52 0
      spim64/include/ape/ureg.h
  15. 71 0
      spim64/include/u.h
  16. 44 0
      spim64/include/ureg.h
  17. 9 0
      spim64/mkfile
  18. 222 0
      sys/lib/acid/mips64
  19. 7 3
      sys/lib/acid/syscall
  20. 10 3
      sys/lib/acid/truss
  21. 5 7
      sys/src/cmd/4a/a.h
  22. 9 17
      sys/src/cmd/4a/a.y
  23. 23 12
      sys/src/cmd/4a/lex.c
  24. 1 8
      sys/src/cmd/4a/mkfile
  25. 202 0
      sys/src/cmd/4c/4.out.h
  26. 0 127
      sys/src/cmd/4c/bits.c
  27. 4 2
      sys/src/cmd/4c/cgen.c
  28. 2 0
      sys/src/cmd/4c/enam.c
  29. 19 17
      sys/src/cmd/4c/gc.h
  30. 1570 0
      sys/src/cmd/4c/lex.c
  31. 7 8
      sys/src/cmd/4c/list.c
  32. 77 0
      sys/src/cmd/4c/machcap.c
  33. 1 1
      sys/src/cmd/4c/mkenam
  34. 19 11
      sys/src/cmd/4c/mkfile
  35. 50 4
      sys/src/cmd/4c/peep.c
  36. 7 3
      sys/src/cmd/4c/reg.c
  37. 16 362
      sys/src/cmd/4c/sgen.c
  38. 84 178
      sys/src/cmd/4c/swt.c
  39. 46 29
      sys/src/cmd/4c/txt.c
  40. 368 287
      sys/src/cmd/4l/asm.c
  41. 18 4
      sys/src/cmd/4l/compat.c
  42. 44 23
      sys/src/cmd/4l/l.h
  43. 12 16
      sys/src/cmd/4l/list.c
  44. 8 11
      sys/src/cmd/4l/mkfile
  45. 8 8
      sys/src/cmd/4l/noop.c
  46. 251 83
      sys/src/cmd/4l/obj.c
  47. 8 1
      sys/src/cmd/4l/optab.c
  48. 19 7
      sys/src/cmd/4l/pass.c
  49. 1 2
      sys/src/cmd/4l/sched.c
  50. 86 18
      sys/src/cmd/4l/span.c
  51. 22 0
      sys/src/libc/9syscall/mkfile
  52. 14 0
      sys/src/libc/mips64/_nsec.c
  53. 14 0
      sys/src/libc/mips64/_seek.c
  54. 4 0
      sys/src/libc/mips64/argv0.s
  55. 52 0
      sys/src/libc/mips64/atom.s
  56. 3 0
      sys/src/libc/mips64/c_fcr0.s
  57. 10 0
      sys/src/libc/mips64/cycles.c
  58. 3 0
      sys/src/libc/mips64/getcallerpc.s
  59. 15 0
      sys/src/libc/mips64/getfcr.s
  60. 25 0
      sys/src/libc/mips64/main9.s
  61. 41 0
      sys/src/libc/mips64/main9p.s
  62. 40 0
      sys/src/libc/mips64/mkfile
  63. 16 0
      sys/src/libc/mips64/notejmp.c
  64. 14 0
      sys/src/libc/mips64/setjmp.s
  65. 103 0
      sys/src/libc/mips64/sqrt.c
  66. 19 0
      sys/src/libc/mips64/tas.s
  67. 14 0
      sys/src/libc/spim64/_nsec.c
  68. 14 0
      sys/src/libc/spim64/_seek.c
  69. 4 0
      sys/src/libc/spim64/argv0.s
  70. 52 0
      sys/src/libc/spim64/atom.s
  71. 3 0
      sys/src/libc/spim64/c_fcr0.s
  72. 10 0
      sys/src/libc/spim64/cycles.c
  73. 3 0
      sys/src/libc/spim64/getcallerpc.s
  74. 15 0
      sys/src/libc/spim64/getfcr.s
  75. 25 0
      sys/src/libc/spim64/main9.s
  76. 41 0
      sys/src/libc/spim64/main9p.s
  77. 20 0
      sys/src/libc/spim64/memccpy.s
  78. 39 0
      sys/src/libc/spim64/memchr.s
  79. 237 0
      sys/src/libc/spim64/memmove.s
  80. 88 0
      sys/src/libc/spim64/memset.s
  81. 40 0
      sys/src/libc/spim64/mkfile
  82. 16 0
      sys/src/libc/spim64/notejmp.c
  83. 14 0
      sys/src/libc/spim64/setjmp.s
  84. 103 0
      sys/src/libc/spim64/sqrt.c
  85. 63 0
      sys/src/libc/spim64/strchr.s
  86. 21 0
      sys/src/libc/spim64/strcmp.s
  87. 92 0
      sys/src/libc/spim64/strcpy.s
  88. 19 0
      sys/src/libc/spim64/tas.s
  89. 118 0
      sys/src/libmach/4.c
  90. 202 0
      sys/src/libmach/4c/4.out.h
  91. 145 0
      sys/src/libmach/4obj.c
  92. 12 11
      sys/src/libmach/executable.c
  93. 4 1
      sys/src/libmach/mkfile
  94. 3 0
      sys/src/libmach/obj.c
  95. 6 6
      sys/src/libmach/setmach.c
  96. 25 25
      sys/src/libmach/vdb.c
  97. 22 0
      sys/src/libmp/mips64/mkfile
  98. 22 0
      sys/src/libmp/spim64/mkfile
  99. 20 0
      sys/src/libsec/mips64/mkfile
  100. 20 0
      sys/src/libsec/spim64/mkfile

+ 73 - 0
mips64/include/ape/float.h

@@ -0,0 +1,73 @@
+#ifndef __FLOAT
+#define __FLOAT
+/* IEEE, default rounding */
+
+#define FLT_ROUNDS	1
+#define FLT_RADIX	2
+
+#define FLT_DIG		6
+#define FLT_EPSILON	1.19209290e-07
+#define FLT_MANT_DIG	24
+#define FLT_MAX		3.40282347e+38
+#define FLT_MAX_10_EXP	38
+#define FLT_MAX_EXP	128
+#define FLT_MIN		1.17549435e-38
+#define FLT_MIN_10_EXP	-37
+#define FLT_MIN_EXP	-125
+
+#define DBL_DIG		15
+#define DBL_EPSILON	2.2204460492503131e-16
+#define DBL_MANT_DIG	53
+#define DBL_MAX		1.797693134862315708145e+308
+#define DBL_MAX_10_EXP	308
+#define DBL_MAX_EXP	1024
+#define DBL_MIN		2.225073858507201383090233e-308
+#define DBL_MIN_10_EXP	-307
+#define DBL_MIN_EXP	-1021
+#define LDBL_MANT_DIG	DBL_MANT_DIG
+#define LDBL_EPSILON	DBL_EPSILON
+#define LDBL_DIG	DBL_DIG
+#define LDBL_MIN_EXP	DBL_MIN_EXP
+#define LDBL_MIN	DBL_MIN
+#define LDBL_MIN_10_EXP	DBL_MIN_10_EXP
+#define LDBL_MAX_EXP	DBL_MAX_EXP
+#define LDBL_MAX	DBL_MAX
+#define LDBL_MAX_10_EXP	DBL_MAX_10_EXP
+
+typedef 	union FPdbleword FPdbleword;
+union FPdbleword
+{
+	double	x;
+	struct {	/* big endian */
+		long hi;
+		long lo;
+	};
+};
+
+#ifdef _RESEARCH_SOURCE
+/* define stuff needed for floating conversion */
+#define IEEE_8087	1
+#define Sudden_Underflow 1
+#endif
+#ifdef _PLAN9_SOURCE
+/* FCR */
+#define	FPINEX	(1<<7)
+#define	FPOVFL	(1<<9)
+#define	FPUNFL	(1<<8)
+#define	FPZDIV	(1<<10)
+#define	FPRNR	(0<<0)
+#define	FPRZ	(1<<0)
+#define	FPRPINF	(2<<0)
+#define	FPRNINF	(3<<0)
+#define	FPRMASK	(3<<0)
+#define	FPPEXT	0
+#define	FPPSGL	0
+#define	FPPDBL	0
+#define	FPPMASK	0
+/* FSR */
+#define	FPAINEX	(1<<2)
+#define	FPAOVFL	(1<<4)
+#define	FPAUNFL	(1<<3)
+#define	FPAZDIV	(1<<5)
+#endif
+#endif /* __FLOAT */

+ 78 - 0
mips64/include/ape/math.h

@@ -0,0 +1,78 @@
+#ifndef __MATH
+#define __MATH
+#pragma lib "/$M/lib/ape/libap.a"
+
+/* a HUGE_VAL appropriate for IEEE double-precision */
+/* the correct value, 1.797693134862316e+308, causes a ken overflow */
+#define HUGE_VAL 1.79769313486231e+308
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern double acos(double);
+extern double asin(double);
+extern double atan(double);
+extern double atan2(double, double);
+extern double cos(double);
+extern double hypot(double, double);
+extern double sin(double);
+extern double tan(double);
+extern double cosh(double);
+extern double sinh(double);
+extern double tanh(double);
+extern double exp(double);
+extern double frexp(double, int *);
+extern double ldexp(double, int);
+extern double log(double);
+extern double log10(double);
+extern double modf(double, double *);
+extern double pow(double, double);
+extern double sqrt(double);
+extern double ceil(double);
+extern double fabs(double);
+extern double floor(double);
+extern double fmod(double, double);
+extern double NaN(void);
+extern int isNaN(double);
+extern double Inf(int);
+extern int isInf(double, int);
+
+#ifdef _RESEARCH_SOURCE
+/* does >> treat left operand as unsigned ? */
+#define Unsigned_Shifts 1
+#define	M_E		2.7182818284590452354	/* e */
+#define	M_LOG2E		1.4426950408889634074	/* log 2e */
+#define	M_LOG10E	0.43429448190325182765	/* log 10e */
+#define	M_LN2		0.69314718055994530942	/* log e2 */
+#define	M_LN10		2.30258509299404568402	/* log e10 */
+#define	M_PI		3.14159265358979323846	/* pi */
+#define	M_PI_2		1.57079632679489661923	/* pi/2 */
+#define	M_PI_4		0.78539816339744830962	/* pi/4 */
+#define	M_1_PI		0.31830988618379067154	/* 1/pi */
+#define	M_2_PI		0.63661977236758134308	/* 2/pi */
+#define	M_2_SQRTPI	1.12837916709551257390	/* 2/sqrt(pi) */
+#define	M_SQRT2		1.41421356237309504880	/* sqrt(2) */
+#define	M_SQRT1_2	0.70710678118654752440	/* 1/sqrt(2) */
+
+extern double hypot(double, double);
+extern double erf(double);
+extern double erfc(double);
+extern double j0(double);
+extern double y0(double);
+extern double j1(double);
+extern double y1(double);
+extern double jn(int, double);
+extern double yn(int, double);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define isnan(x) isNaN(x)
+#define isinf(x) isInf(x, 0)
+
+#endif /* __MATH */

+ 20 - 0
mips64/include/ape/stdarg.h

@@ -0,0 +1,20 @@
+#ifndef __STDARG
+#define __STDARG
+
+typedef char *va_list;
+
+#define va_start(list, start) list =\
+	(sizeof(start) < 8?\
+		(char*)((int*)&(start)+1):\
+		(char*)(&(start)+1))
+#define va_end(list)
+#define va_arg(list, mode)\
+	((sizeof(mode) == 1)?\
+		((list += 8), (mode*)list)[-1]:\
+	(sizeof(mode) == 2)?\
+		((list += 8), (mode*)list)[-1]:\
+	(sizeof(mode) == 4)?\
+		((list += 8), (mode*)list)[-1]:\
+		((list += sizeof(mode)), (mode*)list)[-1])
+
+#endif /* __STDARG */

+ 52 - 0
mips64/include/ape/ureg.h

@@ -0,0 +1,52 @@
+#ifndef __UREG_H
+#define __UREG_H
+#if !defined(_PLAN9_SOURCE)
+    This header file is an extension to ANSI/POSIX
+#endif
+
+struct Ureg
+{
+	unsigned long long	status;
+	unsigned long long	pc;
+	union{
+		unsigned long long	sp;		/* r29 */
+		unsigned long long	usp;		/* r29 */
+	};
+	unsigned long long	cause;
+	unsigned long long	badvaddr;
+	unsigned long long	tlbvirt;
+	unsigned long long	hi;
+	unsigned long long	lo;
+	unsigned long long	r31;
+	unsigned long long	r30;
+	unsigned long long	r28;
+	unsigned long long	r27;		/* unused */
+	unsigned long long	r26;		/* unused */
+	unsigned long long	r25;
+	unsigned long long	r24;
+	unsigned long long	r23;
+	unsigned long long	r22;
+	unsigned long long	r21;
+	unsigned long long	r20;
+	unsigned long long	r19;
+	unsigned long long	r18;
+	unsigned long long	r17;
+	unsigned long long	r16;
+	unsigned long long	r15;
+	unsigned long long	r14;
+	unsigned long long	r13;
+	unsigned long long	r12;
+	unsigned long long	r11;
+	unsigned long long	r10;
+	unsigned long long	r9;
+	unsigned long long	r8;
+	unsigned long long	r7;
+	unsigned long long	r6;
+	unsigned long long	r5;
+	unsigned long long	r4;
+	unsigned long long	r3;
+	unsigned long long	r2;
+	unsigned long long	r1;
+};
+
+#endif

+ 71 - 0
mips64/include/u.h

@@ -0,0 +1,71 @@
+#define nil		((void*)0)
+typedef	unsigned short	ushort;
+typedef	unsigned char	uchar;
+typedef	unsigned long	ulong;
+typedef	unsigned int	uint;
+typedef	signed char	schar;
+typedef	long long	vlong;
+typedef	unsigned long long uvlong;
+typedef unsigned long long uintptr;
+typedef unsigned long	usize;
+typedef	uint		Rune;
+typedef 	union FPdbleword FPdbleword;
+typedef uintptr	jmp_buf[2];
+#define	JMPBUFSP	0
+#define	JMPBUFPC	1
+#define	JMPBUFDPC	0
+typedef unsigned int	mpdigit;	/* for /sys/include/mp.h */
+typedef unsigned char u8int;
+typedef unsigned short u16int;
+typedef unsigned int	u32int;
+typedef unsigned long long u64int;
+
+/* FCR (FCR31) */
+#define	FPINEX	(1<<7)		/* enables */
+#define	FPUNFL	(1<<8)
+#define	FPOVFL	(1<<9)
+#define	FPZDIV	(1<<10)
+#define	FPINVAL	(1<<11)
+#define	FPRNR	(0<<0)		/* rounding modes */
+#define	FPRZ	(1<<0)
+#define	FPRPINF	(2<<0)
+#define	FPRNINF	(3<<0)
+#define	FPRMASK	(3<<0)
+#define	FPPEXT	0
+#define	FPPSGL	0
+#define	FPPDBL	0
+#define	FPPMASK	0
+#define FPCOND	(1<<23)
+
+/* FSR (also FCR31) */
+#define	FPAINEX	(1<<2)		/* flags */
+#define	FPAOVFL	(1<<4)
+#define	FPAUNFL	(1<<3)
+#define	FPAZDIV	(1<<5)
+#define	FPAINVAL (1<<6)
+
+union FPdbleword
+{
+	double	x;
+	struct {	/* big endian */
+		ulong hi;
+		ulong lo;
+	};
+};
+
+/* stdarg */
+typedef	char*	va_list;
+#define va_start(list, start) list =\
+	(sizeof(start) < 8?\
+		(char*)((vlong*)&(start)+1):\
+		(char*)(&(start)+1))
+#define va_end(list)\
+	USED(list)
+#define va_arg(list, mode)\
+	((sizeof(mode) == 1)?\
+		((list += 8), (mode*)list)[-1]:\
+	(sizeof(mode) == 2)?\
+		((list += 8), (mode*)list)[-1]:\
+	(sizeof(mode) == 4)?\
+		((list += 8), (mode*)list)[-1]:\
+		((list += sizeof(mode)), (mode*)list)[-1])

+ 44 - 0
mips64/include/ureg.h

@@ -0,0 +1,44 @@
+struct Ureg
+{
+	u64int	status;
+	u64int	pc;
+	union{
+		u64int	sp;		/* r29 */
+		u64int	usp;		/* r29 */
+	};
+	u64int	cause;
+	u64int	badvaddr;
+	u64int	tlbvirt;
+	u64int	hi;
+	u64int	lo;
+	u64int	r31;
+	u64int	r30;
+	u64int	r28;
+	u64int	r27;		/* unused */
+	u64int	r26;		/* unused */
+	u64int	r25;
+	u64int	r24;
+	u64int	r23;
+	u64int	r22;
+	u64int	r21;
+	u64int	r20;
+	u64int	r19;
+	u64int	r18;
+	u64int	r17;
+	u64int	r16;
+	u64int	r15;
+	u64int	r14;
+	u64int	r13;
+	u64int	r12;
+	u64int	r11;
+	u64int	r10;
+	u64int	r9;
+	u64int	r8;
+	u64int	r7;
+	u64int	r6;
+	u64int	r5;
+	u64int	r4;
+	u64int	r3;
+	u64int	r2;
+	u64int	r1;
+};

+ 9 - 0
mips64/mkfile

@@ -0,0 +1,9 @@
+</sys/src/mkfile.proto
+
+OS=04589qvx
+CPUS=$CPUS mips64
+
+CC=4c
+LD=4l
+O=4
+AS=4a

+ 2 - 0
rc/bin/xa

@@ -0,0 +1,2 @@
+#!/bin/rc
+exec 4a -L $*

+ 2 - 0
rc/bin/xc

@@ -0,0 +1,2 @@
+#!/bin/rc
+exec 4c -l $*

+ 2 - 0
rc/bin/xl

@@ -0,0 +1,2 @@
+#!/bin/rc
+exec 4l -m $*

+ 73 - 0
spim64/include/ape/float.h

@@ -0,0 +1,73 @@
+#ifndef __FLOAT
+#define __FLOAT
+/* IEEE, default rounding */
+
+#define FLT_ROUNDS	1
+#define FLT_RADIX	2
+
+#define FLT_DIG		6
+#define FLT_EPSILON	1.19209290e-07
+#define FLT_MANT_DIG	24
+#define FLT_MAX		3.40282347e+38
+#define FLT_MAX_10_EXP	38
+#define FLT_MAX_EXP	128
+#define FLT_MIN		1.17549435e-38
+#define FLT_MIN_10_EXP	-37
+#define FLT_MIN_EXP	-125
+
+#define DBL_DIG		15
+#define DBL_EPSILON	2.2204460492503131e-16
+#define DBL_MANT_DIG	53
+#define DBL_MAX		1.797693134862315708145e+308
+#define DBL_MAX_10_EXP	308
+#define DBL_MAX_EXP	1024
+#define DBL_MIN		2.225073858507201383090233e-308
+#define DBL_MIN_10_EXP	-307
+#define DBL_MIN_EXP	-1021
+#define LDBL_MANT_DIG	DBL_MANT_DIG
+#define LDBL_EPSILON	DBL_EPSILON
+#define LDBL_DIG	DBL_DIG
+#define LDBL_MIN_EXP	DBL_MIN_EXP
+#define LDBL_MIN	DBL_MIN
+#define LDBL_MIN_10_EXP	DBL_MIN_10_EXP
+#define LDBL_MAX_EXP	DBL_MAX_EXP
+#define LDBL_MAX	DBL_MAX
+#define LDBL_MAX_10_EXP	DBL_MAX_10_EXP
+
+typedef 	union FPdbleword FPdbleword;
+union FPdbleword
+{
+	double	x;
+	struct {	/* little endian */
+		long lo;
+		long hi;
+	};
+};
+
+#ifdef _RESEARCH_SOURCE
+/* define stuff needed for floating conversion */
+#define IEEE_8087	1
+#define Sudden_Underflow 1
+#endif
+#ifdef _PLAN9_SOURCE
+/* FCR */
+#define	FPINEX	(1<<7)
+#define	FPOVFL	(1<<9)
+#define	FPUNFL	(1<<8)
+#define	FPZDIV	(1<<10)
+#define	FPRNR	(0<<0)
+#define	FPRZ	(1<<0)
+#define	FPRPINF	(2<<0)
+#define	FPRNINF	(3<<0)
+#define	FPRMASK	(3<<0)
+#define	FPPEXT	0
+#define	FPPSGL	0
+#define	FPPDBL	0
+#define	FPPMASK	0
+/* FSR */
+#define	FPAINEX	(1<<2)
+#define	FPAOVFL	(1<<4)
+#define	FPAUNFL	(1<<3)
+#define	FPAZDIV	(1<<5)
+#endif
+#endif /* __FLOAT */

+ 78 - 0
spim64/include/ape/math.h

@@ -0,0 +1,78 @@
+#ifndef __MATH
+#define __MATH
+#pragma lib "/$M/lib/ape/libap.a"
+
+/* a HUGE_VAL appropriate for IEEE double-precision */
+/* the correct value, 1.797693134862316e+308, causes a ken overflow */
+#define HUGE_VAL 1.79769313486231e+308
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern double acos(double);
+extern double asin(double);
+extern double atan(double);
+extern double atan2(double, double);
+extern double cos(double);
+extern double hypot(double, double);
+extern double sin(double);
+extern double tan(double);
+extern double cosh(double);
+extern double sinh(double);
+extern double tanh(double);
+extern double exp(double);
+extern double frexp(double, int *);
+extern double ldexp(double, int);
+extern double log(double);
+extern double log10(double);
+extern double modf(double, double *);
+extern double pow(double, double);
+extern double sqrt(double);
+extern double ceil(double);
+extern double fabs(double);
+extern double floor(double);
+extern double fmod(double, double);
+extern double NaN(void);
+extern int isNaN(double);
+extern double Inf(int);
+extern int isInf(double, int);
+
+#ifdef _RESEARCH_SOURCE
+/* does >> treat left operand as unsigned ? */
+#define Unsigned_Shifts 1
+#define	M_E		2.7182818284590452354	/* e */
+#define	M_LOG2E		1.4426950408889634074	/* log 2e */
+#define	M_LOG10E	0.43429448190325182765	/* log 10e */
+#define	M_LN2		0.69314718055994530942	/* log e2 */
+#define	M_LN10		2.30258509299404568402	/* log e10 */
+#define	M_PI		3.14159265358979323846	/* pi */
+#define	M_PI_2		1.57079632679489661923	/* pi/2 */
+#define	M_PI_4		0.78539816339744830962	/* pi/4 */
+#define	M_1_PI		0.31830988618379067154	/* 1/pi */
+#define	M_2_PI		0.63661977236758134308	/* 2/pi */
+#define	M_2_SQRTPI	1.12837916709551257390	/* 2/sqrt(pi) */
+#define	M_SQRT2		1.41421356237309504880	/* sqrt(2) */
+#define	M_SQRT1_2	0.70710678118654752440	/* 1/sqrt(2) */
+
+extern double hypot(double, double);
+extern double erf(double);
+extern double erfc(double);
+extern double j0(double);
+extern double y0(double);
+extern double j1(double);
+extern double y1(double);
+extern double jn(int, double);
+extern double yn(int, double);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define isnan(x) isNaN(x)
+#define isinf(x) isInf(x, 0)
+
+#endif /* __MATH */

+ 20 - 0
spim64/include/ape/stdarg.h

@@ -0,0 +1,20 @@
+#ifndef __STDARG
+#define __STDARG
+
+typedef char *va_list;
+
+#define va_start(list, start) list =\
+	(sizeof(start) < 8?\
+		(char*)((int*)&(start)+1):\
+		(char*)(&(start)+1))
+#define va_end(list)
+#define va_arg(list, mode)\
+	((sizeof(mode) == 1)?\
+		((list += 8), (mode*)list)[-8]:\
+	(sizeof(mode) == 2)?\
+		((list += 8), (mode*)list)[-4]:\
+	(sizeof(mode) == 4)?\
+		((list += 8), (mode*)list)[-2]:\
+		((list += sizeof(mode)), (mode*)list)[-1])
+
+#endif /* __STDARG */

+ 52 - 0
spim64/include/ape/ureg.h

@@ -0,0 +1,52 @@
+#ifndef __UREG_H
+#define __UREG_H
+#if !defined(_PLAN9_SOURCE)
+    This header file is an extension to ANSI/POSIX
+#endif
+
+struct Ureg
+{
+	unsigned long long	status;
+	unsigned long long	pc;
+	union{
+		unsigned long long	sp;		/* r29 */
+		unsigned long long	usp;		/* r29 */
+	};
+	unsigned long long	cause;
+	unsigned long long	badvaddr;
+	unsigned long long	tlbvirt;
+	unsigned long long	hi;
+	unsigned long long	lo;
+	unsigned long long	r31;
+	unsigned long long	r30;
+	unsigned long long	r28;
+	unsigned long long	r27;		/* unused */
+	unsigned long long	r26;		/* unused */
+	unsigned long long	r25;
+	unsigned long long	r24;
+	unsigned long long	r23;
+	unsigned long long	r22;
+	unsigned long long	r21;
+	unsigned long long	r20;
+	unsigned long long	r19;
+	unsigned long long	r18;
+	unsigned long long	r17;
+	unsigned long long	r16;
+	unsigned long long	r15;
+	unsigned long long	r14;
+	unsigned long long	r13;
+	unsigned long long	r12;
+	unsigned long long	r11;
+	unsigned long long	r10;
+	unsigned long long	r9;
+	unsigned long long	r8;
+	unsigned long long	r7;
+	unsigned long long	r6;
+	unsigned long long	r5;
+	unsigned long long	r4;
+	unsigned long long	r3;
+	unsigned long long	r2;
+	unsigned long long	r1;
+};
+
+#endif

+ 71 - 0
spim64/include/u.h

@@ -0,0 +1,71 @@
+#define nil		((void*)0)
+typedef	unsigned short	ushort;
+typedef	unsigned char	uchar;
+typedef	unsigned long	ulong;
+typedef	unsigned int	uint;
+typedef	signed char	schar;
+typedef	long long	vlong;
+typedef	unsigned long long uvlong;
+typedef unsigned long long uintptr;
+typedef unsigned long	usize;
+typedef	uint		Rune;
+typedef 	union FPdbleword FPdbleword;
+typedef uintptr	jmp_buf[2];
+#define	JMPBUFSP	0
+#define	JMPBUFPC	1
+#define	JMPBUFDPC	0
+typedef unsigned int	mpdigit;	/* for /sys/include/mp.h */
+typedef unsigned char u8int;
+typedef unsigned short u16int;
+typedef unsigned int	u32int;
+typedef unsigned long long u64int;
+
+/* FCR (FCR31) */
+#define	FPINEX	(1<<7)		/* enables */
+#define	FPUNFL	(1<<8)
+#define	FPOVFL	(1<<9)
+#define	FPZDIV	(1<<10)
+#define	FPINVAL	(1<<11)
+#define	FPRNR	(0<<0)		/* rounding modes */
+#define	FPRZ	(1<<0)
+#define	FPRPINF	(2<<0)
+#define	FPRNINF	(3<<0)
+#define	FPRMASK	(3<<0)
+#define	FPPEXT	0
+#define	FPPSGL	0
+#define	FPPDBL	0
+#define	FPPMASK	0
+#define FPCOND	(1<<23)
+
+/* FSR (also FCR31) */
+#define	FPAINEX	(1<<2)		/* flags */
+#define	FPAOVFL	(1<<4)
+#define	FPAUNFL	(1<<3)
+#define	FPAZDIV	(1<<5)
+#define	FPAINVAL (1<<6)
+
+union FPdbleword
+{
+	double	x;
+	struct {	/* little endian */
+		ulong lo;
+		ulong hi;
+	};
+};
+
+/* stdarg */
+typedef	char*	va_list;
+#define va_start(list, start) list =\
+	(sizeof(start) < 8?\
+		(char*)((vlong*)&(start)+1):\
+		(char*)(&(start)+1))
+#define va_end(list)\
+	USED(list)
+#define va_arg(list, mode)\
+	((sizeof(mode) == 1)?\
+		((list += 8), (mode*)list)[-8]:\
+	(sizeof(mode) == 2)?\
+		((list += 8), (mode*)list)[-4]:\
+	(sizeof(mode) == 4)?\
+		((list += 8), (mode*)list)[-2]:\
+		((list += sizeof(mode)), (mode*)list)[-1])

+ 44 - 0
spim64/include/ureg.h

@@ -0,0 +1,44 @@
+struct Ureg
+{
+	u64int	status;
+	u64int	pc;
+	union{
+		u64int	sp;		/* r29 */
+		u64int	usp;		/* r29 */
+	};
+	u64int	cause;
+	u64int	badvaddr;
+	u64int	tlbvirt;
+	u64int	hi;
+	u64int	lo;
+	u64int	r31;
+	u64int	r30;
+	u64int	r28;
+	u64int	r27;		/* unused */
+	u64int	r26;		/* unused */
+	u64int	r25;
+	u64int	r24;
+	u64int	r23;
+	u64int	r22;
+	u64int	r21;
+	u64int	r20;
+	u64int	r19;
+	u64int	r18;
+	u64int	r17;
+	u64int	r16;
+	u64int	r15;
+	u64int	r14;
+	u64int	r13;
+	u64int	r12;
+	u64int	r11;
+	u64int	r10;
+	u64int	r9;
+	u64int	r8;
+	u64int	r7;
+	u64int	r6;
+	u64int	r5;
+	u64int	r4;
+	u64int	r3;
+	u64int	r2;
+	u64int	r1;
+};

+ 9 - 0
spim64/mkfile

@@ -0,0 +1,9 @@
+</sys/src/mkfile.proto
+
+OS=04589qvx
+CPUS=$CPUS spim64
+
+CC=xc
+LD=xl
+O=x
+AS=xa

+ 222 - 0
sys/lib/acid/mips64

@@ -0,0 +1,222 @@
+// Mips64 support
+
+defn acidinit()			// Called after all the init modules are loaded
+{
+	bplist = {};
+	bpfmt = 'X';
+
+	srcpath = {
+		"./",
+		"/sys/src/libc/port/",
+		"/sys/src/libc/9sys/",
+		"/sys/src/libc/mips64/"
+	};
+
+	srcfiles = {};		// list of loaded files
+	srctext = {};		// the text of the files
+}
+
+defn stk()			// trace
+{
+	_stk(*PC, *SP, linkreg(0), 0);
+}
+
+defn lstk()			// trace with locals
+{
+	_stk(*PC, *SP, linkreg(0), 1);
+}
+
+defn gpr()			// print general purpose registers
+{
+	print("R1\t", *R1, " R2\t", *R2, "\n");
+	print("R3\t", *R3, " R4\t", *R4, "\n");
+	print("R5\t", *R5, " R6\t", *R6, "\n");
+	print("R7\t", *R7, " R8\t", *R8, "\n");
+	print("R9\t", *R9, " R10\t", *R10, "\n");
+	print("R11\t", *R11, " R12\t", *R12, "\n");
+	print("R13\t", *R13, " R14\t", *R14, "\n");
+	print("R15\t", *R15, " R16\t", *R16, "\n");
+	print("R17\t", *R17, " R18\t", *R18, "\n");
+	print("R19\t", *R19, " R20\t", *R20, "\n");
+	print("R21\t", *R21, " R22\t", *R22, "\n");
+	print("R23\t", *R23, " R24\t", *R24, "\n");
+	print("R25\t", *R25, " R26\t", *R26, "\n");
+	print("R27\t", *R27, " R28\t", *R28, "\n");
+	print("R29\t", *SP, " R30\t", *R30, "\n");
+	print("R31\t", *R31, "\n");
+}
+
+defn Fpr()
+{
+	print("F0\t",  *fmt(F0, 'G'),  "\tF2\t",  *fmt(F2, 'G'), "\n");
+	print("F4\t",  *fmt(F4, 'G'),  "\tF6\t",  *fmt(F6, 'G'), "\n");
+	print("F8\t",  *fmt(F8, 'G'),  "\tF10\t", *fmt(F10, 'G'), "\n");
+	print("F12\t", *fmt(F12, 'G'), "\tF14\t", *fmt(F14, 'G'), "\n");
+	print("F16\t", *fmt(F16, 'G'), "\tF18\t", *fmt(F18, 'G'), "\n");
+	print("F20\t", *fmt(F20, 'G'), "\tF22\t", *fmt(F22, 'G'), "\n");
+	print("F24\t", *fmt(F24, 'G'), "\tF26\t", *fmt(F26, 'G'), "\n");
+	print("F28\t", *fmt(F28, 'G'), "\tF30\t", *fmt(F30, 'G'), "\n");
+}
+
+defn fpr()
+{
+	print("F0\t",  *fmt(F0, 'g'),  "\tF1\t",  *fmt(F1, 'g'), "\n");
+	print("F2\t",  *fmt(F2, 'g'),  "\tF3\t",  *fmt(F3, 'g'), "\n");
+	print("F4\t",  *fmt(F4, 'g'),  "\tF5\t",  *fmt(F5, 'g'), "\n");
+	print("F6\t",  *fmt(F6, 'g'),  "\tF7\t",  *fmt(F7, 'g'), "\n");
+	print("F8\t",  *fmt(F8, 'g'),  "\tF9\t",  *fmt(F9, 'g'), "\n");
+	print("F10\t", *fmt(F10, 'g'), "\tF11\t", *fmt(F11, 'g'), "\n");
+	print("F12\t", *fmt(F12, 'g'), "\tF13\t", *fmt(F13, 'g'), "\n");
+	print("F14\t", *fmt(F14, 'g'), "\tF15\t", *fmt(F15, 'g'), "\n");
+	print("F16\t", *fmt(F16, 'g'), "\tF17\t", *fmt(F17, 'g'), "\n");
+	print("F18\t", *fmt(F18, 'g'), "\tF19\t", *fmt(F19, 'g'), "\n");
+	print("F20\t", *fmt(F20, 'g'), "\tF21\t", *fmt(F21, 'g'), "\n");
+	print("F22\t", *fmt(F22, 'g'), "\tF23\t", *fmt(F23, 'g'), "\n");
+	print("F24\t", *fmt(F24, 'g'), "\tF25\t", *fmt(F25, 'g'), "\n");
+	print("F26\t", *fmt(F26, 'g'), "\tF27\t", *fmt(F27, 'g'), "\n");
+	print("F28\t", *fmt(F28, 'g'), "\tF29\t", *fmt(F29, 'g'), "\n");
+	print("F30\t", *fmt(F30, 'g'), "\tF31\t", *fmt(F31, 'g'), "\n");
+}
+
+defn spr()				// print special processor registers
+{
+	local pc, link, cause;
+
+	pc = *PC;
+	print("PC\t", pc, " ", fmt(pc, 'a'), "  ");
+	pfl(pc);
+
+	link = *R31;
+	print("SP\t", *SP, "\tLINK\t", link, " ", fmt(link, 'a'), " ");
+	pfl(link);
+
+	cause = *CAUSE;
+	print("STATUS\t", *STATUS, "\tCAUSE\t", cause, " ", reason(cause), "\n");
+	print("TLBVIR\t", *TLBVIRT, "\tBADVADR\t", *BADVADDR, "\n");
+
+	print("HI\t", *HI, "\tLO\t", *LO, "\n");
+}
+
+defn regs()				// print all registers
+{
+	spr();
+	gpr();
+}
+
+defn pstop(pid)
+{
+	local l, pc;
+
+	pc = *PC;
+
+	print(pid,": ", reason(*CAUSE), "\t");
+	print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n");
+
+	if notes then {
+		if notes[0] != "sys: breakpoint" then {
+			print("Notes pending:\n");
+			l = notes;
+			while l do {
+				print("\t", head l, "\n");
+				l = tail l;
+			}
+		}
+	}
+}
+
+sizeofUreg = 152;
+aggr Ureg
+{
+	'X' 0 status;
+	'Y' 8 pc;
+	{
+	'Y' 16 sp;
+	'Y' 16 usp;
+	};
+	'X' 24 cause;
+	'Y' 32 badvaddr;
+	'Y' 40 tlbvirt;
+	'Y' 48 hi;
+	'Y' 56 lo;
+	'Y' 64 r31;
+	'Y' 72 r30;
+	'Y' 80 r28;
+	'Y' 88 r27;
+	'Y' 96 r26;
+	'Y' 104 r25;
+	'Y' 112 r24;
+	'Y' 120 r23;
+	'Y' 128 r22;
+	'Y' 136 r21;
+	'Y' 144 r20;
+	'Y' 152 r19;
+	'Y' 160 r18;
+	'Y' 168 r17;
+	'Y' 176 r16;
+	'Y' 184 r15;
+	'Y' 192 r14;
+	'Y' 200 r13;
+	'Y' 208 r12;
+	'Y' 216 r11;
+	'Y' 224 r10;
+	'Y' 232 r9;
+	'Y' 240 r8;
+	'Y' 248 r7;
+	'Y' 256 r6;
+	'Y' 264 r5;
+	'Y' 272 r4;
+	'Y' 280 r3;
+	'Y' 288 r2;
+	'Y' 296 r1;
+};
+
+defn
+Ureg(addr) {
+	complex Ureg addr;
+	print("	status	", addr.status, "\n");
+	print("	pc	", addr.pc, "\n");
+	print("	sp	", addr.sp, "\n");
+	print("	cause	", addr.cause, "\n");
+	print("	badvaddr	", addr.badvaddr, "\n");
+	print("	tlbvirt	", addr.tlbvirt, "\n");
+	print("	hi	", addr.hi, "\n");
+	print("	lo	", addr.lo, "\n");
+	print("	r31	", addr.r31, "\n");
+	print("	r30	", addr.r30, "\n");
+	print("	r28	", addr.r28, "\n");
+	print("	r27	", addr.r27, "\n");
+	print("	r26	", addr.r26, "\n");
+	print("	r25	", addr.r25, "\n");
+	print("	r24	", addr.r24, "\n");
+	print("	r23	", addr.r23, "\n");
+	print("	r22	", addr.r22, "\n");
+	print("	r21	", addr.r21, "\n");
+	print("	r20	", addr.r20, "\n");
+	print("	r19	", addr.r19, "\n");
+	print("	r18	", addr.r18, "\n");
+	print("	r17	", addr.r17, "\n");
+	print("	r16	", addr.r16, "\n");
+	print("	r15	", addr.r15, "\n");
+	print("	r14	", addr.r14, "\n");
+	print("	r13	", addr.r13, "\n");
+	print("	r12	", addr.r12, "\n");
+	print("	r11	", addr.r11, "\n");
+	print("	r10	", addr.r10, "\n");
+	print("	r9	", addr.r9, "\n");
+	print("	r8	", addr.r8, "\n");
+	print("	r7	", addr.r7, "\n");
+	print("	r6	", addr.r6, "\n");
+	print("	r5	", addr.r5, "\n");
+	print("	r4	", addr.r4, "\n");
+	print("	r3	", addr.r3, "\n");
+	print("	r2	", addr.r2, "\n");
+	print("	r1	", addr.r1, "\n");
+};
+
+defn linkreg(addr)
+{
+	complex Ureg addr;
+	return addr.r31\Y;
+}
+
+print("/sys/lib/acid/mips64");

+ 7 - 3
sys/lib/acid/syscall

@@ -57,10 +57,10 @@ defn printsyscall(name, fmt, arg) {
 			print(argl);
 		} else if (fmt[i] == 'Z') && (~*a == 0) then {
 			print("-1");
-			a++;	// advance extra word for quadword
+			if fmtsize(a) != 8 then a++;	// advance extra word for quadword
 		} else if (fmt[i] == 'Y') || (fmt[i] == 'V') then {
 			print(fmt(*a, fmt[i]));
-			a++;	// advance extra word for quadword
+			if fmtsize(a) != 8 then a++;	// advance extra word for quadword
 		} else if (fmt[i] == 'T') then {
 			if *a == 0 then
 				print("nil");
@@ -152,6 +152,8 @@ defn UPCSPRET() {
 		return { code(*(*PC-4)), code(*SP+4), code(*AX) };
 	if (objtype == "mips") || (objtype == "mips2") then
 		return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R1) };
+	if objtype == "mips64" then
+		return { code(*(*PC-8) & 0xffff), code(*SP), code(*R1) };
 	if objtype == "arm" then
 		return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) };	// untested
 	if objtype == "alpha" then
@@ -163,15 +165,17 @@ defn trapoffset() {
 	if objtype == "386" then return 5;
 	if objtype == "mips" then return 8;
 	if objtype == "mips2" then return 8;
+	if objtype == "mips64" then return 12;
 	if objtype == "arm" then return 8;	// untested
 	if objtype == "alpha" then return 8;	// untested
-}	
+}
 
 defn trapreason() {
 	// return reason for trap
 	if objtype == "386" then return reason(*TRAP);
 	if objtype == "mips" then return reason(*CAUSE);
 	if objtype == "mips2" then return reason(*CAUSE);
+	if objtype == "mips64" then return reason(*CAUSE);
 	if objtype == "arm" then return "unknown trap";	// untested
 	if objtype == "alpha" then return reason(cause);	// untested
 }

+ 10 - 3
sys/lib/acid/truss

@@ -164,6 +164,8 @@ defn setuptruss() {
 	while lst do
 	{
 		name = head lst;
+		if objtype == "mips64" && name == "seek" then
+			name = "_seek";
 		lst = tail lst;
 		addr = addressof(name);
 		if addr then
@@ -198,7 +200,7 @@ defn new() {
 }
 
 defn truss() {
-	local pc, lst, offset, prevpc, pcspret, ret;
+	local pc, lst, offset, prevpc, pcspret, ret, dataoffset;
 
 	offset = trapoffset();
 
@@ -207,6 +209,11 @@ defn truss() {
 	setuptruss();
 	pcspret = UPCSPRET();
 
+	if objtype == "mips64" then
+		dataoffset = 8;
+	else
+		dataoffset = 4;
+
 	while !_stoprunning do {
 		cont();
 		if notes[0]!="sys: breakpoint" then {
@@ -229,11 +236,11 @@ defn truss() {
 			print("\treturn value: ", ret\D, "\n");
 			if (ret>=0) && (match(prevpc, readPC)>=0) then {
 				print("\tdata: ");
-				printtextordata(*((eval pcspret[1])+4), ret);
+				printtextordata(*((eval pcspret[1])+dataoffset), ret);
 				print("\n");
 			}
 			if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then {
-				print("\tdata: \"", *(*((eval pcspret[1])+4)\s), "\"\n");
+				print("\tdata: \"", *(*((eval pcspret[1])+dataoffset)\s), "\"\n");
 			}
 			if (ret>=0) && (match(prevpc, errstrPC)>=0) then {
 				print("\tdata: \"", *(*(eval pcspret[1])\s), "\"\n");

+ 5 - 7
sys/src/cmd/4a/a.h

@@ -1,19 +1,18 @@
 #include <u.h>
 #include <libc.h>
 #include <bio.h>
-#include "../vc/v.out.h"
+#include "../4c/4.out.h"
 
 #ifndef	EXTERN
 #define	EXTERN	extern
 #endif
 
-#define	MAXALIGN	7
-
 typedef	struct	Sym	Sym;
 typedef	struct	Gen	Gen;
 typedef	struct	Io	Io;
 typedef	struct	Hist	Hist;
 
+#define	MAXALIGN	7
 #define	FPCHIP		1
 #define	NSYMB		8192
 #define	BUFSIZ		8192
@@ -63,13 +62,12 @@ EXTERN	struct
 struct	Gen
 {
 	Sym*	sym;
-	long	offset;
+	vlong	offset;
 	short	type;
 	short	reg;
 	short	name;
 	double	dval;
 	char	sval[8];
-	vlong	vval;
 };
 
 struct	Hist
@@ -86,7 +84,7 @@ enum
 	CLAST,
 	CMACARG,
 	CMACRO,
-	CPREPROC,
+	CPREPROC
 };
 
 EXTERN	char	debug[256];
@@ -170,7 +168,7 @@ enum				/* keep in synch with ../cc/cc.h */
 {
 	Plan9	= 1<<0,
 	Unix	= 1<<1,
-	Windows	= 1<<2,
+	Windows	= 1<<2
 };
 int	mywait(int*);
 int	mycreat(char*, int);

+ 9 - 17
sys/src/cmd/4a/a.y

@@ -361,13 +361,11 @@ freg:
 ximm:	'$' con
 	{
 		$$ = nullgen;
-		if(isvconst($2)) {
+		if(isvconst($2))
 			$$.type = D_VCONST;
-			$$.vval = $2;
-		} else {
+		else
 			$$.type = D_CONST;
-			$$.offset = $2;
-		}
+		$$.offset = $2;
 	}
 |	'$' oreg
 	{
@@ -462,15 +460,11 @@ imr:
 imm:	'$' con
 	{
 		$$ = nullgen;
-		if(isvconst($2)) {
-			fprint(2, "imm: vconst: 0x%llx\n", $2);
+		if(isvconst($2))
 			$$.type = D_VCONST;
-			$$.vval = $2;
-		} else {
-			fprint(2, "imm: const: 0x%lx\n", (long)$2);
+		else
 			$$.type = D_CONST;
-			$$.offset = $2;
-		}
+		$$.offset = $2;
 	}
 
 reg:
@@ -604,10 +598,8 @@ expr:
 int
 isvconst(vlong con)
 {
-	vlong v;
+	long l;
 
-	v = con >> 32;
-	if(v != 0 && v != -1)
-		return 1;
-	return 0;
+	l = con;
+	return (vlong)l != con;
 }

+ 23 - 12
sys/src/cmd/4a/lex.c

@@ -1,7 +1,7 @@
-#include <ctype.h>
 #define	EXTERN
 #include "a.h"
 #include "y.tab.h"
+#include <ctype.h>
 
 void
 main(int argc, char *argv[])
@@ -10,7 +10,7 @@ main(int argc, char *argv[])
 	int nout, nproc, status, i, c;
 
 	thechar = '4';
-	thestring = "mips2";
+	thestring = "mips64";
 	memset(debug, 0, sizeof(debug));
 	cinit();
 	outfile = 0;
@@ -36,6 +36,10 @@ main(int argc, char *argv[])
 		p = ARGF();
 		setinclude(p);
 		break;
+	case  'L':			/* for little-endian mips */
+		thechar = 'x';	/* XXX the char unknown */
+		thestring = "spim64";
+		break;
 	} ARGEND
 	if(*argv == 0) {
 		print("usage: %ca [-options] file.s\n", thechar);
@@ -318,9 +322,9 @@ struct
 	"SRA",		LTYPE1, ASRA,
 
 	"ADDV",		LTYPE1, AADDV,
-	"ADDVU",	LTYPE1, AADDVU,
+	"ADDVU",		LTYPE1, AADDVU,
 	"SUBV",		LTYPE1, ASUBV,	/* converted to ADD(-) in loader */
-	"SUBVU",	LTYPE1, ASUBVU,
+	"SUBVU",		LTYPE1, ASUBVU,
 	"SLLV",		LTYPE1, ASLLV,
 	"SRLV",		LTYPE1, ASRLV,
 	"SRAV",		LTYPE1, ASRAV,
@@ -357,9 +361,9 @@ struct
 	"MUL",		LTYPE6, AMUL,
 	"MULU",		LTYPE6, AMULU,
 	"DIVV",		LTYPE6, ADIVV,
-	"DIVVU",	LTYPE6, ADIVVU,
+	"DIVVU",		LTYPE6, ADIVVU,
 	"MULV",		LTYPE6, AMULV,
-	"MULVU",	LTYPE6, AMULVU,
+	"MULVU",		LTYPE6, AMULVU,
 
 	"RFE",		LTYPE7, ARFE,
 	"JMP",		LTYPE7, AJMP,
@@ -454,7 +458,7 @@ cinit(void)
 		s->value = itab[i].value;
 	}
 
-	pathname = alloc(100);
+	pathname = allocn(pathname, 0, 100);
 	if(mygetwd(pathname, 99) == 0) {
 		pathname = allocn(pathname, 100, 900);
 		if(mygetwd(pathname, 999) == 0)
@@ -559,7 +563,7 @@ zaddr(Gen *a, int s)
 		break;
 
 	case D_VCONST:
-		v = a->vval;
+		v = a->offset;
 		Bputc(&obuf, v);
 		Bputc(&obuf, v>>8);
 		Bputc(&obuf, v>>16);
@@ -650,12 +654,17 @@ outhist(void)
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
 		op = 0;
+		/* on windows skip drive specifier in pathname */
+		if(systemtype(Windows) && p && p[1] == ':'){
+			p += 2;
+			c = *p;
+		}
 		if(p && p[0] != c && h->offset == 0 && pathname){
 			/* on windows skip drive specifier in pathname */
-			if(systemtype(Windows) && pathname[2] == c) {
+			if(systemtype(Windows) && pathname[1] == ':') {
 				op = p;
 				p = pathname+2;
-				*p = '/';
+				c = *p;
 			} else if(pathname[0] == c){
 				op = p;
 				p = pathname;
@@ -665,8 +674,10 @@ outhist(void)
 			q = strchr(p, c);
 			if(q) {
 				n = q-p;
-				if(n == 0)
+				if(n == 0){
 					n = 1;	/* leading "/" */
+					*p = '/';	/* don't emit "\" on windows */
+				}
 				q++;
 			} else {
 				n = strlen(p);
@@ -699,6 +710,6 @@ outhist(void)
 	}
 }
 
-#include "lexbody"
+#include "../cc/lexbody"
 #include "../cc/macbody"
 #include "../cc/compat"

+ 1 - 8
sys/src/cmd/4a/mkfile

@@ -6,20 +6,13 @@ OFILES=\
 	lex.$O\
 
 HFILES=\
-	../vc/v.out.h\
+	../4c/4.out.h\
 	y.tab.h\
 	a.h\
 
 YFILES=a.y\
 
 BIN=/$objtype/bin
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-	$YFILES\
-
 < /sys/src/cmd/mkone
 YFLAGS=-D1 -d
 

+ 202 - 0
sys/src/cmd/4c/4.out.h

@@ -0,0 +1,202 @@
+#define	NSNAME	8
+#define	NSYM	50
+#define	NREG	32
+
+#define NOPROF	(1<<0)
+#define DUPOK	(1<<1)
+
+#define	REGZERO		0
+#define	REGRET		1
+#define	REGARG		1
+/* compiler allocates R1 up as temps */
+/* compiler allocates register variables R3-R23 */
+#define	REGEXT		25
+/* compiler allocates external registers R25 down */
+/* dont use R26 R27 */
+#define	REGTMP		28
+#define	REGSP		29
+#define	REGSB		30
+#define	REGLINK		31
+
+#define	FREGRET		0
+/* compiler allocates register variables F4-F22 */
+/* compiler allocates external registers F22 down */
+#define	FREGEXT		22
+#define	FREGZERO	24	/* both float and double */
+#define	FREGHALF	26	/* double */
+#define	FREGONE		28	/* double */
+#define	FREGTWO		30	/* double */
+
+enum	as
+{
+	AXXX,
+
+	AABSD,
+	AABSF,
+	AABSW,
+	AADD,
+	AADDD,
+	AADDF,
+	AADDU,
+	AADDW,
+	AAND,
+	ABEQ,
+	ABFPF,
+	ABFPT,
+	ABGEZ,
+	ABGEZAL,
+	ABGTZ,
+	ABLEZ,
+	ABLTZ,
+	ABLTZAL,
+	ABNE,
+	ABREAK,
+	ACMPEQD,
+	ACMPEQF,
+	ACMPGED,
+	ACMPGEF,
+	ACMPGTD,
+	ACMPGTF,
+	ADATA,
+	ADIV,
+	ADIVD,
+	ADIVF,
+	ADIVU,
+	ADIVW,
+	AGLOBL,
+	AGOK,
+	AHISTORY,
+	AJAL,
+	AJMP,
+	AMOVB,
+	AMOVBU,
+	AMOVD,
+	AMOVDF,
+	AMOVDW,
+	AMOVF,
+	AMOVFD,
+	AMOVFW,
+	AMOVH,
+	AMOVHU,
+	AMOVW,
+	AMOVWD,
+	AMOVWF,
+	AMOVWL,
+	AMOVWR,
+	AMUL,
+	AMULD,
+	AMULF,
+	AMULU,
+	AMULW,
+	ANAME32,
+	ANAME,
+	ANEGD,
+	ANEGF,
+	ANEGW,
+	ANOP,
+	ANOR,
+	AOR,
+	AREM,
+	AREMU,
+	ARET,
+	ARFE,
+	ASGT,
+	ASGTU,
+	ASLL,
+	ASRA,
+	ASRL,
+	ASUB,
+	ASUBD,
+	ASUBF,
+	ASUBU,
+	ASUBW,
+	ASYSCALL,
+	ATEXT,
+	ATLBP,
+	ATLBR,
+	ATLBWI,
+	ATLBWR,
+	AWORD,
+	AXOR,
+
+	AEND,
+
+	AMOVV,
+	AMOVVL,
+	AMOVVR,
+	ASLLV,
+	ASRAV,
+	ASRLV,
+	ADIVV,
+	ADIVVU,
+	AREMV,
+	AREMVU,
+	AMULV,
+	AMULVU,
+	AADDV,
+	AADDVU,
+	ASUBV,
+	ASUBVU,
+
+	ADYNT,
+	AINIT,
+
+	ABCASE,
+	ACASE,
+
+	ATRUNCFV,
+	ATRUNCDV,
+	ATRUNCFW,
+	ATRUNCDW,
+	AMOVWU,
+	AMOVFV,
+	AMOVDV,
+	AMOVVF,
+	AMOVVD,
+
+	ASIGNAME,
+
+	ALAST,
+};
+
+/* type/name */
+#define	D_GOK	0
+#define	D_NONE	1
+
+/* type */
+#define	D_BRANCH (D_NONE+1)
+#define	D_OREG	(D_NONE+2)
+#define	D_EXTERN (D_NONE+3)	/* name */
+#define	D_STATIC (D_NONE+4)	/* name */
+#define	D_AUTO	(D_NONE+5)	/* name */
+#define	D_PARAM	(D_NONE+6)	/* name */
+#define	D_CONST	(D_NONE+7)
+#define	D_FCONST (D_NONE+8)
+#define	D_SCONST (D_NONE+9)
+#define	D_HI	(D_NONE+10)
+#define	D_LO	(D_NONE+11)
+#define	D_REG	(D_NONE+12)
+#define	D_FREG	(D_NONE+13)
+#define	D_FCREG	(D_NONE+14)
+#define	D_MREG	(D_NONE+15)
+#define	D_FILE	(D_NONE+16)
+#define	D_OCONST (D_NONE+17)
+#define	D_FILE1	(D_NONE+18)
+#define	D_VCONST (D_NONE+19)
+
+/*
+ * this is the ranlib header
+ */
+#define	SYMDEF	"__.SYMDEF"
+
+/*
+ * this is the simulated IEEE floating point
+ */
+typedef	struct	ieee	Ieee;
+struct	ieee
+{
+	long	l;	/* contains ls-man	0xffffffff */
+	long	h;	/* contains sign	0x80000000
+				    exp		0x7ff00000
+				    ms-man	0x000fffff */
+};

+ 0 - 127
sys/src/cmd/4c/bits.c

@@ -1,127 +0,0 @@
-#define	EXTERN
-#include "gc.h"
-
-/*
-Bits
-bor(Bits a, Bits b)
-{
-	Bits c;
-	int i;
-
-	for(i=0; i<BITS; i++)
-		c.b[i] = a.b[i] | b.b[i];
-	return c;
-}
-*/
-
-/*
-Bits
-band(Bits a, Bits b)
-{
-	Bits c;
-	int i;
-
-	for(i=0; i<BITS; i++)
-		c.b[i] = a.b[i] & b.b[i];
-	return c;
-}
-*/
-
-/*
-Bits
-bnot(Bits a)
-{
-	Bits c;
-	int i;
-
-	for(i=0; i<BITS; i++)
-		c.b[i] = ~a.b[i];
-	return c;
-}
-*/
-
-int
-bany(Bits *a)
-{
-	int i;
-
-	for(i=0; i<BITS; i++)
-		if(a->b[i])
-			return 1;
-	return 0;
-}
-
-/*
-int
-beq(Bits a, Bits b)
-{
-	int i;
-
-	for(i=0; i<BITS; i++)
-		if(a.b[i] != b.b[i])
-			return 0;
-	return 1;
-}
-*/
-
-int
-bnum(Bits a)
-{
-	int i;
-	long b;
-
-	for(i=0; i<BITS; i++)
-		if(b = a.b[i])
-			return 32*i + bitno(b);
-	diag(Z, "bad in bnum");
-	return 0;
-}
-
-Bits
-blsh(unsigned n)
-{
-	Bits c;
-
-	c = zbits;
-	c.b[n/32] = 1L << (n%32);
-	return c;
-}
-
-/*
-int
-bset(Bits a, unsigned n)
-{
-	int i;
-
-	if(a.b[n/32] & (1L << (n%32)))
-		return 1;
-	return 0;
-}
-*/
-
-int
-Bconv(va_list *arg, Fconv *fp)
-{
-	char str[STRINGSZ], ss[STRINGSZ], *s;
-	Bits bits;
-	int i;
-
-	str[0] = 0;
-	bits = va_arg(*arg, Bits);
-	while(bany(&bits)) {
-		i = bnum(bits);
-		if(str[0])
-			strcat(str, " ");
-		if(var[i].sym == S) {
-			sprint(ss, "$%ld", var[i].offset);
-			s = ss;
-		} else
-			s = var[i].sym->name;
-		if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
-			break;
-		strcat(str, s);
-		bits.b[i/32] &= ~(1L << (i%32));
-	}
-	strconv(str, fp);
-	return 0;
-}

+ 4 - 2
sys/src/cmd/4c/cgen.c

@@ -200,13 +200,13 @@ cgen(Node *n, Node *nn)
 		if(l->op == OBIT)
 			goto asbitop;
 		if(r->op == OCONST)
+		if(!typefd[r->type->etype])
 		if(!typefd[n->type->etype]) {
 			if(l->addable < INDEXED)
 				reglcgen(&nod2, l, Z);
 			else
 				nod2 = *l;
-
-			regalloc(&nod, n, nn);
+			regalloc(&nod, r, nn);
 			gopcode(OAS, &nod2, Z, &nod);
 			gopcode(o, r, Z, &nod);
 			gopcode(OAS, &nod, Z, &nod2);
@@ -497,6 +497,8 @@ cgen(Node *n, Node *nn)
 		} else
 			gopcode(OADD, nodconst(v), Z, &nod);
 		gopcode(OAS, &nod, Z, &nod2);
+		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
+			gins(ANOP, l, Z);
 
 		regfree(&nod);
 		if(l->addable < INDEXED)

+ 2 - 0
sys/src/cmd/4l/enam.c → sys/src/cmd/4c/enam.c

@@ -58,6 +58,7 @@ char*	anames[] =
 	"MULF",
 	"MULU",
 	"MULW",
+	"NAME32",
 	"NAME",
 	"NEGD",
 	"NEGF",
@@ -117,5 +118,6 @@ char*	anames[] =
 	"MOVDV",
 	"MOVVF",
 	"MOVVD",
+	"SIGNAME",
 	"LAST",
 };

+ 19 - 17
sys/src/cmd/4c/gc.h

@@ -1,8 +1,8 @@
 #include	"../cc/cc.h"
-#include	"../vc/v.out.h"
+#include	"../4c/4.out.h"
 
 /*
- * 4c/mips2
+ * 4c/mips64
  * Mips 4000
  */
 #define	SZ_CHAR		1
@@ -27,9 +27,8 @@ typedef	struct	Rgn	Rgn;
 
 struct	Adr
 {
-	long	offset;
+	vlong	offset;
 	double	dval;
-	vlong	vval;
 	char	sval[NSNAME];
 	Ieee	ieee;
 
@@ -56,15 +55,16 @@ struct	Prog
 struct	Case
 {
 	Case*	link;
-	long	val;
-	u64int	label;
+	vlong	val;
+	long	label;
 	char	def;
+	char isv;
 };
 #define	C	((Case*)0)
 
 struct	C1
 {
-	long	val;
+	vlong	val;
 	long	label;
 };
 
@@ -90,7 +90,7 @@ struct	Var
 
 struct	Reg
 {
-	u64int	pc;
+	long	pc;
 	long	rpo;		/* reverse post ordering */
 
 	Bits	set;
@@ -120,7 +120,7 @@ struct	Reg
 };
 #define	R	((Reg*)0)
 
-#define	NRGN	600
+#define	NRGN	1000		/* was 600; raised for paranoia.c */
 struct	Rgn
 {
 	Reg*	enter;
@@ -130,6 +130,7 @@ struct	Rgn
 };
 
 EXTERN	long	breakpc;
+EXTERN	long	nbreak;
 EXTERN	Case*	cases;
 EXTERN	Node	constnode;
 EXTERN	Node	fconstnode;
@@ -141,7 +142,6 @@ EXTERN	Prog*	lastp;
 EXTERN	long	maxargsafe;
 EXTERN	int	mnstring;
 EXTERN	Multab	multab[20];
-EXTERN	int	retok;
 EXTERN	int	hintabsize;
 EXTERN	Node*	nodrat;
 EXTERN	Node*	nodret;
@@ -149,15 +149,15 @@ EXTERN	Node*	nodsafe;
 EXTERN	long	nrathole;
 EXTERN	long	nstring;
 EXTERN	Prog*	p;
-EXTERN	u64int	pc;
+EXTERN	long	pc;
 EXTERN	Node	regnode;
 EXTERN	char	string[NSNAME];
 EXTERN	Sym*	symrathole;
 EXTERN	Node	znode;
 EXTERN	Prog	zprog;
 EXTERN	char	reg[NREG+NREG];
-EXTERN	u64int	exregoffset;
-EXTERN	u64int	exfregoffset;
+EXTERN	long	exregoffset;
+EXTERN	long	exfregoffset;
 
 #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
 #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
@@ -185,6 +185,7 @@ EXTERN	long	regbits;
 EXTERN	long	exregbits;
 
 EXTERN	int	change;
+EXTERN	int	suppress;
 
 EXTERN	Reg*	firstr;
 EXTERN	Reg*	lastr;
@@ -205,7 +206,7 @@ void	codgen(Node*, Node*);
 void	gen(Node*);
 void	noretval(int);
 void	xcom(Node*);
-void	bcomplex(Node*);
+int	bcomplex(Node*, Node*);
 void	usedset(Node*, int);
 
 /*
@@ -228,6 +229,7 @@ void	nextpc(void);
 void	gargs(Node*, Node*, Node*);
 void	garg1(Node*, Node*, Node*, int, Node**);
 Node*	nodconst(long);
+Node*	nod32const(vlong);
 Node*	nodfconst(double);
 void	nodreg(Node*, Node*, int);
 void	regret(Node*, Node*);
@@ -257,15 +259,15 @@ void	gpseudo(int, Sym*, Node*);
  */
 int	swcmp(const void*, const void*);
 void	doswit(Node*);
-void	swit1(C1*, int, long, Node*, Node*);
-void	cas(void);
+void	swit1(C1*, int, long, Node*);
+void	swit2(C1*, int, long, Node*, Node*);
+void	casf(void);
 void	bitload(Node*, Node*, Node*, Node*, Node*);
 void	bitstore(Node*, Node*, Node*, Node*, Node*);
 long	outstring(char*, long);
 int	mulcon(Node*, Node*);
 Multab*	mulcon0(long);
 void	nullwarn(Node*, Node*);
-void	sextern(Sym*, Node*, long, long);
 void	gextern(Sym*, Node*, long, long);
 void	outcode(void);
 void	ieeedtod(Ieee*, double);

+ 1570 - 0
sys/src/cmd/4c/lex.c

@@ -0,0 +1,1570 @@
+#include	"cc.h"
+#include	"y.tab.h"
+
+#ifndef	CPP
+#define	CPP	"/bin/cpp"
+#endif
+
+/*
+ * known debug flags
+ *	-a		acid declaration output
+ *	-A		!B
+ *	-B		non ANSI
+ *	-d		print declarations
+ *	-D name		define
+ *	-F		format specification check
+ *	-i		print initialization
+ *	-I path		include
+ *	-l		generate little-endian code
+ *	-L		print every NAME symbol
+ *	-M		constant multiplication
+ *	-m		print add/sub/mul trees
+ *	-n		print acid to file (%.c=%.acid) (with -a or -aa)
+ *	-o file		output file
+ *	-p		use standard cpp ANSI preprocessor (not on windows)
+ *	-r		print registerization
+ *	-s		print structure offsets (with -a or -aa)
+ *	-S		print assembly
+ *	-t		print type trees
+ *	-V		enable void* conversion warnings
+ *	-v		verbose printing
+ *	-w		print warnings
+ *	-X		abort on error
+ *	-.		Inhibit search for includes in source directory
+ */
+
+void
+main(int argc, char *argv[])
+{
+	char **defs, **np, *p;
+	int nproc, nout, status, i, c, ndef, maxdef;
+
+	memset(debug, 0, sizeof(debug));
+	tinit();
+	cinit();
+	ginit();
+	arginit();
+
+	profileflg = 1;	/* #pragma can turn it off */
+	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
+	maxdef = 0;
+	ndef = 0;
+	outfile = 0;
+	defs = nil;
+	setinclude(".");
+	ARGBEGIN {
+	default:
+		c = ARGC();
+		if(c >= 0 && c < sizeof(debug))
+			debug[c]++;
+		break;
+
+	case 'l':			/* for little-endian mips */
+		switch(thechar) {
+		default:
+			print("can only use -l with vc or 4c\n");
+			errorexit();
+
+		case 'v':
+			thechar = '0';
+			thestring = "spim";
+			break;
+
+		case '4':
+			thechar = 'x';
+			thestring = "spim64";
+			break;
+		}
+		break;
+
+	case 'o':
+		outfile = ARGF();
+		break;
+
+	case 'D':
+		p = ARGF();
+		if(p) {
+			if(ndef >= maxdef){
+				maxdef += 50;
+				np = alloc(maxdef * sizeof *np);
+				if(defs != nil)
+					memmove(np, defs, (maxdef - 50) * sizeof *np);
+				defs = np;
+			}
+			defs[ndef++] = p;
+			dodefine(p);
+		}
+		break;
+
+	case 'I':
+		p = ARGF();
+		if(p)
+			setinclude(p);
+		break;
+	} ARGEND
+	if(argc < 1 && outfile == 0) {
+		print("usage: %cc [-options] files\n", thechar);
+		errorexit();
+	}
+	if(argc > 1 && systemtype(Windows)){
+		print("can't compile multiple files on windows\n");
+		errorexit();
+	}
+	if(argc > 1 && !systemtype(Windows)) {
+		nproc = 1;
+		/*
+		 * if we're writing acid to standard output, don't compile
+		 * concurrently, to avoid interleaving output.
+		 */
+		if(((!debug['a'] && !debug['Z']) || debug['n']) &&
+		    (p = getenv("NPROC")) != nil)
+			nproc = atol(p);	/* */
+		c = 0;
+		nout = 0;
+		for(;;) {
+			while(nout < nproc && argc > 0) {
+				i = myfork();
+				if(i < 0) {
+					i = mywait(&status);
+					if(i < 0) {
+						print("cannot create a process\n");
+						errorexit();
+					}
+					if(status)
+						c++;
+					nout--;
+					continue;
+				}
+				if(i == 0) {
+					fprint(2, "%s:\n", *argv);
+					if (compile(*argv, defs, ndef))
+						errorexit();
+					exits(0);
+				}
+				nout++;
+				argc--;
+				argv++;
+			}
+			i = mywait(&status);
+			if(i < 0) {
+				if(c)
+					errorexit();
+				exits(0);
+			}
+			if(status)
+				c++;
+			nout--;
+		}
+	}
+
+	if(argc == 0)
+		c = compile("stdin", defs, ndef);
+	else
+		c = compile(argv[0], defs, ndef);
+
+	if(c)
+		errorexit();
+	exits(0);
+}
+
+int
+compile(char *file, char **defs, int ndef)
+{
+	char ofile[400], incfile[20];
+	char *p, **av, opt[256];
+	int i, c, fd[2];
+	static int first = 1;
+
+	strcpy(ofile, file);
+	p = utfrrune(ofile, pathchar());
+	if(p) {
+		*p++ = 0;
+		if(!debug['.'])
+			include[0] = strdup(ofile);
+	} else
+		p = ofile;
+
+	if(outfile == 0) {
+		outfile = p;
+		if(outfile) {
+			if(p = utfrrune(outfile, '.'))
+				if(p[1] == 'c' && p[2] == 0)
+					p[0] = 0;
+			p = utfrune(outfile, 0);
+			if(debug['a'] && debug['n'])
+				strcat(p, ".acid");
+			else if(debug['Z'] && debug['n'])
+				strcat(p, "_pickle.c");
+			else {
+				p[0] = '.';
+				p[1] = thechar;
+				p[2] = 0;
+			}
+		} else
+			outfile = "/dev/null";
+	}
+
+	if(p = getenv("INCLUDE")) {
+		setinclude(p);
+	} else {
+		if(systemtype(Plan9)) {
+			sprint(incfile, "/%s/include", thestring);
+			setinclude(strdup(incfile));
+			setinclude("/sys/include");
+		}
+	}
+	if (first)
+		Binit(&diagbuf, 1, OWRITE);
+	/*
+	 * if we're writing acid to standard output, don't keep scratching
+	 * outbuf.
+	 */
+	if((debug['a'] || debug['Z']) && !debug['n']) {
+		if (first) {
+			outfile = 0;
+			Binit(&outbuf, dup(1, -1), OWRITE);
+			dup(2, 1);
+		}
+	} else {
+		c = mycreat(outfile, 0664);
+		if(c < 0) {
+			diag(Z, "cannot open %s - %r", outfile);
+			outfile = 0;
+			errorexit();
+		}
+		Binit(&outbuf, c, OWRITE);
+	}
+	newio();
+	first = 0;
+
+	/* Use an ANSI preprocessor */
+	if(debug['p']) {
+		if(systemtype(Windows)) {
+			diag(Z, "-p option not supported on windows");
+			errorexit();
+		}
+		if(myaccess(file) < 0) {
+			diag(Z, "%s does not exist", file);
+			errorexit();
+		}
+		if(mypipe(fd) < 0) {
+			diag(Z, "pipe failed");
+			errorexit();
+		}
+		switch(myfork()) {
+		case -1:
+			diag(Z, "fork failed");
+			errorexit();
+		case 0:
+			close(fd[0]);
+			mydup(fd[1], 1);
+			close(fd[1]);
+			av = alloc((3 + ndef + ninclude + 2) * sizeof *av);
+			av[0] = CPP;
+			i = 1;
+			if(debug['.'])
+				av[i++] = strdup("-.");
+			/* 1999 ANSI C requires recognising // comments */
+			av[i++] = strdup("-+");
+			for(c = 0; c < ndef; c++) {
+				sprint(opt, "-D%s", defs[c]);
+				av[i++] = strdup(opt);
+			}
+			for(c = 0; c < ninclude; c++) {
+				sprint(opt, "-I%s", include[c]);
+				av[i++] = strdup(opt);
+			}
+			if(strcmp(file, "stdin") != 0)
+				av[i++] = file;
+			av[i] = 0;
+			if(debug['p'] > 1) {
+				for(c = 0; c < i; c++)
+					fprint(2, "%s ", av[c]);
+				fprint(2, "\n");
+			}
+			myexec(av[0], av);
+			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
+			errorexit();
+		default:
+			close(fd[1]);
+			newfile(file, fd[0]);
+			break;
+		}
+	} else {
+		if(strcmp(file, "stdin") == 0)
+			newfile(file, 0);
+		else
+			newfile(file, -1);
+	}
+	yyparse();
+	if(!debug['a'] && !debug['Z'])
+		gclean();
+	return nerrors;
+}
+
+void
+errorexit(void)
+{
+	if(outfile)
+		remove(outfile);
+	exits("error");
+}
+
+void
+pushio(void)
+{
+	Io *i;
+
+	i = iostack;
+	if(i == I) {
+		yyerror("botch in pushio");
+		errorexit();
+	}
+	i->p = fi.p;
+	i->c = fi.c;
+}
+
+void
+newio(void)
+{
+	Io *i;
+	static int pushdepth = 0;
+
+	i = iofree;
+	if(i == I) {
+		pushdepth++;
+		if(pushdepth > 1000) {
+			yyerror("macro/io expansion too deep");
+			errorexit();
+		}
+		i = alloc(sizeof(*i));
+	} else
+		iofree = i->link;
+	i->c = 0;
+	i->f = -1;
+	ionext = i;
+}
+
+void
+newfile(char *s, int f)
+{
+	Io *i;
+
+	if(debug['e'])
+		print("%L: %s\n", lineno, s);
+
+	i = ionext;
+	i->link = iostack;
+	iostack = i;
+	i->f = f;
+	if(f < 0)
+		i->f = open(s, 0);
+	if(i->f < 0) {
+		yyerror("%cc: %r: %s", thechar, s);
+		errorexit();
+	}
+	fi.c = 0;
+	linehist(s, 0);
+}
+
+Sym*
+slookup(char *s)
+{
+
+	strcpy(symb, s);
+	return lookup();
+}
+
+Sym*
+lookup(void)
+{
+	Sym *s;
+	ulong h;
+	char *p;
+	int c, n;
+
+	h = 0;
+	for(p=symb; *p;) {
+		h = h * 3;
+		h += *p++;
+	}
+	n = (p - symb) + 1;
+	if((long)h < 0)
+		h = ~h;
+	h %= NHASH;
+	c = symb[0];
+	for(s = hash[h]; s != S; s = s->link) {
+		if(s->name[0] != c)
+			continue;
+		if(strcmp(s->name, symb) == 0)
+			return s;
+	}
+	s = alloc(sizeof(*s));
+	s->name = alloc(n);
+	memmove(s->name, symb, n);
+
+	strcpy(s->name, symb);
+	s->link = hash[h];
+	hash[h] = s;
+	syminit(s);
+
+	return s;
+}
+
+void
+syminit(Sym *s)
+{
+	s->lexical = LNAME;
+	s->block = 0;
+	s->offset = 0;
+	s->type = T;
+	s->suetag = T;
+	s->class = CXXX;
+	s->aused = 0;
+	s->sig = SIGNONE;
+}
+
+#define	EOF	(-1)
+#define	IGN	(-2)
+#define	ESC	(Runemask+1)		/* Rune flag: a literal byte */
+#define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
+
+enum
+{
+	Numdec		= 1<<0,
+	Numlong		= 1<<1,
+	Numuns		= 1<<2,
+	Numvlong	= 1<<3,
+	Numflt		= 1<<4,
+};
+
+long
+yylex(void)
+{
+	vlong vv;
+	long c, c1, t;
+	char *cp;
+	Rune rune;
+	Sym *s;
+
+	if(peekc != IGN) {
+		c = peekc;
+		peekc = IGN;
+		goto l1;
+	}
+l0:
+	c = GETC();
+
+l1:
+	if(c >= Runeself) {
+		/*
+		 * extension --
+		 *	all multibyte runes are alpha
+		 */
+		cp = symb;
+		goto talph;
+	}
+	if(isspace(c)) {
+		if(c == '\n')
+			lineno++;
+		goto l0;
+	}
+	if(isalpha(c)) {
+		cp = symb;
+		if(c != 'L')
+			goto talph;
+		*cp++ = c;
+		c = GETC();
+		if(c == '\'') {
+			/* L'x' */
+			c = escchar('\'', 1, 0);
+			if(c == EOF)
+				c = '\'';
+			c1 = escchar('\'', 1, 0);
+			if(c1 != EOF) {
+				yyerror("missing '");
+				peekc = c1;
+			}
+			yylval.vval = convvtox(c, TRUNE);
+			return LUCONST;
+		}
+		if(c == '"') {
+			goto caselq;
+		}
+		goto talph;
+	}
+	if(isdigit(c))
+		goto tnum;
+	switch(c)
+	{
+
+	case EOF:
+		peekc = EOF;
+		return -1;
+
+	case '_':
+		cp = symb;
+		goto talph;
+
+	case '#':
+		domacro();
+		goto l0;
+
+	case '.':
+		c1 = GETC();
+		if(isdigit(c1)) {
+			cp = symb;
+			*cp++ = c;
+			c = c1;
+			c1 = 0;
+			goto casedot;
+		}
+		break;
+
+	case '"':
+		strcpy(symb, "\"<string>\"");
+		cp = alloc(0);
+		c1 = 0;
+
+		/* "..." */
+		for(;;) {
+			c = escchar('"', 0, 1);
+			if(c == EOF)
+				break;
+			if(c & ESC) {
+				cp = allocn(cp, c1, 1);
+				cp[c1++] = c;
+			} else {
+				rune = c;
+				c = runelen(rune);
+				cp = allocn(cp, c1, c);
+				runetochar(cp+c1, &rune);
+				c1 += c;
+			}
+		}
+		yylval.sval.l = c1;
+		do {
+			cp = allocn(cp, c1, 1);
+			cp[c1++] = 0;
+		} while(c1 & MAXALIGN);
+		yylval.sval.s = cp;
+		return LSTRING;
+
+	caselq:
+		/* L"..." */
+		strcpy(symb, "\"L<string>\"");
+		cp = alloc(0);
+		c1 = 0;
+		for(;;) {
+			c = escchar('"', 1, 0);
+			if(c == EOF)
+				break;
+			cp = allocn(cp, c1, sizeof(TRune));
+			*(TRune*)(cp + c1) = c;
+			c1 += sizeof(TRune);
+		}
+		yylval.sval.l = c1;
+		do {
+			cp = allocn(cp, c1, sizeof(TRune));
+			*(TRune*)(cp + c1) = 0;
+			c1 += sizeof(TRune);
+		} while(c1 & MAXALIGN);
+		yylval.sval.s = cp;
+		return LLSTRING;
+
+	case '\'':
+		/* '.' */
+		c = escchar('\'', 0, 0);
+		if(c == EOF)
+			c = '\'';
+		c1 = escchar('\'', 0, 0);
+		if(c1 != EOF) {
+			yyerror("missing '");
+			peekc = c1;
+		}
+		vv = c;
+		yylval.vval = convvtox(vv, TUCHAR);
+		if(yylval.vval != vv)
+			yyerror("overflow in character constant: 0x%lx", c);
+		else
+		if(c & 0x80){
+			nearln = lineno;
+			warn(Z, "sign-extended character constant");
+		}
+		yylval.vval = convvtox(vv, TCHAR);
+		return LCONST;
+
+	case '/':
+		c1 = GETC();
+		if(c1 == '*') {
+			for(;;) {
+				c = getr();
+				while(c == '*') {
+					c = getr();
+					if(c == '/')
+						goto l0;
+				}
+				if(c == EOF) {
+					yyerror("eof in comment");
+					errorexit();
+				}
+			}
+		}
+		if(c1 == '/') {
+			for(;;) {
+				c = getr();
+				if(c == '\n')
+					goto l0;
+				if(c == EOF) {
+					yyerror("eof in comment");
+					errorexit();
+				}
+			}
+		}
+		if(c1 == '=')
+			return LDVE;
+		break;
+
+	case '*':
+		c1 = GETC();
+		if(c1 == '=')
+			return LMLE;
+		break;
+
+	case '%':
+		c1 = GETC();
+		if(c1 == '=')
+			return LMDE;
+		break;
+
+	case '+':
+		c1 = GETC();
+		if(c1 == '+')
+			return LPP;
+		if(c1 == '=')
+			return LPE;
+		break;
+
+	case '-':
+		c1 = GETC();
+		if(c1 == '-')
+			return LMM;
+		if(c1 == '=')
+			return LME;
+		if(c1 == '>')
+			return LMG;
+		break;
+
+	case '>':
+		c1 = GETC();
+		if(c1 == '>') {
+			c = LRSH;
+			c1 = GETC();
+			if(c1 == '=')
+				return LRSHE;
+			break;
+		}
+		if(c1 == '=')
+			return LGE;
+		break;
+
+	case '<':
+		c1 = GETC();
+		if(c1 == '<') {
+			c = LLSH;
+			c1 = GETC();
+			if(c1 == '=')
+				return LLSHE;
+			break;
+		}
+		if(c1 == '=')
+			return LLE;
+		break;
+
+	case '=':
+		c1 = GETC();
+		if(c1 == '=')
+			return LEQ;
+		break;
+
+	case '!':
+		c1 = GETC();
+		if(c1 == '=')
+			return LNE;
+		break;
+
+	case '&':
+		c1 = GETC();
+		if(c1 == '&')
+			return LANDAND;
+		if(c1 == '=')
+			return LANDE;
+		break;
+
+	case '|':
+		c1 = GETC();
+		if(c1 == '|')
+			return LOROR;
+		if(c1 == '=')
+			return LORE;
+		break;
+
+	case '^':
+		c1 = GETC();
+		if(c1 == '=')
+			return LXORE;
+		break;
+
+	default:
+		return c;
+	}
+	peekc = c1;
+	return c;
+
+talph:
+	/*
+	 * cp is set to symb and some
+	 * prefix has been stored
+	 */
+	for(;;) {
+		if(c >= Runeself) {
+			for(c1=0;;) {
+				cp[c1++] = c;
+				if(fullrune(cp, c1))
+					break;
+				c = GETC();
+			}
+			cp += c1;
+			c = GETC();
+			continue;
+		}
+		if(!isalnum(c) && c != '_')
+			break;
+		*cp++ = c;
+		c = GETC();
+	}
+	*cp = 0;
+	if(debug['L'])
+		print("%L: %s\n", lineno, symb);
+	peekc = c;
+	s = lookup();
+	if(s->macro) {
+		newio();
+		cp = ionext->b;
+		macexpand(s, cp);
+		pushio();
+		ionext->link = iostack;
+		iostack = ionext;
+		fi.p = cp;
+		fi.c = strlen(cp);
+		if(peekc != IGN) {
+			cp[fi.c++] = peekc;
+			cp[fi.c] = 0;
+			peekc = IGN;
+		}
+		goto l0;
+	}
+	yylval.sym = s;
+	if(s->class == CTYPEDEF || s->class == CTYPESTR)
+		return LTYPE;
+	return s->lexical;
+
+tnum:
+	c1 = 0;
+	cp = symb;
+	if(c != '0') {
+		c1 |= Numdec;
+		for(;;) {
+			*cp++ = c;
+			c = GETC();
+			if(isdigit(c))
+				continue;
+			goto dc;
+		}
+	}
+	*cp++ = c;
+	c = GETC();
+	if(c == 'x' || c == 'X')
+		for(;;) {
+			*cp++ = c;
+			c = GETC();
+			if(isdigit(c))
+				continue;
+			if(c >= 'a' && c <= 'f')
+				continue;
+			if(c >= 'A' && c <= 'F')
+				continue;
+			if(cp == symb+2)
+				yyerror("malformed hex constant");
+			goto ncu;
+		}
+	if(c < '0' || c > '7')
+		goto dc;
+	for(;;) {
+		if(c >= '0' && c <= '7') {
+			*cp++ = c;
+			c = GETC();
+			continue;
+		}
+		goto ncu;
+	}
+
+dc:
+	if(c == '.')
+		goto casedot;
+	if(c == 'e' || c == 'E')
+		goto casee;
+
+ncu:
+	if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
+		c = GETC();
+		c1 |= Numuns;
+		goto ncu;
+	}
+	if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
+		c = GETC();
+		if(c1 & Numlong)
+			c1 |= Numvlong;
+		c1 |= Numlong;
+		goto ncu;
+	}
+	*cp = 0;
+	peekc = c;
+	if(mpatov(symb, &yylval.vval))
+		yyerror("overflow in constant");
+
+	vv = yylval.vval;
+	if(c1 & Numvlong) {
+		if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
+			c = LUVLCONST;
+			t = TUVLONG;
+			goto nret;
+		}
+		c = LVLCONST;
+		t = TVLONG;
+		goto nret;
+	}
+	if(c1 & Numlong) {
+		if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
+			c = LULCONST;
+			t = TULONG;
+			goto nret;
+		}
+		c = LLCONST;
+		t = TLONG;
+		goto nret;
+	}
+	if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
+		c = LUCONST;
+		t = TUINT;
+		goto nret;
+	}
+	c = LCONST;
+	t = TINT;
+	goto nret;
+
+nret:
+	yylval.vval = convvtox(vv, t);
+	if(yylval.vval != vv){
+		nearln = lineno;
+		warn(Z, "truncated constant: %T %s", types[t], symb);
+	}
+	return c;
+
+casedot:
+	for(;;) {
+		*cp++ = c;
+		c = GETC();
+		if(!isdigit(c))
+			break;
+	}
+	if(c != 'e' && c != 'E')
+		goto caseout;
+
+casee:
+	*cp++ = 'e';
+	c = GETC();
+	if(c == '+' || c == '-') {
+		*cp++ = c;
+		c = GETC();
+	}
+	if(!isdigit(c))
+		yyerror("malformed fp constant exponent");
+	while(isdigit(c)) {
+		*cp++ = c;
+		c = GETC();
+	}
+
+caseout:
+	if(c == 'L' || c == 'l') {
+		c = GETC();
+		c1 |= Numlong;
+	} else
+	if(c == 'F' || c == 'f') {
+		c = GETC();
+		c1 |= Numflt;
+	}
+	*cp = 0;
+	peekc = c;
+	yylval.dval = strtod(symb, nil);
+	if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
+		yyerror("overflow in float constant");
+		yylval.dval = 0;
+	}
+	if(c1 & Numflt)
+		return LFCONST;
+	return LDCONST;
+}
+
+/*
+ * convert a string, s, to vlong in *v
+ * return conversion overflow.
+ * required syntax is [0[x]]d*
+ */
+int
+mpatov(char *s, vlong *v)
+{
+	vlong n, nn;
+	int c;
+
+	n = 0;
+	c = *s;
+	if(c == '0')
+		goto oct;
+	while(c = *s++) {
+		if(c >= '0' && c <= '9')
+			nn = n*10 + c-'0';
+		else
+			goto bad;
+		if(n < 0 && nn >= 0)
+			goto bad;
+		n = nn;
+	}
+	goto out;
+
+oct:
+	s++;
+	c = *s;
+	if(c == 'x' || c == 'X')
+		goto hex;
+	while(c = *s++) {
+		if(c >= '0' || c <= '7')
+			nn = n*8 + c-'0';
+		else
+			goto bad;
+		if(n < 0 && nn >= 0)
+			goto bad;
+		n = nn;
+	}
+	goto out;
+
+hex:
+	s++;
+	while(c = *s++) {
+		if(c >= '0' && c <= '9')
+			c += 0-'0';
+		else
+		if(c >= 'a' && c <= 'f')
+			c += 10-'a';
+		else
+		if(c >= 'A' && c <= 'F')
+			c += 10-'A';
+		else
+			goto bad;
+		nn = n*16 + c;
+		if(n < 0 && nn >= 0)
+			goto bad;
+		n = nn;
+	}
+out:
+	*v = n;
+	return 0;
+
+bad:
+	*v = ~0;
+	return 1;
+}
+
+int
+getc(void)
+{
+	int c;
+
+	if(peekc != IGN) {
+		c = peekc;
+		peekc = IGN;
+	} else
+		c = GETC();
+	if(c == '\n')
+		lineno++;
+	if(c == EOF) {
+		yyerror("End of file");
+		errorexit();
+	}
+	return c;
+}
+
+long
+getr(void)
+{
+	int c, i;
+	char str[UTFmax+1];
+	Rune rune;
+
+
+	c = getc();
+	if(c < Runeself)
+		return c;
+	i = 0;
+	str[i++] = c;
+
+loop:
+	c = getc();
+	str[i++] = c;
+	if(!fullrune(str, i))
+		goto loop;
+	c = chartorune(&rune, str);
+	if(rune == Runeerror && c == 1) {
+		nearln = lineno;
+		diag(Z, "illegal rune in string");
+		for(c=0; c<i; c++)
+			print(" %.2x", *(uchar*)(str+c));
+		print("\n");
+	}
+	return rune;
+}
+
+int
+getnsc(void)
+{
+	int c;
+
+	if(peekc != IGN) {
+		c = peekc;
+		peekc = IGN;
+	} else
+		c = GETC();
+	for(;;) {
+		if(c >= Runeself || !isspace(c))
+			return c;
+		if(c == '\n') {
+			lineno++;
+			return c;
+		}
+		c = GETC();
+	}
+}
+
+void
+unget(int c)
+{
+
+	peekc = c;
+	if(c == '\n')
+		lineno--;
+}
+
+long
+escchar(long e, int longflg, int escflg)
+{
+	long c, l;
+	int i;
+
+loop:
+	c = getr();
+	if(c == '\n') {
+		yyerror("newline in string");
+		return EOF;
+	}
+	if(c != '\\') {
+		if(c == e)
+			c = EOF;
+		return c;
+	}
+	c = getr();
+	if(c == 'x') {
+		/*
+		 * note this is not ansi,
+		 * supposed to only accept 2 hex
+		 */
+		i = 2;
+		if(longflg)
+			i = 6;
+		l = 0;
+		for(; i>0; i--) {
+			c = getc();
+			if(c >= '0' && c <= '9') {
+				l = l*16 + c-'0';
+				continue;
+			}
+			if(c >= 'a' && c <= 'f') {
+				l = l*16 + c-'a' + 10;
+				continue;
+			}
+			if(c >= 'A' && c <= 'F') {
+				l = l*16 + c-'A' + 10;
+				continue;
+			}
+			unget(c);
+			break;
+		}
+		if(escflg)
+			l |= ESC;
+		return l;
+	}
+	if(c >= '0' && c <= '7') {
+		/*
+		 * note this is not ansi,
+		 * supposed to only accept 3 oct
+		 */
+		i = 2;
+		if(longflg)
+			i = 8;
+		l = c - '0';
+		for(; i>0; i--) {
+			c = getc();
+			if(c >= '0' && c <= '7') {
+				l = l*8 + c-'0';
+				continue;
+			}
+			unget(c);
+		}
+		if(escflg)
+			l |= ESC;
+		return l;
+	}
+	switch(c)
+	{
+	case '\n':	goto loop;
+	case 'n':	return '\n';
+	case 't':	return '\t';
+	case 'b':	return '\b';
+	case 'r':	return '\r';
+	case 'f':	return '\f';
+	case 'a':	return '\a';
+	case 'v':	return '\v';
+	}
+	return c;
+}
+
+struct
+{
+	char	*name;
+	ushort	lexical;
+	ushort	type;
+} itab[] =
+{
+	"auto",		LAUTO,		0,
+	"break",	LBREAK,		0,
+	"case",		LCASE,		0,
+	"char",		LCHAR,		TCHAR,
+	"const",	LCONSTNT,	0,
+	"continue",	LCONTINUE,	0,
+	"default",	LDEFAULT,	0,
+	"do",		LDO,		0,
+	"double",	LDOUBLE,	TDOUBLE,
+	"else",		LELSE,		0,
+	"enum",		LENUM,		0,
+	"extern",	LEXTERN,	0,
+	"float",	LFLOAT,		TFLOAT,
+	"for",		LFOR,		0,
+	"goto",		LGOTO,		0,
+	"if",		LIF,		0,
+	"inline",	LINLINE,	0,
+	"int",		LINT,		TINT,
+	"long",		LLONG,		TLONG,
+	"register",	LREGISTER,	0,
+	"restrict",	LRESTRICT,	0,
+	"return",	LRETURN,	0,
+	"SET",		LSET,		0,
+	"short",	LSHORT,		TSHORT,
+	"signed",	LSIGNED,	0,
+	"signof",	LSIGNOF,	0,
+	"sizeof",	LSIZEOF,	0,
+	"static",	LSTATIC,	0,
+	"struct",	LSTRUCT,	0,
+	"switch",	LSWITCH,	0,
+	"typedef",	LTYPEDEF,	0,
+	"typestr",	LTYPESTR,	0,
+	"union",	LUNION,		0,
+	"unsigned",	LUNSIGNED,	0,
+	"USED",		LUSED,		0,
+	"void",		LVOID,		TVOID,
+	"volatile",	LVOLATILE,	0,
+	"while",	LWHILE,		0,
+	0
+};
+
+void
+cinit(void)
+{
+	Sym *s;
+	int i;
+	Type *t;
+
+	nerrors = 0;
+	lineno = 1;
+	iostack = I;
+	iofree = I;
+	peekc = IGN;
+	nhunk = 0;
+
+	types[TXXX] = T;
+	types[TCHAR] = typ(TCHAR, T);
+	types[TUCHAR] = typ(TUCHAR, T);
+	types[TSHORT] = typ(TSHORT, T);
+	types[TUSHORT] = typ(TUSHORT, T);
+	types[TINT] = typ(TINT, T);
+	types[TUINT] = typ(TUINT, T);
+	types[TLONG] = typ(TLONG, T);
+	types[TULONG] = typ(TULONG, T);
+	types[TVLONG] = typ(TVLONG, T);
+	types[TUVLONG] = typ(TUVLONG, T);
+	types[TFLOAT] = typ(TFLOAT, T);
+	types[TDOUBLE] = typ(TDOUBLE, T);
+	types[TVOID] = typ(TVOID, T);
+	types[TENUM] = typ(TENUM, T);
+	types[TFUNC] = typ(TFUNC, types[TINT]);
+	types[TIND] = typ(TIND, types[TVOID]);
+
+	for(i=0; i<NHASH; i++)
+		hash[i] = S;
+	for(i=0; itab[i].name; i++) {
+		s = slookup(itab[i].name);
+		s->lexical = itab[i].lexical;
+		if(itab[i].type != 0)
+			s->type = types[itab[i].type];
+	}
+	blockno = 0;
+	autobn = 0;
+	autoffset = 0;
+
+	t = typ(TARRAY, types[TCHAR]);
+	t->width = 0;
+	symstring = slookup(".string");
+	symstring->class = CSTATIC;
+	symstring->type = t;
+
+	t = typ(TARRAY, types[TCHAR]);
+	t->width = 0;
+
+	nodproto = new(OPROTO, Z, Z);
+	dclstack = D;
+
+	pathname = allocn(pathname, 0, 100);
+	if(mygetwd(pathname, 99) == 0) {
+		pathname = allocn(pathname, 100, 900);
+		if(mygetwd(pathname, 999) == 0)
+			strcpy(pathname, "/???");
+	}
+
+	fmtinstall('O', Oconv);
+	fmtinstall('T', Tconv);
+	fmtinstall('F', FNconv);
+	fmtinstall('L', Lconv);
+	fmtinstall('Q', Qconv);
+	fmtinstall('|', VBconv);
+}
+
+int
+filbuf(void)
+{
+	Io *i;
+
+loop:
+	i = iostack;
+	if(i == I)
+		return EOF;
+	if(i->f < 0)
+		goto pop;
+	fi.c = read(i->f, i->b, BUFSIZ) - 1;
+	if(fi.c < 0) {
+		close(i->f);
+		linehist(0, 0);
+		goto pop;
+	}
+	fi.p = i->b + 1;
+	return i->b[0] & 0xff;
+
+pop:
+	iostack = i->link;
+	i->link = iofree;
+	iofree = i;
+	i = iostack;
+	if(i == I)
+		return EOF;
+	fi.p = i->p;
+	fi.c = i->c;
+	if(--fi.c < 0)
+		goto loop;
+	return *fi.p++ & 0xff;
+}
+
+int
+Oconv(Fmt *fp)
+{
+	int a;
+
+	a = va_arg(fp->args, int);
+	if(a < OXXX || a > OEND)
+		return fmtprint(fp, "***badO %d***", a);
+
+	return fmtstrcpy(fp, onames[a]);
+}
+
+int
+Lconv(Fmt *fp)
+{
+	char str[STRINGSZ], s[STRINGSZ];
+	Hist *h;
+	struct
+	{
+		Hist*	incl;	/* start of this include file */
+		long	idel;	/* delta line number to apply to include */
+		Hist*	line;	/* start of this #line directive */
+		long	ldel;	/* delta line number to apply to #line */
+	} a[HISTSZ];
+	long l, d;
+	int i, n;
+
+	l = va_arg(fp->args, long);
+	n = 0;
+	for(h = hist; h != H; h = h->link) {
+		if(l < h->line)
+			break;
+		if(h->name) {
+			if(h->offset != 0) {		/* #line directive, not #pragma */
+				if(n > 0 && n < HISTSZ && h->offset >= 0) {
+					a[n-1].line = h;
+					a[n-1].ldel = h->line - h->offset + 1;
+				}
+			} else {
+				if(n < HISTSZ) {	/* beginning of file */
+					a[n].incl = h;
+					a[n].idel = h->line;
+					a[n].line = 0;
+				}
+				n++;
+			}
+			continue;
+		}
+		n--;
+		if(n > 0 && n < HISTSZ) {
+			d = h->line - a[n].incl->line;
+			a[n-1].ldel += d;
+			a[n-1].idel += d;
+		}
+	}
+	if(n > HISTSZ)
+		n = HISTSZ;
+	str[0] = 0;
+	for(i=n-1; i>=0; i--) {
+		if(i != n-1) {
+			if(fp->flags & ~(FmtWidth|FmtPrec))	/* BUG ROB - was f3 */
+				break;
+			strcat(str, " ");
+		}
+		if(a[i].line)
+			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
+				a[i].line->name, l-a[i].ldel+1,
+				a[i].incl->name, l-a[i].idel+1);
+		else
+			snprint(s, STRINGSZ, "%s:%ld",
+				a[i].incl->name, l-a[i].idel+1);
+		if(strlen(s)+strlen(str) >= STRINGSZ-10)
+			break;
+		strcat(str, s);
+		l = a[i].incl->line - 1;	/* now print out start of this file */
+	}
+	if(n == 0)
+		strcat(str, "<eof>");
+	return fmtstrcpy(fp, str);
+}
+
+int
+Tconv(Fmt *fp)
+{
+	char str[STRINGSZ+20], s[STRINGSZ+20];
+	Type *t, *t1;
+	int et;
+	long n;
+
+	str[0] = 0;
+	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
+		et = t->etype;
+		if(str[0])
+			strcat(str, " ");
+		if(t->garb&~GINCOMPLETE) {
+			sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
+			if(strlen(str) + strlen(s) < STRINGSZ)
+				strcat(str, s);
+		}
+		sprint(s, "%s", tnames[et]);
+		if(strlen(str) + strlen(s) < STRINGSZ)
+			strcat(str, s);
+		if(et == TFUNC && (t1 = t->down)) {
+			sprint(s, "(%T", t1);
+			if(strlen(str) + strlen(s) < STRINGSZ)
+				strcat(str, s);
+			while(t1 = t1->down) {
+				sprint(s, ", %T", t1);
+				if(strlen(str) + strlen(s) < STRINGSZ)
+					strcat(str, s);
+			}
+			if(strlen(str) + strlen(s) < STRINGSZ)
+				strcat(str, ")");
+		}
+		if(et == TARRAY) {
+			n = t->width;
+			if(t->link && t->link->width)
+				n /= t->link->width;
+			sprint(s, "[%ld]", n);
+			if(strlen(str) + strlen(s) < STRINGSZ)
+				strcat(str, s);
+		}
+		if(t->nbits) {
+			sprint(s, " %d:%d", t->shift, t->nbits);
+			if(strlen(str) + strlen(s) < STRINGSZ)
+				strcat(str, s);
+		}
+		if(typesu[et]) {
+			if(t->tag) {
+				strcat(str, " ");
+				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
+					strcat(str, t->tag->name);
+			} else
+				strcat(str, " {}");
+			break;
+		}
+	}
+	return fmtstrcpy(fp, str);
+}
+
+int
+FNconv(Fmt *fp)
+{
+	char *str;
+	Node *n;
+
+	n = va_arg(fp->args, Node*);
+	str = "<indirect>";
+	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
+		str = n->sym->name;
+	return fmtstrcpy(fp, str);
+}
+
+int
+Qconv(Fmt *fp)
+{
+	char str[STRINGSZ+20], *s;
+	long b;
+	int i;
+
+	str[0] = 0;
+	for(b = va_arg(fp->args, long); b;) {
+		i = bitno(b);
+		if(str[0])
+			strcat(str, " ");
+		s = qnames[i];
+		if(strlen(str) + strlen(s) >= STRINGSZ)
+			break;
+		strcat(str, s);
+		b &= ~(1L << i);
+	}
+	return fmtstrcpy(fp, str);
+}
+
+int
+VBconv(Fmt *fp)
+{
+	char str[STRINGSZ];
+	int i, n, t, pc;
+
+	n = va_arg(fp->args, int);
+	pc = 0;	/* BUG: was printcol */
+	i = 0;
+	while(pc < n) {
+		t = (pc+4) & ~3;
+		if(t <= n) {
+			str[i++] = '\t';
+			pc = t;
+			continue;
+		}
+		str[i++] = ' ';
+		pc++;
+	}
+	str[i] = 0;
+
+	return fmtstrcpy(fp, str);
+}
+
+/*
+ * real allocs
+ */
+void*
+alloc(long n)
+{
+	void *p;
+
+	while((uintptr)hunk & MAXALIGN) {
+		hunk++;
+		nhunk--;
+	}
+	while(nhunk < n)
+		gethunk();
+	p = hunk;
+	nhunk -= n;
+	hunk += n;
+	return p;
+}
+
+void*
+allocn(void *p, long on, long n)
+{
+	void *q;
+
+	q = (uchar*)p + on;
+	if(q != hunk || nhunk < n) {
+		while(nhunk < on+n)
+			gethunk();
+		memmove(hunk, p, on);
+		p = hunk;
+		hunk += on;
+		nhunk -= on;
+	}
+	hunk += n;
+	nhunk -= n;
+	return p;
+}
+
+void
+setinclude(char *p)
+{
+	int i;
+	char *e, **np;
+
+	while(*p != 0) {
+		e = strchr(p, ' ');
+		if(e != 0)
+			*e = '\0';
+
+		for(i=0; i < ninclude; i++)
+			if(strcmp(p, include[i]) == 0)
+				break;
+
+		if(i >= ninclude){
+			if(i >= maxinclude){
+				maxinclude += 20;
+				np = alloc(maxinclude * sizeof *np);
+				if(include != nil)
+					memmove(np, include, (maxinclude - 20) * sizeof *np);
+				include = np;
+			}
+			include[ninclude++] = p;
+		}
+
+		if(e == 0)
+			break;
+		p = e+1;
+	}
+}

+ 7 - 8
sys/src/cmd/4c/list.c

@@ -4,7 +4,6 @@
 void
 listinit(void)
 {
-
 	fmtinstall('A', Aconv);
 	fmtinstall('P', Pconv);
 	fmtinstall('S', Sconv);
@@ -153,7 +152,7 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_VCONST:
-		sprint(str, "$0x%llux", a->vval);
+		sprint(str, "$0x%llux", a->offset);
 		break;
 	}
 	return fmtstrcpy(fp, str);
@@ -216,7 +215,7 @@ Nconv(Fmt *fp)
 	a = va_arg(fp->args, Adr*);
 	s = a->sym;
 	if(s == S) {
-		sprint(str, "%ld", a->offset);
+		sprint(str, "%lld", a->offset);
 		goto out;
 	}
 	switch(a->name) {
@@ -225,23 +224,23 @@ Nconv(Fmt *fp)
 		break;
 
 	case D_NONE:
-		sprint(str, "%ld", a->offset);
+		sprint(str, "%lld", a->offset);
 		break;
 
 	case D_EXTERN:
-		sprint(str, "%s+%ld(SB)", s->name, a->offset);
+		sprint(str, "%s+%lld(SB)", s->name, a->offset);
 		break;
 
 	case D_STATIC:
-		sprint(str, "%s<>+%ld(SB)", s->name, a->offset);
+		sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
 		break;
 
 	case D_AUTO:
-		sprint(str, "%s-%ld(SP)", s->name, -a->offset);
+		sprint(str, "%s-%lld(SP)", s->name, -a->offset);
 		break;
 
 	case D_PARAM:
-		sprint(str, "%s+%ld(FP)", s->name, a->offset);
+		sprint(str, "%s+%lld(FP)", s->name, a->offset);
 		break;
 	}
 out:

+ 77 - 0
sys/src/cmd/4c/machcap.c

@@ -0,0 +1,77 @@
+#include "gc.h"
+
+int
+machcap(Node *n)
+{
+
+	if(n == Z)
+		return 1;	/* test */
+
+	switch(n->op) {
+	case OMUL:
+	case OLMUL:
+	case OASMUL:
+	case OASLMUL:
+		if(typechlv[n->type->etype])
+			return 1;
+		break;
+
+	case OADD:
+	case OAND:
+	case OOR:
+	case OSUB:
+	case OXOR:
+	case OASHL:
+	case OLSHR:
+	case OASHR:
+		if(typechlv[n->left->type->etype])
+			return 1;
+		break;
+
+	case OCAST:
+		return 1;
+
+	case OCOND:
+	case OCOMMA:
+	case OLIST:
+	case OANDAND:
+	case OOROR:
+	case ONOT:
+		return 1;
+
+	case OASADD:
+	case OASSUB:
+	case OASAND:
+	case OASOR:
+	case OASXOR:
+		return 1;
+
+	case OASASHL:
+	case OASASHR:
+	case OASLSHR:
+		return 1;
+
+	case OPOSTINC:
+	case OPOSTDEC:
+	case OPREINC:
+	case OPREDEC:
+		return 1;
+
+	case OEQ:
+	case ONE:
+	case OLE:
+	case OGT:
+	case OLT:
+	case OGE:
+	case OHI:
+	case OHS:
+	case OLO:
+	case OLS:
+		return 1;
+
+	case OCOM:
+	case ONEG:
+		break;
+	}
+	return 0;
+}

+ 1 - 1
sys/src/cmd/4c/mkenam

@@ -1,4 +1,4 @@
-ed - ../vc/v.out.h <<'!'
+ed - ../4c/4.out.h <<'!'
 v/^	A/d
 ,s/^	A/	"/
 g/ .*$/s///

+ 19 - 11
sys/src/cmd/4c/mkfile

@@ -5,38 +5,46 @@ OFILES=\
 	cgen.$O\
 	enam.$O\
 	list.$O\
+	machcap.$O\
+	mul.$O\
 	peep.$O\
+	pgen.$O\
+	pswt.$O\
 	reg.$O\
 	sgen.$O\
 	swt.$O\
 	txt.$O\
-	mul.$O\
 
 HFILES=\
 	gc.h\
-	../vc/v.out.h\
+	4.out.h\
 	../cc/cc.h\
 
 LIB=../cc/cc.a$O
 
 BIN=/$objtype/bin
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-
 </sys/src/cmd/mkone
 
-enam.$O:	../vc/enam.c
-	$CC $CFLAGS ../vc/enam.c
+enam.c:	4.out.h
+	rc mkenam
 
 $LIB:
-	cd ../cc
+	rfork
+	bind lex.c ../cc/lex.c	# hack
+	builtin cd ../cc		# for acme
 	mk install
 	mk clean
 
+%.$O: ../cc/%.c
+	$CC $CFLAGS ../cc/$stem.c
+
 t:V:	$O.out
 	$O.out -S t
 	$LD -o t.out t.$O
 	t.out
+
+# XXX
+clean:	cleanlib
+
+cleanlib:
+	rm -f ../cc/cc.a[$OS]

+ 50 - 4
sys/src/cmd/4c/peep.c

@@ -34,6 +34,7 @@ peep(void)
 		case ADATA:
 		case AGLOBL:
 		case ANAME:
+		case ASIGNAME:
 			p = p->link;
 		}
 	}
@@ -42,7 +43,7 @@ loop1:
 	t = 0;
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
-		if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
+		if(/*p->as == AMOVW ||*/ p->as == AMOVV || p->as == AMOVF || p->as == AMOVD)
 		if(regtyp(&p->to)) {
 			if(regtyp(&p->from))
 			if(p->from.type == p->to.type) {
@@ -84,6 +85,8 @@ loop1:
 		case AMOVHU:
 		case AMOVB:
 		case AMOVBU:
+		case AMOVW:
+		case AMOVWU:
 			if(p->to.type != D_REG)
 				continue;
 			break;
@@ -229,6 +232,18 @@ subprop(Reg *r0)
 		case ADIV:
 		case ADIVU:
 
+		case AADDV:
+		case AADDVU:
+		case ASUBV:
+		case ASUBVU:
+		case ASLLV:
+		case ASRLV:
+		case ASRAV:
+		case AMULV:
+		case AMULVU:
+		case ADIVV:
+		case ADIVVU:
+
 		case AADDD:
 		case AADDF:
 		case ASUBD:
@@ -248,6 +263,7 @@ subprop(Reg *r0)
 		case AMOVF:
 		case AMOVD:
 		case AMOVW:
+		case AMOVV:
 			if(p->to.type == v1->type)
 			if(p->to.reg == v1->reg)
 				goto gotit;
@@ -415,16 +431,23 @@ copyu(Prog *p, Adr *v, Adr *s)
 
 	case ANOP:	/* read, write */
 	case AMOVW:
+	case AMOVV:
 	case AMOVF:
 	case AMOVD:
 	case AMOVH:
 	case AMOVHU:
 	case AMOVB:
 	case AMOVBU:
-	case AMOVDW:
-	case AMOVWD:
 	case AMOVFD:
 	case AMOVDF:
+	case AMOVDW:
+	case AMOVWD:
+	case AMOVFW:
+	case AMOVWF:
+	case AMOVDV:
+	case AMOVVD:
+	case AMOVFV:
+	case AMOVVF:
 		if(s != A) {
 			if(copysub(&p->from, v, s, 1))
 				return 1;
@@ -463,6 +486,18 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case ADIV:
 	case ADIVU:
 
+	case AADDV:
+	case AADDVU:
+	case ASUBV:
+	case ASUBVU:
+	case ASLLV:
+	case ASRLV:
+	case ASRAV:
+	case AMULV:
+	case AMULVU:
+	case ADIVV:
+	case ADIVVU:
+
 	case AADDF:
 	case AADDD:
 	case ASUBF:
@@ -568,7 +603,6 @@ copyu(Prog *p, Adr *v, Adr *s)
 				return 3;
 		return 0;
 	}
-	return 0;
 }
 
 int
@@ -600,6 +634,18 @@ a2type(Prog *p)
 	case AMULU:
 	case ADIV:
 	case ADIVU:
+
+	case AADDV:
+	case AADDVU:
+	case ASUBV:
+	case ASUBVU:
+	case ASLLV:
+	case ASRLV:
+	case ASRAV:
+	case AMULV:
+	case AMULVU:
+	case ADIVV:
+	case ADIVVU:
 		return D_REG;
 
 	case ACMPEQD:

+ 7 - 3
sys/src/cmd/4c/reg.c

@@ -80,6 +80,7 @@ regopt(Prog *p)
 		case ADATA:
 		case AGLOBL:
 		case ANAME:
+		case ASIGNAME:
 			continue;
 		}
 		r = rega();
@@ -284,6 +285,8 @@ loop2:
 					print(" rb=%B", r->refbehind);
 				if(bany(&r->calbehind))
 					print(" cb=%B", r->calbehind);
+				if(bany(&r->regdiff))
+					print(" rd=%B", r->regdiff);
 			}
 			print("\n");
 		}
@@ -408,6 +411,7 @@ brk:
 			case ADATA:
 			case AGLOBL:
 			case ANAME:
+			case ASIGNAME:
 				break;
 			}
 		}
@@ -598,7 +602,7 @@ out:
 	if(n == D_PARAM)
 		for(z=0; z<BITS; z++)
 			params.b[z] |= bit.b[z];
-	if(v->etype != et || !typechlpfd[et])	/* funny punning */
+	if(v->etype != et || (!typechlpfd[et] && !typev[et]))	/* funny punning */
 		for(z=0; z<BITS; z++)
 			addrs.b[z] |= bit.b[z];
 	if(t == D_CONST) {
@@ -725,7 +729,7 @@ rpolca(long *idom, long rpo1, long rpo2)
 		while(rpo1 < rpo2){
 			t = idom[rpo2];
 			if(t >= rpo2)
-				sysfatal("bad idom");
+				fatal(Z, "bad idom");
 			rpo2 = t;
 		}
 	}
@@ -781,7 +785,7 @@ loopit(Reg *r, long nr)
 
 	d = postorder(r, rpo2r, 0);
 	if(d > nr)
-		sysfatal("too many reg nodes");
+		fatal(Z, "too many reg nodes");
 	nr = d;
 	for(i = 0; i < nr / 2; i++){
 		r1 = rpo2r[i];

+ 16 - 362
sys/src/cmd/4c/sgen.c

@@ -1,344 +1,5 @@
 #include "gc.h"
 
-void
-codgen(Node *n, Node *nn)
-{
-	Prog *sp;
-	Node *n1, nod, nod1;
-
-	cursafe = 0;
-	curarg = 0;
-	maxargsafe = 0;
-
-	/*
-	 * isolate name
-	 */
-	for(n1 = nn;; n1 = n1->left) {
-		if(n1 == Z) {
-			diag(nn, "cant find function name");
-			return;
-		}
-		if(n1->op == ONAME)
-			break;
-	}
-	nearln = nn->lineno;
-	gpseudo(ATEXT, n1->sym, nodconst(stkoff));
-	sp = p;
-
-	/*
-	 * isolate first argument
-	 */
-	if(REGARG) {
-		if(typesu[thisfn->link->etype]) {
-			nod1 = *nodret->left;
-			nodreg(&nod, &nod1, REGARG);
-			gopcode(OAS, &nod, Z, &nod1);
-		} else
-		if(firstarg && typechlp[firstargtype->etype]) {
-			nod1 = *nodret->left;
-			nod1.sym = firstarg;
-			nod1.type = firstargtype;
-			nod1.xoffset = align(0, firstargtype, Aarg1);
-			nod1.etype = firstargtype->etype;
-			nodreg(&nod, &nod1, REGARG);
-			gopcode(OAS, &nod, Z, &nod1);
-		}
-	}
-
-	retok = 0;
-	gen(n);
-	if(!retok)
-		if(thisfn->link->etype != TVOID)
-			warn(Z, "no return at end of function: %s", n1->sym->name);
-	noretval(3);
-	gbranch(ORETURN);
-
-	if(!debug['N'] || debug['R'] || debug['P'])
-		regopt(sp);
-
-	sp->to.offset += maxargsafe;
-}
-
-void
-gen(Node *n)
-{
-	Node *l, nod;
-	Prog *sp, *spc, *spb;
-	Case *cn;
-	u64int sbc, scc;
-	int o;
-
-loop:
-	if(n == Z)
-		return;
-	nearln = n->lineno;
-	o = n->op;
-	if(debug['G'])
-		if(o != OLIST)
-			print("%L %O\n", nearln, o);
-
-	retok = 0;
-	switch(o) {
-
-	default:
-		complex(n);
-		cgen(n, Z);
-		break;
-
-	case OLIST:
-		gen(n->left);
-
-	rloop:
-		n = n->right;
-		goto loop;
-
-	case ORETURN:
-		retok = 1;
-		complex(n);
-		if(n->type == T)
-			break;
-		l = n->left;
-		if(l == Z) {
-			noretval(3);
-			gbranch(ORETURN);
-			break;
-		}
-		if(typesu[n->type->etype]) {
-			sugen(l, nodret, n->type->width);
-			noretval(3);
-			gbranch(ORETURN);
-			break;
-		}
-		regret(&nod, n);
-		cgen(l, &nod);
-		regfree(&nod);
-		if(typefd[n->type->etype])
-			noretval(1);
-		else
-			noretval(2);
-		gbranch(ORETURN);
-		break;
-
-	case OLABEL:
-		l = n->left;
-		if(l) {
-			l->pc = pc;
-			if(l->label)
-				patch(l->label, pc);
-		}
-		gbranch(OGOTO);	/* prevent self reference in reg */
-		patch(p, pc);
-		goto rloop;
-
-	case OGOTO:
-		retok = 1;
-		n = n->left;
-		if(n == Z)
-			return;
-		if(n->complex == 0) {
-			diag(Z, "label undefined: %s", n->sym->name);
-			return;
-		}
-		gbranch(OGOTO);
-		if(n->pc) {
-			patch(p, n->pc);
-			return;
-		}
-		if(n->label)
-			patch(n->label, pc-1);
-		n->label = p;
-		return;
-
-	case OCASE:
-		l = n->left;
-		if(cases == C)
-			diag(n, "case/default outside a switch");
-		if(l == Z) {
-			cas();
-			cases->val = 0;
-			cases->def = 1;
-			cases->label = pc;
-			goto rloop;
-		}
-		complex(l);
-		if(l->type == T)
-			goto rloop;
-		if(l->op == OCONST)
-		if(typechl[l->type->etype]) {
-			cas();
-			cases->val = l->vconst;
-			cases->def = 0;
-			cases->label = pc;
-			goto rloop;
-		}
-		diag(n, "case expression must be integer constant");
-		goto rloop;
-
-	case OSWITCH:
-		l = n->left;
-		complex(l);
-		if(l->type == T)
-			break;
-		if(!typechl[l->type->etype]) {
-			diag(n, "switch expression must be integer");
-			break;
-		}
-
-		gbranch(OGOTO);		/* entry */
-		sp = p;
-
-		cn = cases;
-		cases = C;
-		cas();
-
-		sbc = breakpc;
-		breakpc = pc;
-		gbranch(OGOTO);
-		spb = p;
-
-		gen(n->right);
-		gbranch(OGOTO);
-		patch(p, breakpc);
-
-		patch(sp, pc);
-		regalloc(&nod, l, Z);
-		nod.type = types[TLONG];
-		cgen(l, &nod);
-		doswit(&nod);
-		regfree(&nod);
-		patch(spb, pc);
-
-		cases = cn;
-		breakpc = sbc;
-		break;
-
-	case OWHILE:
-	case ODWHILE:
-		l = n->left;
-		gbranch(OGOTO);		/* entry */
-		sp = p;
-
-		scc = continpc;
-		continpc = pc;
-		gbranch(OGOTO);
-		spc = p;
-
-		sbc = breakpc;
-		breakpc = pc;
-		gbranch(OGOTO);
-		spb = p;
-
-		patch(spc, pc);
-		if(n->op == OWHILE)
-			patch(sp, pc);
-		bcomplex(l);		/* test */
-		patch(p, breakpc);
-
-		if(n->op == ODWHILE)
-			patch(sp, pc);
-		gen(n->right);		/* body */
-		gbranch(OGOTO);
-		patch(p, continpc);
-
-		patch(spb, pc);
-		continpc = scc;
-		breakpc = sbc;
-		break;
-
-	case OFOR:
-		l = n->left;
-		gen(l->right->left);	/* init */
-		gbranch(OGOTO);		/* entry */
-		sp = p;
-
-		scc = continpc;
-		continpc = pc;
-		gbranch(OGOTO);
-		spc = p;
-
-		sbc = breakpc;
-		breakpc = pc;
-		gbranch(OGOTO);
-		spb = p;
-
-		patch(spc, pc);
-		gen(l->right->right);	/* inc */
-		patch(sp, pc);
-		if(l->left != Z) {	/* test */
-			bcomplex(l->left);
-			patch(p, breakpc);
-		}
-		gen(n->right);		/* body */
-		gbranch(OGOTO);
-		patch(p, continpc);
-
-		patch(spb, pc);
-		continpc = scc;
-		breakpc = sbc;
-		break;
-
-	case OCONTINUE:
-		if(continpc < 0) {
-			diag(n, "continue not in a loop");
-			break;
-		}
-		gbranch(OGOTO);
-		patch(p, continpc);
-		break;
-
-	case OBREAK:
-		if(breakpc < 0) {
-			diag(n, "break not in a loop");
-			break;
-		}
-		gbranch(OGOTO);
-		patch(p, breakpc);
-		break;
-
-	case OIF:
-		l = n->left;
-		bcomplex(l);
-		sp = p;
-		if(n->right->left != Z)
-			gen(n->right->left);
-		if(n->right->right != Z) {
-			gbranch(OGOTO);
-			patch(sp, pc);
-			sp = p;
-			gen(n->right->right);
-		}
-		patch(sp, pc);
-		break;
-
-	case OSET:
-	case OUSED:
-		usedset(n->left, o);
-		break;
-	}
-}
-
-void
-usedset(Node *n, int o)
-{
-	if(n->op == OLIST) {
-		usedset(n->left, o);
-		usedset(n->right, o);
-		return;
-	}
-	complex(n);
-	switch(n->op) {
-	case OADDR:	/* volatile */
-		gins(ANOP, n, Z);
-		break;
-	case ONAME:
-		if(o == OSET)
-			gins(ANOP, Z, n);
-		else
-			gins(ANOP, n, Z);
-		break;
-	}
-}
-
 void
 noretval(int n)
 {
@@ -450,21 +111,19 @@ xcom(Node *n)
 	case OLMUL:
 		xcom(l);
 		xcom(r);
-		t = vlog(r);
-		if(t >= 0) {
-			n->op = OASHL;
-			r->vconst = t;
-			r->type = types[TINT];
-		}
 		t = vlog(l);
 		if(t >= 0) {
-			n->op = OASHL;
 			n->left = r;
 			n->right = l;
-			r = l;
-			l = n->left;
+			l = r;
+			r = n->right;
+		}
+		t = vlog(r);
+		if(t >= 0) {
+			n->op = OASHL;
 			r->vconst = t;
 			r->type = types[TINT];
+			simplifyshift(n);
 		}
 		break;
 
@@ -487,6 +146,7 @@ xcom(Node *n)
 			n->op = OLSHR;
 			r->vconst = t;
 			r->type = types[TINT];
+			simplifyshift(n);
 		}
 		break;
 
@@ -510,6 +170,14 @@ xcom(Node *n)
 		}
 		break;
 
+	case OLSHR:
+	case OASHL:
+	case OASHR:
+		xcom(l);
+		xcom(r);
+		simplifyshift(n);
+		break;
+
 	default:
 		if(l != Z)
 			xcom(l);
@@ -553,17 +221,3 @@ xcom(Node *n)
 		break;
 	}
 }
-
-void
-bcomplex(Node *n)
-{
-
-	complex(n);
-	if(n->type != T)
-	if(tcompat(n, T, n->type, tnot))
-		n->type = T;
-	if(n->type != T)
-		boolgen(n, 1, Z);
-	else
-		gbranch(OGOTO);
-}

+ 84 - 178
sys/src/cmd/4c/swt.c

@@ -1,62 +1,17 @@
 #include "gc.h"
 
-int
-swcmp(const void *a1, const void *a2)
-{
-	C1 *p1, *p2;
-
-	p1 = (C1*)a1;
-	p2 = (C1*)a2;
-	if(p1->val < p2->val)
-		return -1;
-	return  p1->val > p2->val;
-}
-
 void
-doswit(Node *n)
+swit1(C1 *q, int nc, long def, Node *n)
 {
-	Case *c;
-	C1 *q, *iq;
-	long def, nc, i;
 	Node tn;
 
-	def = 0;
-	nc = 0;
-	for(c = cases; c->link != C; c = c->link) {
-		if(c->def) {
-			if(def)
-				diag(n, "more than one default in switch");
-			def = c->label;
-			continue;
-		}
-		nc++;
-	}
-
-	iq = alloc(nc*sizeof(C1));
-	q = iq;
-	for(c = cases; c->link != C; c = c->link) {
-		if(c->def)
-			continue;
-		q->label = c->label;
-		q->val = c->val;
-		q++;
-	}
-	qsort(iq, nc, sizeof(C1), swcmp);
-	if(debug['W'])
-		for(i=0; i<nc; i++)
-			print("case %2ld: = %.8lux\n", i, iq[i].val);
-	if(def == 0)
-		def = breakpc;
-	for(i=0; i<nc-1; i++)
-		if(iq[i].val == iq[i+1].val)
-			diag(n, "duplicate cases in switch %ld", iq[i].val);
 	regalloc(&tn, &regnode, Z);
-	swit1(iq, nc, def, n, &tn);
+	swit2(q, nc, def, n, &tn);
 	regfree(&tn);
 }
 
 void
-swit1(C1 *q, int nc, long def, Node *n, Node *tn)
+swit2(C1 *q, int nc, long def, Node *n, Node *tn)
 {
 	C1 *r;
 	int i;
@@ -64,8 +19,8 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn)
 
 	if(nc < 5) {
 		for(i=0; i<nc; i++) {
-			if(debug['W'])
-				print("case = %.8lux\n", q->val);
+			if(debug['K'])
+				print("case = %.8llux\n", q->val);
 			gmove(nodconst(q->val), tn);
 			gopcode(OEQ, n, tn, Z);
 			patch(p, q->label);
@@ -77,29 +32,19 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn)
 	}
 	i = nc / 2;
 	r = q+i;
-	if(debug['W'])
-		print("case > %.8lux\n", r->val);
+	if(debug['K'])
+		print("case > %.8llux\n", r->val);
 	gmove(nodconst(r->val), tn);
 	gopcode(OLT, tn, n, Z);
 	sp = p;
 	gopcode(OEQ, n, tn, Z);
 	patch(p, r->label);
-	swit1(q, i, def, n, tn);
+	swit2(q, i, def, n, tn);
 
-	if(debug['W'])
-		print("case < %.8lux\n", r->val);
+	if(debug['K'])
+		print("case < %.8llux\n", r->val);
 	patch(sp, pc);
-	swit1(r+1, nc-i-1, def, n, tn);
-}
-
-void
-cas(void)
-{
-	Case *c;
-
-	c = alloc(sizeof(*c));
-	c->link = cases;
-	cases = c;
+	swit2(r+1, nc-i-1, def, n, tn);
 }
 
 void
@@ -179,6 +124,8 @@ outstring(char *s, long n)
 {
 	long r;
 
+	if(suppress)
+		return nstring;
 	r = nstring;
 	while(n) {
 		string[mnstring] = *s++;
@@ -197,31 +144,6 @@ outstring(char *s, long n)
 	return r;
 }
 
-long
-outlstring(ushort *s, long n)
-{
-	char buf[2];
-	int c;
-	long r;
-
-	while(nstring & 1)
-		outstring("", 1);
-	r = nstring;
-	while(n > 0) {
-		c = *s++;
-		if(align(0, types[TCHAR], Aarg1)) {
-			buf[0] = c>>8;
-			buf[1] = c;
-		} else {
-			buf[0] = c;
-			buf[1] = c>>8;
-		}
-		outstring(buf, 2);
-		n -= sizeof(ushort);
-	}
-	return r;
-}
-
 int
 mulcon(Node *n, Node *nn)
 {
@@ -313,42 +235,21 @@ loop:
 	goto loop;
 }
 
-void
-nullwarn(Node *l, Node *r)
-{
-	warn(Z, "result of operation not used");
-	if(l != Z)
-		cgen(l, Z);
-	if(r != Z)
-		cgen(r, Z);
-}
-
-void
-sextern(Sym *s, Node *a, long o, long w)
-{
-	long e, lw;
-
-	for(e=0; e<w; e+=NSNAME) {
-		lw = NSNAME;
-		if(w-e < lw)
-			lw = w-e;
-		gpseudo(ADATA, s, nodconst(0));
-		p->from.offset += o+e;
-		p->reg = lw;
-		p->to.type = D_SCONST;
-		memmove(p->to.sval, a->cstring+e, lw);
-	}
-}
-
 void
 gextern(Sym *s, Node *a, long o, long w)
 {
 
 	if(a->op == OCONST && typev[a->type->etype]) {
-		gpseudo(ADATA, s, nodconst(a->vconst>>32));
+		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
+			gpseudo(ADATA, s, nod32const(a->vconst>>32));
+		else
+			gpseudo(ADATA, s, nod32const(a->vconst));
 		p->from.offset += o;
 		p->reg = 4;
-		gpseudo(ADATA, s, nodconst(a->vconst));
+		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
+			gpseudo(ADATA, s, nod32const(a->vconst));
+		else
+			gpseudo(ADATA, s, nod32const(a->vconst>>32));
 		p->from.offset += o + 4;
 		p->reg = 4;
 		return;
@@ -360,7 +261,7 @@ gextern(Sym *s, Node *a, long o, long w)
 		p->to.type = D_CONST;
 }
 
-void	zname(Biobuf*, char*, int, int);
+void	zname(Biobuf*, Sym*, int);
 char*	zaddr(char*, Adr*, int);
 void	zwrite(Biobuf*, Prog*, int, int);
 void	outhist(Biobuf*);
@@ -417,8 +318,8 @@ outcode(void)
 			if(h[sf].type == t)
 			if(h[sf].sym == s)
 				break;
-			zname(&outbuf, s->name, t, sym);
 			s->sym = sym;
+			zname(&outbuf, s, t);
 			h[sym].sym = s;
 			h[sym].type = t;
 			sf = sym;
@@ -437,8 +338,8 @@ outcode(void)
 			if(h[st].type == t)
 			if(h[st].sym == s)
 				break;
-			zname(&outbuf, s->name, t, sym);
 			s->sym = sym;
+			zname(&outbuf, s, t);
 			h[sym].sym = s;
 			h[sym].type = t;
 			st = sym;
@@ -469,12 +370,17 @@ outhist(Biobuf *b)
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
 		op = 0;
+		/* on windows skip drive specifier in pathname */
+		if(systemtype(Windows) && p && p[1] == ':'){
+			p += 2;
+			c = *p;
+		}
 		if(p && p[0] != c && h->offset == 0 && pathname){
 			/* on windows skip drive specifier in pathname */
-			if(systemtype(Windows) && pathname[2] == c) {
+			if(systemtype(Windows) && pathname[1] == ':') {
 				op = p;
 				p = pathname+2;
-				*p = '/';
+				c = *p;
 			} else if(pathname[0] == c){
 				op = p;
 				p = pathname;
@@ -484,8 +390,10 @@ outhist(Biobuf *b)
 			q = utfrune(p, c);
 			if(q) {
 				n = q-p;
-				if(n == 0)
+				if(n == 0){
 					n = 1;	/* leading "/" */
+					*p = '/';	/* don't emit "\" on windows */
+				}
 				q++;
 			} else {
 				n = strlen(p);
@@ -516,24 +424,44 @@ outhist(Biobuf *b)
 }
 
 void
-zname(Biobuf *b, char *n, int t, int s)
+zname(Biobuf *b, Sym *s, int t)
 {
-	char bf[3];
-
-	bf[0] = ANAME;
-	bf[1] = t;	/* type */
-	bf[2] = s;	/* sym */
-	Bwrite(b, bf, 3);
+	char *n, bf[7];
+	ulong sig;
+
+	n = s->name;
+	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
+		sig = sign(s);
+		bf[0] = ASIGNAME;
+		bf[1] = sig;
+		bf[2] = sig>>8;
+		bf[3] = sig>>16;
+		bf[4] = sig>>24;
+		bf[5] = t;
+		bf[6] = s->sym;
+		Bwrite(b, bf, 7);
+		s->sig = SIGDONE;
+	}
+	else{
+		bf[0] = ANAME;
+		bf[1] = t;	/* type */
+		bf[2] = s->sym;	/* sym */
+		Bwrite(b, bf, 3);
+	}
 	Bwrite(b, n, strlen(n)+1);
 }
 
 char*
 zaddr(char *bp, Adr *a, int s)
 {
-	vlong v;
 	long l;
 	Ieee e;
 
+	if(a->type == D_CONST) {
+		l = a->offset;
+		if((vlong)l != a->offset)
+			a->type = D_VCONST;
+	}
 	bp[0] = a->type;
 	bp[1] = a->reg;
 	bp[2] = s;
@@ -552,8 +480,8 @@ zaddr(char *bp, Adr *a, int s)
 	case D_HI:
 		break;
 
-	case D_CONST:
 	case D_OREG:
+	case D_CONST:
 	case D_BRANCH:
 		l = a->offset;
 		bp[0] = l;
@@ -585,50 +513,23 @@ zaddr(char *bp, Adr *a, int s)
 		break;
 
 	case D_VCONST:
-		v = a->vval;
-		bp[0] = v;
-		bp[1] = v>>8;
-		bp[2] = v>>16;
-		bp[3] = v>>24;
-		bp[4] = v>>32;
-		bp[5] = v>>40;
-		bp[6] = v>>48;
-		bp[7] = v>>56;
-		bp += 8;
+		l = a->offset;
+		bp[0] = l;
+		bp[1] = l>>8;
+		bp[2] = l>>16;
+		bp[3] = l>>24;
+		bp += 4;
+		l = a->offset>>32;
+		bp[0] = l;
+		bp[1] = l>>8;
+		bp[2] = l>>16;
+		bp[3] = l>>24;
+		bp += 4;
 		break;
 	}
 	return bp;
 }
 
-void
-ieeedtod(Ieee *ieee, double native)
-{
-	double fr, ho, f;
-	int exp;
-
-	if(native < 0) {
-		ieeedtod(ieee, -native);
-		ieee->h |= 0x80000000L;
-		return;
-	}
-	if(native == 0) {
-		ieee->l = 0;
-		ieee->h = 0;
-		return;
-	}
-	fr = frexp(native, &exp);
-	f = 2097152L;		/* shouldnt use fp constants here */
-	fr = modf(fr*f, &ho);
-	ieee->h = ho;
-	ieee->h &= 0xfffffL;
-	ieee->h |= (exp+1022L) << 20;
-	f = 65536L;
-	fr = modf(fr*f, &ho);
-	ieee->l = ho;
-	ieee->l <<= 16;
-	ieee->l |= (long)(fr*f);
-}
-
 long
 align(long i, Type *t, int op)
 {
@@ -645,6 +546,8 @@ align(long i, Type *t, int op)
 
 	case Asu2:	/* padding at end of a struct */
 		w = SZ_VLONG;
+		if(packflg)
+			w = packflg;
 		break;
 
 	case Ael1:	/* initial allign of struct element */
@@ -653,6 +556,8 @@ align(long i, Type *t, int op)
 		w = ewidth[v->etype];
 		if(w <= 0 || w >= SZ_VLONG)
 			w = SZ_VLONG;
+		if(packflg)
+			w = packflg;
 		break;
 
 	case Ael2:	/* width of a struct element */
@@ -672,13 +577,14 @@ align(long i, Type *t, int op)
 			w = SZ_VLONG;
 			break;
 		}
-		o += SZ_LONG - w;	/* big endian adjustment */
+		if(thechar == '4')
+			o += SZ_VLONG - w;	/* big endian adjustment */
 		w = 1;
 		break;
 
 	case Aarg2:	/* width of a parameter */
 		o += t->width;
-		w = SZ_LONG;
+		w = SZ_VLONG;
 		break;
 
 	case Aaut3:	/* total allign of automatic */
@@ -695,8 +601,8 @@ align(long i, Type *t, int op)
 long
 maxround(long max, long v)
 {
-	v += SZ_VLONG-1;
+	v = round(v, SZ_VLONG);
 	if(v > max)
-		max = round(v, SZ_VLONG);
+		return v;
 	return max;
 }

+ 46 - 29
sys/src/cmd/4c/txt.c

@@ -22,6 +22,11 @@ ginit(void)
 	lastp = P;
 	tfield = types[TLONG];
 
+	/* 64-bit machine */
+	typeword = typechlvp;
+	typeswitch = typechlv;
+	typecmplx = typesu;
+
 	zprog.link = P;
 	zprog.as = AGOK;
 	zprog.reg = NREG;
@@ -77,10 +82,12 @@ ginit(void)
 	nodret = new(OIND, nodret, Z);
 	complex(nodret);
 
-	memset(reg, 0, sizeof(reg));
-	for(i=NREG; i<NREG+NREG; i+=2)
-		reg[i+1] = 1;
-	reg[REGZERO] = 1;
+	for(i=0; i<nelem(reg); i++) {
+		reg[i] = 0;
+		if(i == REGZERO ||
+		  (i >= NREG && ((i-NREG)&1)))
+			reg[i] = 1;
+	}
 }
 
 void
@@ -186,7 +193,7 @@ garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
 			sugen(n, tn2, n->type->width);
 		return;
 	}
-	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
+	if(REGARG && curarg == 0 && typeword[n->type->etype]) {
 		regaalloc1(tn1, n);
 		if(n->complex >= FNX) {
 			cgen(*fnxp, tn1);
@@ -218,6 +225,13 @@ nodconst(long v)
 	return &constnode;
 }
 
+Node*
+nod32const(vlong v)
+{
+	constnode.vconst = v & MASK(32);
+	return &constnode;
+}
+
 Node*
 nodfconst(double d)
 {
@@ -262,7 +276,7 @@ void
 regalloc(Node *n, Node *tn, Node *o)
 {
 	int i, j;
-	static lasti;
+	static int lasti;
 
 	switch(tn->type->etype) {
 	case TCHAR:
@@ -316,10 +330,10 @@ regalloc(Node *n, Node *tn, Node *o)
 	}
 	diag(tn, "unknown type in regalloc: %T", tn->type);
 err:
-	i = 0;
+	nodreg(n, tn, 0);
+	return;
 out:
-	if(i)
-		reg[i]++;
+	reg[i]++;
 	lasti++;
 	if(lasti >= 5)
 		lasti = 0;
@@ -494,10 +508,6 @@ naddr(Node *n, Adr *a)
 		if(typefd[n->type->etype]) {
 			a->type = D_FCONST;
 			a->dval = n->fconst;
-		} else
-		if(llconst(n)) {
-			a->type = D_VCONST;
-			a->vval = n->vconst;
 		} else {
 			a->type = D_CONST;
 			a->offset = n->vconst;
@@ -672,10 +682,14 @@ gmove(Node *f, Node *t)
 			a = AMOVW;
 			break;
 		case TUCHAR:
+			a = AMOVBU;
+			break;
 		case TCHAR:
 			a = AMOVB;
 			break;
 		case TUSHORT:
+			a = AMOVHU;
+			break;
 		case TSHORT:
 			a = AMOVH;
 			break;
@@ -730,12 +744,12 @@ gmove(Node *f, Node *t)
 			a = AMOVW;
 			break;
 		case TDOUBLE:
-			gins(AMOVW, f, t);
-			gins(AMOVWD, t, t);
+			gins(AMOVV, f, t);
+			gins(AMOVVD, t, t);
 			return;
 		case TFLOAT:
-			gins(AMOVW, f, t);
-			gins(AMOVWF, t, t);
+			gins(AMOVV, f, t);
+			gins(AMOVVF, t, t);
 			return;
 		}
 		break;
@@ -862,7 +876,7 @@ gmove(Node *f, Node *t)
 		case TUSHORT:
 		case TCHAR:
 		case TUCHAR:
-			a = AMOVW;
+			a = AMOVV;
 			break;
 		}
 		break;
@@ -895,7 +909,7 @@ gmove(Node *f, Node *t)
 		case TUSHORT:
 		case TCHAR:
 		case TUCHAR:
-			a = AMOVW;
+			a = AMOVV;
 			break;
 		}
 		break;
@@ -928,7 +942,7 @@ gmove(Node *f, Node *t)
 			break;
 		case TCHAR:
 		case TUCHAR:
-			a = AMOVW;
+			a = AMOVV;
 			break;
 		}
 		break;
@@ -961,14 +975,14 @@ gmove(Node *f, Node *t)
 			break;
 		case TCHAR:
 		case TUCHAR:
-			a = AMOVW;
+			a = AMOVV;
 			break;
 		}
 		break;
 	}
 	if(a == AGOK)
 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
-	if(a == AMOVW || a == AMOVF || a == AMOVD || a == AMOVV)
+	if((a == AMOVW && ewidth[ft] == ewidth[tt]) || a == AMOVF || a == AMOVD || a == AMOVV)
 	if(samaddr(f, t))
 		return;
 	gins(a, f, t);
@@ -997,7 +1011,10 @@ gopcode(int o, Node *f1, Node *f2, Node *t)
 
 	et = TLONG;
 	if(f1 != Z && f1->type != T)
-		et = f1->type->etype;
+		if(f1-> op == OCONST && t != Z && t->type != T)
+			et = t->type->etype;
+		else
+			et = f1->type->etype;
 	ett = TLONG;
 	if(t != Z && t->type != T)
 		ett = t->type->etype;
@@ -1341,7 +1358,8 @@ gpseudo(int a, Sym *s, Node *n)
 	p->as = a;
 	p->from.type = D_OREG;
 	p->from.sym = s;
-	p->reg = (profileflg ? 0 : NOPROF);
+	if(a == ATEXT)
+		p->reg = (profileflg ? 0 : NOPROF);
 	p->from.name = D_EXTERN;
 	if(s->class == CSTATIC)
 		p->from.name = D_STATIC;
@@ -1358,7 +1376,7 @@ sconst(Node *n)
 	if(n->op == OCONST) {
 		if(!typefd[n->type->etype]) {
 			vv = n->vconst;
-			if(vv >= -32766LL && vv < 32766LL)
+			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
 				return 1;
 		}
 	}
@@ -1368,13 +1386,12 @@ sconst(Node *n)
 int
 llconst(Node *n)
 {
-	vlong vv;
+	long l;
 
 	if(n != Z && n->op == OCONST) {
 		if(typev[n->type->etype] || n->type->etype == TIND) {
-			vv = n->vconst >> 32;
-			if(vv != 0 && vv != -1)
-				return 1;
+			l = n->vconst;
+			return (vlong)l != n->vconst;
 		}
 	}
 	return 0;

+ 368 - 287
sys/src/cmd/4l/asm.c

@@ -1,5 +1,12 @@
 #include	"l.h"
 
+/* can't include a.out.h due to name clashes, but these are taken from it */
+#define	_MAGIC(f, b)	((f)|((((4*(b))+0)*(b))+7))
+#define	V_MAGIC		_MAGIC(0, 16)		/* mips 3000 BE */
+#define	M_MAGIC		_MAGIC(0, 18)		/* mips 4000 BE */
+#define	N_MAGIC		_MAGIC(0, 22)		/* mips 4000 LE */
+#define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */
+
 long	OFFSET;
 /*
 long	BADOFFSET	=	-1;
@@ -13,7 +20,31 @@ long	BADOFFSET	=	-1;
 		OFFSET++;\
 */
 
-#define VPUT(c)\
+#define VPUT(v) { \
+		if (little) { \
+			VLEPUT(v); \
+		} else { \
+			VBEPUT(v); \
+		} \
+	}
+
+#define VLEPUT(c)\
+	{\
+		cbp[0] = (c);\
+		cbp[1] = (c)>>8;\
+		cbp[2] = (c)>>16;\
+		cbp[3] = (c)>>24;\
+		cbp[4] = (c)>>32;\
+		cbp[5] = (c)>>40;\
+		cbp[6] = (c)>>48;\
+		cbp[7] = (c)>>56;\
+		cbp += 8;\
+		cbc -= 8;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
+#define VBEPUT(c)\
 	{\
 		cbp[0] = (c)>>56;\
 		cbp[1] = (c)>>48;\
@@ -29,7 +60,27 @@ long	BADOFFSET	=	-1;
 			cflush();\
 	}
 
-#define	LPUT(c)\
+#define LPUT(l) { \
+		if (little) { \
+			LLEPUT(l); \
+		} else { \
+			LBEPUT(l); \
+		} \
+	}
+
+#define	LLEPUT(c)\
+	{\
+		cbp[0] = (c);\
+		cbp[1] = (c)>>8;\
+		cbp[2] = (c)>>16;\
+		cbp[3] = (c)>>24;\
+		cbp += 4;\
+		cbc -= 4;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
+#define	LBEPUT(c)\
 	{\
 		cbp[0] = (c)>>24;\
 		cbp[1] = (c)>>16;\
@@ -41,6 +92,35 @@ long	BADOFFSET	=	-1;
 			cflush();\
 	}
 
+#define HPUT(h) { \
+		if (little) { \
+			HLEPUT(h); \
+		} else { \
+			HBEPUT(h); \
+		} \
+	}
+
+#define	HLEPUT(c)\
+	{\
+		cbp[0] = (c);\
+		cbp[1] = (c)>>8;\
+		cbp += 2;\
+		cbc -= 2;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
+#define	HBEPUT(c)\
+	{\
+		cbp[0] = (c)>>8;\
+		cbp[1] = (c);\
+		cbp += 2;\
+		cbc -= 2;\
+		if(cbc <= 0)\
+			cflush();\
+	}
+
+
 #define	CPUT(c)\
 	{\
 		cbp[0] = (c);\
@@ -50,7 +130,75 @@ long	BADOFFSET	=	-1;
 			cflush();\
 	}
 
-u64int
+void
+cput(long l)
+{
+	CPUT(l);
+}
+
+void
+objput(long l)	/* emit long in byte order appropriate to object machine */
+{
+	LPUT(l);
+}
+
+void
+objhput(short s)
+{
+	HPUT(s);
+}
+
+void
+wput(long l)
+{
+
+	cbp[0] = l>>8;
+	cbp[1] = l;
+	cbp += 2;
+	cbc -= 2;
+	if(cbc <= 0)
+		cflush();
+}
+
+void
+wputl(long l)
+{
+
+	cbp[0] = l;
+	cbp[1] = l>>8;
+	cbp += 2;
+	cbc -= 2;
+	if(cbc <= 0)
+		cflush();
+}
+
+void
+lput(long l)		/* emit long in big-endian byte order */
+{
+	LBEPUT(l);
+}
+
+void
+lputl(long l)		/* emit long in big-endian byte order */
+{
+	LLEPUT(l);
+}
+
+void
+llput(vlong v)
+{
+	lput(v>>32);
+	lput(v);
+}
+
+void
+llputl(vlong v)
+{
+	lputl(v);
+	lputl(v>>32);
+}
+
+vlong
 entryvalue(void)
 {
 	char *a;
@@ -58,20 +206,84 @@ entryvalue(void)
 
 	a = INITENTRY;
 	if(*a >= '0' && *a <= '9')
-		return (u64int)atovlwhex(a);
+		return atolwhex(a);
 	s = lookup(a, 0);
 	if(s->type == 0)
 		return INITTEXT;
 	if(s->type != STEXT && s->type != SLEAF)
 		diag("entry not text: %s", s->name);
-	return (u64int)s->value;
+	return s->value;
+}
+
+static void
+plan9bootimage(ulong sects, ulong submagicvers, ulong tm,
+	ulong hdrtxtsz, ulong textsz, ulong textva, ulong lcsize)
+{
+	lput(0x160L<<16|sects);		/* magic and sections */
+	lput(tm);			/* time and date */
+	lput(hdrtxtsz+datsize);		/* offset to symbol table */
+	lput(symsize);			/* size of symbol table */
+	lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
+	lput(submagicvers);		/* magic and version */
+
+	lput(textsz);			/* segment sizes */
+	lput(datsize);
+	lput(bsssize);
+
+	lput(entryvalue());		/* va of entry */
+	lput(textva);			/* va of base of text */
+	lput(INITDAT);			/* va of base of data */
+	lput(INITDAT+datsize);		/* va of base of bss */
+
+	lput(~0);			/* gp reg mask */
+	lput(lcsize);			/* pcsize / cprmask[0] */
+	lput(0);			/* coproc reg masks[1⋯3] */
+	lput(0);
+	lput(0);
+	lput(~0);			/* gp value ?? */
+}
+
+static void
+symhdrs(ulong hdrtxtsz)
+{
+	strnput(".text", 8);		/* text segment */
+	lput(INITTEXT);			/* address */
+	lput(INITTEXT);
+	lput(textsize);
+	lput(HEADR);
+	lput(0);
+	lput(HEADR+textsize+datsize+symsize);
+	lput(lcsize);			/* line number size */
+	lput(0x20);			/* flags */
+
+	strnput(".data", 8);		/* data segment */
+	lput(INITDAT);			/* address */
+	lput(INITDAT);
+	lput(datsize);
+	lput(hdrtxtsz);
+	lput(0);
+	lput(0);
+	lput(0);
+	lput(0x40);			/* flags */
+
+	strnput(".bss", 8);		/* bss segment */
+	lput(INITDAT+datsize);		/* address */
+	lput(INITDAT+datsize);
+	lput(bsssize);
+	lput(0);
+	lput(0);
+	lput(0);
+	lput(0);
+	lput(0x80);			/* flags */
 }
 
 void
 asmb(void)
 {
 	Prog *p;
-	long t;
+	long tm;
+	ulong rndtxtsz;
+	vlong t, etext;
 	Optab *o;
 
 	if(debug['v'])
@@ -86,8 +298,7 @@ asmb(void)
 			autosize = p->to.offset + 8;
 		}
 		if(p->pc != pc) {
-			diag("phase error %lux sb %lux",
-				p->pc, pc);
+			diag("phase error %llux sb %llux", p->pc, pc);
 			if(!debug['a'])
 				prasm(curp);
 			pc = p->pc;
@@ -105,6 +316,17 @@ asmb(void)
 	Bflush(&bso);
 	cflush();
 
+	etext = INITTEXT + textsize;
+	for(t = pc; t < etext; t += sizeof(buf)-100) {
+		if(etext-t > sizeof(buf)-100)
+			datblk(t, sizeof(buf)-100, 1);
+		else
+			datblk(t, etext-t, 1);
+	}
+
+	Bflush(&bso);
+	cflush();
+
 	curtext = P;
 	switch(HEADTYPE) {
 	case 0:
@@ -124,9 +346,9 @@ asmb(void)
 	}
 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
 		if(datsize-t > sizeof(buf)-100)
-			datblk(t, sizeof(buf)-100);
+			datblk(t, sizeof(buf)-100, 0);
 		else
-			datblk(t, datsize-t);
+			datblk(t, datsize-t, 0);
 	}
 
 	symsize = 0;
@@ -166,54 +388,26 @@ asmb(void)
 	Bflush(&bso);
 	OFFSET = 0;
 	seek(cout, OFFSET, 0);
+
+	rndtxtsz = rnd(HEADR+textsize, (INITRND > 0? INITRND: 4096));
+	tm = time(0);
 	switch(HEADTYPE) {
 	case 0:
-		lput(0x160L<<16);		/* magic and sections */
-		lput(0L);			/* time and date */
-		lput(rnd(HEADR+textsize, 4096)+datsize);
-		lput(symsize);			/* nsyms */
-		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
-		lput((0413<<16)|0437L);		/* magic and version */
-		lput(rnd(HEADR+textsize, 4096));	/* sizes */
-		lput(datsize);
-		lput(bsssize);
-		lput(entryvalue());		/* va of entry */
-		lput(INITTEXT-HEADR);		/* va of base of text */
-		lput(INITDAT);			/* va of base of data */
-		lput(INITDAT+datsize);		/* va of base of bss */
-		lput(~0L);			/* gp reg mask */
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(~0L);			/* gp value ?? */
+		/* 0413: plan 9 boot image, text segment rounded (to 4KB) */
+		plan9bootimage(0, 0413<<16|0437, 0, rndtxtsz, rndtxtsz,
+			INITTEXT-HEADR, 0);
 		break;
 	case 1:
-		lput(0x160L<<16);		/* magic and sections */
-		lput(0L);			/* time and date */
-		lput(HEADR+textsize+datsize);
-		lput(symsize);			/* nsyms */
-		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
-
-		lput((0407<<16)|0437L);		/* magic and version */
-		lput(textsize);			/* sizes */
-		lput(datsize);
-		lput(bsssize);
-		lput(entryvalue());		/* va of entry */
-		lput(INITTEXT);			/* va of base of text */
-		lput(INITDAT);			/* va of base of data */
-		lput(INITDAT+datsize);		/* va of base of bss */
-		lput(~0L);			/* gp reg mask */
-		lput(lcsize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(~0L);			/* gp value ?? */
-		lput(0L);			/* complete mystery */
+		/* 0407: plan 9 boot image, extra word */
+		plan9bootimage(0, 0407<<16|0437, 0, HEADR+textsize, textsize,
+			INITTEXT, lcsize);
+		lput(0);			/* extra; complete mystery */
 		break;
-	case 2:
-		t = 18;
-		lput(((((4*t)+0)*t)+7));	/* magic */
+	case 2:				/* plan 9 mips 4000 format */
+		if (little)
+			lput(N_MAGIC);		/* mips 4000 LE */
+		else
+			lput(M_MAGIC);		/* mips 4000 BE */
 		lput(textsize);			/* sizes */
 		lput(datsize);
 		lput(bsssize);
@@ -223,156 +417,25 @@ asmb(void)
 		lput(lcsize);
 		break;
 	case 3:
-		lput((0x160L<<16)|3L);		/* magic and sections */
-		lput(time(0));			/* time and date */
-		lput(HEADR+textsize+datsize);
-		lput(symsize);			/* nsyms */
-		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
-
-		lput((0407<<16)|0437L);		/* magic and version */
-		lput(textsize);			/* sizes */
-		lput(datsize);
-		lput(bsssize);
-		lput(entryvalue());		/* va of entry */
-		lput(INITTEXT);			/* va of base of text */
-		lput(INITDAT);			/* va of base of data */
-		lput(INITDAT+datsize);		/* va of base of bss */
-		lput(~0L);			/* gp reg mask */
-		lput(lcsize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(~0L);			/* gp value ?? */
-
-		strnput(".text", 8);		/* text segment */
-		lput(INITTEXT);			/* address */
-		lput(INITTEXT);
-		lput(textsize);
-		lput(HEADR);
-		lput(0L);
-		lput(HEADR+textsize+datsize+symsize);
-		lput(lcsize);			/* line number size */
-		lput(0x20L);			/* flags */
-
-		strnput(".data", 8);		/* data segment */
-		lput(INITDAT);			/* address */
-		lput(INITDAT);
-		lput(datsize);
-		lput(HEADR+textsize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0x40L);			/* flags */
-
-		strnput(".bss", 8);		/* bss segment */
-		lput(INITDAT+datsize);		/* address */
-		lput(INITDAT+datsize);
-		lput(bsssize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0x80L);			/* flags */
+		/* 0407: plan 9 mips 4k boot image with symbols */
+		plan9bootimage(3, 0407<<16|0437, tm, HEADR+textsize, textsize,
+			INITTEXT, lcsize);
+		symhdrs(HEADR+textsize);
 		break;
 	case 4:
-
-		lput((0x160L<<16)|3L);		/* magic and sections */
-		lput(time(0));			/* time and date */
-		lput(rnd(HEADR+textsize, 4096)+datsize);
-		lput(symsize);			/* nsyms */
-		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
-
-		lput((0413<<16)|01012L);	/* magic and version */
-		lput(textsize);			/* sizes */
-		lput(datsize);
-		lput(bsssize);
-		lput(entryvalue());		/* va of entry */
-		lput(INITTEXT);			/* va of base of text */
-		lput(INITDAT);			/* va of base of data */
-		lput(INITDAT+datsize);		/* va of base of bss */
-		lput(~0L);			/* gp reg mask */
-		lput(lcsize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(~0L);			/* gp value ?? */
-
-		strnput(".text", 8);		/* text segment */
-		lput(INITTEXT);			/* address */
-		lput(INITTEXT);
-		lput(textsize);
-		lput(HEADR);
-		lput(0L);
-		lput(HEADR+textsize+datsize+symsize);
-		lput(lcsize);			/* line number size */
-		lput(0x20L);			/* flags */
-
-		strnput(".data", 8);		/* data segment */
-		lput(INITDAT);			/* address */
-		lput(INITDAT);
-		lput(datsize);
-		lput(rnd(HEADR+textsize, 4096));	/* sizes */
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0x40L);			/* flags */
-
-		strnput(".bss", 8);		/* bss segment */
-		lput(INITDAT+datsize);		/* address */
-		lput(INITDAT+datsize);
-		lput(bsssize);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0L);
-		lput(0x80L);			/* flags */
+		/* 0413: plan 9 mips 4k boot image with symbols */
+		plan9bootimage(3, 0413<<16|01012, tm, rndtxtsz, textsize,
+			INITTEXT, lcsize);
+		symhdrs(rndtxtsz);
 		break;
 	case 5:
-		strnput("\177ELF", 4);		/* e_ident */
-		CPUT(1);			/* class = 32 bit */
-		CPUT(2);			/* data = MSB */
-		CPUT(1);			/* version = CURRENT */
-		strnput("", 9);
-		lput((2L<<16)|8L);		/* type = EXEC; machine = MIPS */
-		lput(1L);			/* version = CURRENT */
-		lput(entryvalue());		/* entry vaddr */
-		lput(52L);			/* offset to first phdr */
-		lput(0L);			/* offset to first shdr */
-		lput(0L);			/* flags = MIPS */
-		lput((52L<<16)|32L);		/* Ehdr & Phdr sizes*/
-		lput((3L<<16)|0L);		/* # Phdrs & Shdr size */
-		lput((0L<<16)|0L);		/* # Shdrs & shdr string size */
-
-		lput(1L);			/* text - type = PT_LOAD */
-		lput(0L);			/* file offset */
-		lput(INITTEXT-HEADR);		/* vaddr */
-		lput(INITTEXT-HEADR);		/* paddr */
-		lput(HEADR+textsize);		/* file size */
-		lput(HEADR+textsize);		/* memory size */
-		lput(0x05L);			/* protections = RX */
-		lput(0x10000L);			/* alignment code?? */
-
-		lput(1L);			/* data - type = PT_LOAD */
-		lput(HEADR+textsize);		/* file offset */
-		lput(INITDAT);			/* vaddr */
-		lput(INITDAT);			/* paddr */
-		lput(datsize);			/* file size */
-		lput(datsize+bsssize);		/* memory size */
-		lput(0x06L);			/* protections = RW */
-		lput(0x10000L);			/* alignment code?? */
-
-		lput(0L);			/* data - type = PT_NULL */
-		lput(HEADR+textsize+datsize);	/* file offset */
-		lput(0L);
-		lput(0L);
-		lput(symsize);			/* symbol table size */
-		lput(lcsize);			/* line number size */
-		lput(0x04L);			/* protections = R */
-		lput(0x04L);			/* alignment code?? */
+		elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
 		break;
-	case 6:
-		t = 16;
-		lput(((((4*t)+0)*t)+7));	/* magic */
+	case 6:					/* plan 9 mips 3000 format */
+		if (little)
+			lput(P_MAGIC);		/* mips 3000 LE */
+		else
+			lput(V_MAGIC);		/* mips 3000 BE */
 		lput(textsize);			/* sizes */
 		lput(datsize);
 		lput(bsssize);
@@ -382,38 +445,7 @@ asmb(void)
 		lput(lcsize);
 		break;
 	case 7:
-		strnput("\177ELF", 4);		/* e_ident */
-		CPUT(2);			/* class = 64 bit */
-		CPUT(2);			/* data = MSB */
-		CPUT(1);			/* version = CURRENT */
-		strnput("", 9);
-		lput((2L<<16)|8L);		/* type = EXEC; machine = MIPS */
-		lput(1L);			/* version = CURRENT */
-		VPUT(entryvalue());		/* entry vaddr */
-		VPUT(64LL);			/* offset to first phdr */
-		VPUT(0LL);			/* offset to first shdr */
-		lput(0L);			/* flags = MIPS */
-		lput((64L<<16)|56L);		/* Ehdr & Phdr sizes*/
-		lput((2L<<16)|0L);		/* # Phdrs & Shdr size */
-		lput((0L<<16)|0L);		/* # Shdrs & shdr string size */
-
-		lput(1L);			/* text - type = PT_LOAD */
-		lput(0x05L);			/* protections = RX */
-		VPUT(0x10000ULL);		/* file offset */
-		VPUT(INITTEXT);			/* vaddr */
-		VPUT(INITTEXT);			/* paddr */
-		VPUT((vlong)textsize);		/* file size */
-		VPUT((vlong)HEADR+textsize);	/* memory size */
-		VPUT(0x10000ULL);		/* alignment code?? */
-
-		lput(1L);			/* data - type = PT_LOAD */
-		lput(0x06L);			/* protections = RW */
-		VPUT((vlong)HEADR+textsize);	/* file offset */
-		VPUT(INITDAT);			/* vaddr */
-		VPUT(INITDAT);			/* paddr */
-		VPUT((vlong)datsize);		/* file size */
-		VPUT((vlong)datsize+bsssize);	/* memory size */
-		VPUT(0x10000LL);		/* alignment code?? */
+		elf64(MIPSR4K, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
 		break;
 	}
 	cflush();
@@ -430,13 +462,6 @@ strnput(char *s, int n)
 		CPUT(0);
 }
 
-void
-lput(long l)
-{
-
-	LPUT(l);
-}
-
 void
 cflush(void)
 {
@@ -477,6 +502,10 @@ asmsym(void)
 				putsymb(s->name, 'D', s->value, s->version);
 				continue;
 
+			case SSTRING:
+				putsymb(s->name, 'T', s->value, s->version);
+				continue;
+
 			case SDATA:
 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
 				continue;
@@ -523,13 +552,19 @@ asmsym(void)
 }
 
 void
-putsymb(char *s, int t, long v, int ver)
+putsymb(char *s, int t, vlong v, int ver)
 {
 	int i, f;
+	long l;
 
 	if(t == 'f')
 		s++;
-	LPUT(v);
+	if(HEADTYPE == 2) {
+		l = v >> 32;
+		LBEPUT(l);
+	}
+	l = v;
+	LBEPUT(l);
 	if(ver)
 		t += 'a' - 'A';
 	CPUT(t+0x80);			/* 0x80 is variable length */
@@ -550,10 +585,12 @@ putsymb(char *s, int t, long v, int ver)
 		CPUT(0);
 	}
 	symsize += 4 + 1 + i + 1;
+	if(HEADTYPE == 2)
+		symsize += 4;
 
 	if(debug['n']) {
 		if(t == 'z' || t == 'Z') {
-			Bprint(&bso, "%c %.8lux ", t, v);
+			Bprint(&bso, "%c %.8llux ", t, v);
 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
 				Bprint(&bso, "/%x", f);
@@ -562,9 +599,9 @@ putsymb(char *s, int t, long v, int ver)
 			return;
 		}
 		if(ver)
-			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
+			Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
 		else
-			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
+			Bprint(&bso, "%c %.8llux %s\n", t, v, s);
 	}
 }
 
@@ -572,9 +609,9 @@ putsymb(char *s, int t, long v, int ver)
 void
 asmlc(void)
 {
-	long oldpc, oldlc;
+	long oldlc, v, s;
+	vlong oldpc;
 	Prog *p;
-	long v, s;
 
 	oldpc = INITTEXT;
 	oldlc = 0;
@@ -582,12 +619,11 @@ asmlc(void)
 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
 			if(p->as == ATEXT)
 				curtext = p;
-			if(debug['L'])
-				Bprint(&bso, "%6llux %P\n",
-					p->pc, p);
+			if(debug['V'])
+				Bprint(&bso, "%6llux %P\n", p->pc, p);
 			continue;
 		}
-		if(debug['L'])
+		if(debug['V'])
 			Bprint(&bso, "\t\t%6ld", lcsize);
 		v = (p->pc - oldpc) / MINLC;
 		while(v) {
@@ -595,7 +631,7 @@ asmlc(void)
 			if(v < 127)
 				s = v;
 			CPUT(s+128);	/* 129-255 +pc */
-			if(debug['L'])
+			if(debug['V'])
 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
 			v -= s;
 			lcsize++;
@@ -609,32 +645,29 @@ asmlc(void)
 			CPUT(s>>16);
 			CPUT(s>>8);
 			CPUT(s);
-			if(debug['L']) {
+			if(debug['V']) {
 				if(s > 0)
 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
 						s, 0, s);
 				else
 					Bprint(&bso, " lc%ld(%d,%ld)\n",
 						s, 0, s);
-				Bprint(&bso, "%6llux %P\n",
-					p->pc, p);
+				Bprint(&bso, "%6llux %P\n", p->pc, p);
 			}
 			lcsize += 5;
 			continue;
 		}
 		if(s > 0) {
 			CPUT(0+s);	/* 1-64 +lc */
-			if(debug['L']) {
+			if(debug['V']) {
 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
-				Bprint(&bso, "%6llux %P\n",
-					p->pc, p);
+				Bprint(&bso, "%6llux %P\n", p->pc, p);
 			}
 		} else {
 			CPUT(64-s);	/* 65-128 -lc */
-			if(debug['L']) {
+			if(debug['V']) {
 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
-				Bprint(&bso, "%6llux %P\n",
-					p->pc, p);
+				Bprint(&bso, "%6llux %P\n", p->pc, p);
 			}
 		}
 		lcsize++;
@@ -644,22 +677,25 @@ asmlc(void)
 		CPUT(s);
 		lcsize++;
 	}
-	if(debug['v'] || debug['L'])
+	if(debug['v'] || debug['V'])
 		Bprint(&bso, "lcsize = %ld\n", lcsize);
 	Bflush(&bso);
 }
 
 void
-datblk(long s, long n)
+datblk(long s, long n, int str)
 {
 	Prog *p;
 	char *cast;
-	long l, fl, j, d;
+	long l, fl, j;
+	vlong d;
 	int i, c;
 
 	memset(buf.dbuf, 0, n+100);
 	for(p = datap; p != P; p = p->link) {
 		curp = p;
+		if(str != (p->from.sym->type == SSTRING))
+			continue;
 		l = p->from.sym->value + p->from.offset - s;
 		c = p->reg;
 		i = 0;
@@ -686,14 +722,6 @@ datblk(long s, long n)
 			diag("unknown mode in initialization\n%P", p);
 			break;
 
-		case D_VCONST:
-			cast = (char*)p->to.ieee;
-			for(; i<c; i++) {
-				buf.dbuf[l] = cast[fnuxi8[i]];
-				l++;
-			}
-			break;
-
 		case D_FCONST:
 			switch(c) {
 			default:
@@ -701,7 +729,7 @@ datblk(long s, long n)
 				fl = ieeedtof(p->to.ieee);
 				cast = (char*)&fl;
 				for(; i<c; i++) {
-					buf.dbuf[l] = cast[fnuxi8[i+4]];
+					buf.dbuf[l] = cast[fnuxi4[i]];
 					l++;
 				}
 				break;
@@ -725,13 +753,17 @@ datblk(long s, long n)
 		case D_CONST:
 			d = p->to.offset;
 			if(p->to.sym) {
-				if(p->to.sym->type == STEXT ||
-				   p->to.sym->type == SLEAF)
+				switch(p->to.sym->type) {
+				case STEXT:
+				case SLEAF:
+				case SSTRING:
 					d += p->to.sym->value;
-				if(p->to.sym->type == SDATA)
-					d += p->to.sym->value + INITDAT;
-				if(p->to.sym->type == SBSS)
+					break;
+				case SDATA:
+				case SBSS:
 					d += p->to.sym->value + INITDAT;
+					break;
+				}
 			}
 			cast = (char*)&d;
 			switch(c) {
@@ -756,6 +788,12 @@ datblk(long s, long n)
 					l++;
 				}
 				break;
+			case 8:
+				for(; i<c; i++) {
+					buf.dbuf[l] = cast[inuxi8[i]];
+					l++;
+				}
+				break;
 			}
 			break;
 		}
@@ -791,6 +829,8 @@ datblk(long s, long n)
 #define	FPV(x,y)\
 	(SP(2,1)|(21<<21)|((x)<<3)|((y)<<0))
 
+int vshift(int);
+
 int
 asmout(Prog *p, Optab *o, int aflag)
 {
@@ -847,7 +887,7 @@ asmout(Prog *p, Optab *o, int aflag)
 		r = p->from.reg;
 		if(r == NREG)
 			r = o->param;
-		a = AADDU;
+		a = AADDVU;
 		if(o->a1 == C_ANDCON)
 			a = AOR;
 		o1 = OP_IRR(opirr(a), v, r, p->to.reg);
@@ -881,10 +921,10 @@ asmout(Prog *p, Optab *o, int aflag)
 				else
 					v = (p->cond->pc+4 - pc-4) >> 2;
 				if(((v << 16) >> 16) != v)
-					diag("short branch too far: %d\n%P", v, p);
+					diag("short branch too far: %lld\n%P", v, p);
 				o1 = OP_IRR(opirr(p->as+ALAST), v, p->from.reg, p->reg);
 				if(debug['a'])
-					Bprint(&bso, " %.8llux: %.8lux %.8lux\t%P\n",
+					Bprint(&bso, " %.16llux: %.8lux %.8lux\t%P\n",
 						p->pc, o1, o2, p);
 				LPUT(o1);
 				LPUT(o2);
@@ -896,7 +936,7 @@ asmout(Prog *p, Optab *o, int aflag)
 		else
 			v = (p->cond->pc - pc-4) >> 2;
 		if(((v << 16) >> 16) != v)
-			diag("short branch too far: %d\n%P", v, p);
+			diag("short branch too far: %lld\n%P", v, p);
 		o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
 		break;
 
@@ -951,7 +991,7 @@ asmout(Prog *p, Optab *o, int aflag)
 			if(o2) {
 				o1 += 1;
 				if(debug['a'])
-					Bprint(&bso, " %.8llux: %.8lux %.8lux%P\n",
+					Bprint(&bso, " %.16llux: %.8lux %.8lux%P\n",
 						p->pc, o1, o2, p);
 				LPUT(o1);
 				LPUT(o2);
@@ -978,7 +1018,10 @@ asmout(Prog *p, Optab *o, int aflag)
 	case 14:	/* movwu r,r */
 		v = 32-32;
 		o1 = OP_SRR(opirr(ASLLV+ALAST), v, p->from.reg, p->to.reg);
-		o2 = OP_SRR(opirr(ASRLV+ALAST), v, p->to.reg, p->to.reg);
+		if(p->as == AMOVWU)
+			o2 = OP_SRR(opirr(ASRLV+ALAST), v, p->to.reg, p->to.reg);
+		else
+			o2 = OP_SRR(opirr(ASRAV+ALAST), v, p->to.reg, p->to.reg);
 		break;
 
 	case 16:	/* sll $c,[r1],r2 */
@@ -986,7 +1029,9 @@ asmout(Prog *p, Optab *o, int aflag)
 		r = p->reg;
 		if(r == NREG)
 			r = p->to.reg;
-		if(v >= 32)
+
+		/* OP_SRR will use only the low 5 bits of the shift value */
+		if(v >= 32 && vshift(p->as))
 			o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
 		else
 			o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
@@ -1060,7 +1105,7 @@ asmout(Prog *p, Optab *o, int aflag)
 		r = p->from.reg;
 		if(r == NREG)
 			r = o->param;
-		o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
+		o3 = OP_RRR(oprrr(AADDVU), REGTMP, r, p->to.reg);
 		break;
 
 	case 27:		/* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
@@ -1076,7 +1121,7 @@ asmout(Prog *p, Optab *o, int aflag)
 		case 16:
 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
-			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
+			o3 = OP_RRR(oprrr(AADDVU), r, REGTMP, REGTMP);
 			o4 = OP_IRR(o4, 0, REGTMP, p->to.reg);
 			break;
 		case 4:
@@ -1100,7 +1145,7 @@ asmout(Prog *p, Optab *o, int aflag)
 				diag("cant synthesize large constant\n%P", p);
 			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
 			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
-			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
+			o3 = OP_RRR(oprrr(AADDVU), r, REGTMP, REGTMP);
 			o4 = OP_IRR(o4, 0, REGTMP, p->from.reg);
 			break;
 		case 4:
@@ -1155,7 +1200,7 @@ asmout(Prog *p, Optab *o, int aflag)
 			diag("cant synthesize large constant\n%P", p);
 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
-		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
+		o3 = OP_RRR(oprrr(AADDVU), r, REGTMP, REGTMP);
 		o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
 		break;
 
@@ -1168,7 +1213,7 @@ asmout(Prog *p, Optab *o, int aflag)
 			diag("cant synthesize large constant\n%P", p);
 		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
 		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
-		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
+		o3 = OP_RRR(oprrr(AADDVU), r, REGTMP, REGTMP);
 		o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
 		break;
 
@@ -1208,6 +1253,31 @@ asmout(Prog *p, Optab *o, int aflag)
 		o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
 		break;
 
+	case 45:	/* case r */
+		if(p->link == P)
+			v = p->pc+28;
+		else
+			v = p->link->pc;
+		if(v & (1<<15))
+			o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
+		else
+			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
+		o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
+		o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
+		o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
+		o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
+		o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
+		o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
+		break;
+
+	case 46:	/* bcase $con,lbra */
+		if(p->cond == P)
+			v = p->pc;
+		else
+			v = p->cond->pc;
+		o1 = v;
+		break;
+
 	case 47:	/* movv r,fr */
 		r = SP(2,1)|(5<<21);		/* dmtc1 */
 		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
@@ -1475,3 +1545,14 @@ opirr(int a)
 		diag("bad irr %A", a);
 	return 0;
 }
+
+int
+vshift(int a)
+{
+	switch(a){
+	case ASLLV:		return 1;
+	case ASRLV:		return 1;
+	case ASRAV:		return 1;
+	}
+	return 0;
+}

+ 18 - 4
sys/src/cmd/4l/compat.c

@@ -1,6 +1,5 @@
 #include	"l.h"
 
-#ifdef notdef
 /*
  * fake malloc
  */
@@ -37,15 +36,30 @@ calloc(ulong m, ulong n)
 }
 
 void*
-realloc(void *p, ulong n)
+realloc(void*, ulong)
 {
-	fprint(2, "realloc(0x%p %ld) called\n", p, n);
+	fprint(2, "realloc called\n");
 	abort();
 	return 0;
 }
-#endif
+
 void*
 mysbrk(ulong size)
 {
 	return sbrk(size);
 }
+
+void
+setmalloctag(void *v, ulong pc)
+{
+	USED(v, pc);
+}
+
+int
+fileexists(char *s)
+{
+	uchar dirbuf[400];
+
+	/* it's fine if stat result doesn't fit in dirbuf, since even then the file exists */
+	return stat(s, dirbuf, sizeof(dirbuf)) >= 0;
+}

+ 44 - 23
sys/src/cmd/4l/l.h

@@ -1,12 +1,15 @@
 #include	<u.h>
 #include	<libc.h>
 #include	<bio.h>
-#include	"../vc/v.out.h"
+#include	"../4c/4.out.h"
+#include	"../8l/elf.h"
 
 #ifndef	EXTERN
 #define	EXTERN	extern
 #endif
 
+#define	LIBNAMELEN	300
+
 typedef	struct	Adr	Adr;
 typedef	struct	Sym	Sym;
 typedef	struct	Autom	Auto;
@@ -24,9 +27,8 @@ struct	Adr
 {
 	union
 	{
-		long	u0offset;
+		vlong	u0offset;
 		char*	u0sval;
-		vlong*	u0vval;
 		Ieee*	u0ieee;
 	} u0;
 	union
@@ -43,7 +45,6 @@ struct	Adr
 #define	offset	u0.u0offset
 #define	sval	u0.u0sval
 #define	ieee	u0.u0ieee
-#define vval	u0.u0vval
 
 #define	autom	u1.u1autom
 #define	sym	u1.u1sym
@@ -117,6 +118,7 @@ enum
 	SLEAF,
 	SFILE,
 	SCONST,
+	SSTRING,
 
 	C_NONE		= 0,
 	C_REG,
@@ -167,15 +169,15 @@ enum
 	MINSIZ		= 64,
 	NENT		= 100,
 	MAXIO		= 8192,
-	MAXHIST		= 20,		/* limit of path elements for history symbols */
+	MAXHIST		= 20,				/* limit of path elements for history symbols */
 };
 
 EXTERN union
 {
 	struct
 	{
-		uchar	obuf[MAXIO];	/* output buffer */
-		uchar	ibuf[MAXIO];	/* input buffer */
+		uchar	obuf[MAXIO];			/* output buffer */
+		uchar	ibuf[MAXIO];			/* input buffer */
 	} u;
 	char	dbuf[1];
 } buf;
@@ -183,17 +185,12 @@ EXTERN union
 #define	cbuf	u.obuf
 #define	xbuf	u.ibuf
 
-#pragma	varargck	type	"A"	int
-#pragma	varargck	type	"D"	Adr*
-#pragma	varargck	type	"N"	Adr*
-#pragma	varargck	type	"P"	Prog*
-#pragma	varargck	type	"S"	char*
-
 EXTERN	long	HEADR;			/* length of header */
 EXTERN	int	HEADTYPE;		/* type of header */
 EXTERN	vlong	INITDAT;		/* data location */
 EXTERN	vlong	INITRND;		/* data round above text location */
 EXTERN	vlong	INITTEXT;		/* text location */
+EXTERN	vlong	INITTEXTP;		/* text location (physical) */
 EXTERN	char*	INITENTRY;		/* entry point */
 EXTERN	int	M64;
 EXTERN	long	autosize;
@@ -211,6 +208,7 @@ EXTERN	long	datsize;
 EXTERN	char	debug[128];
 EXTERN	Prog*	etextp;
 EXTERN	Prog*	firstp;
+EXTERN	char	fnuxi4[4];	/* for 3l [sic] */
 EXTERN	char	fnuxi8[8];
 EXTERN	char*	noname;
 EXTERN	Sym*	hash[NHASH];
@@ -220,10 +218,12 @@ EXTERN	int	histgen;
 EXTERN	char*	library[50];
 EXTERN	char*	libraryobj[50];
 EXTERN	int	libraryp;
+EXTERN	int	xrefresolv;
 EXTERN	char*	hunk;
 EXTERN	char	inuxi1[1];
 EXTERN	char	inuxi2[2];
 EXTERN	char	inuxi4[4];
+EXTERN	char	inuxi8[8];
 EXTERN	Prog*	lastp;
 EXTERN	long	lcsize;
 EXTERN	char	literal[32];
@@ -237,12 +237,13 @@ EXTERN	vlong	pc;
 EXTERN	uchar	repop[ALAST];
 EXTERN	long	symsize;
 EXTERN	Prog*	textp;
-EXTERN	long	textsize;
+EXTERN	vlong	textsize;
 EXTERN	long	thunk;
 EXTERN	int	version;
 EXTERN	char	xcmp[32][32];
 EXTERN	Prog	zprg;
 EXTERN	int	dtype;
+EXTERN	int	little;
 
 EXTERN	struct
 {
@@ -252,11 +253,20 @@ EXTERN	struct
 	Count	mfrom;
 	Count	page;
 	Count	jump;
+	Count	store;
 } nop;
 
 extern	char*	anames[];
 extern	Optab	optab[];
 
+#pragma	varargck	type	"A"	int
+#pragma	varargck	type	"D"	Adr*
+#pragma	varargck	type	"N"	Adr*
+#pragma	varargck	type	"P"	Prog*
+#pragma	varargck	type	"S"	char*
+
+#pragma	varargck	argpos	diag 1
+
 int	Aconv(Fmt*);
 int	Dconv(Fmt*);
 int	Nconv(Fmt*);
@@ -264,48 +274,58 @@ int	Pconv(Fmt*);
 int	Sconv(Fmt*);
 int	aclass(Adr*);
 void	addhist(long, int);
+void	addlibpath(char*);
 void	addnop(Prog*);
 void	append(Prog*, Prog*);
 void	asmb(void);
 void	asmlc(void);
 int	asmout(Prog*, Optab*, int);
 void	asmsym(void);
-long	atolwhex(char*);
+vlong	atolwhex(char*);
 vlong	atovlwhex(char*);
 Prog*	brloop(Prog*);
-Biobuf	bso;
 void	buildop(void);
 void	buildrep(int, int);
 void	cflush(void);
 int	cmp(int, int);
+void	cput(long);
 int	compound(Prog*);
 double	cputime(void);
-void	datblk(long, long);
+void	datblk(long, long, int);
 void	diag(char*, ...);
 void	dodata(void);
 void	doprof1(void);
 void	doprof2(void);
-u64int	entryvalue(void);
+vlong	entryvalue(void);
 void	errorexit(void);
 void	exchange(Prog*);
+int	fileexists(char*);
 int	find1(long, int);
+char*	findlib(char*);
 void	follow(void);
 void	gethunk(void);
 void	histtoauto(void);
 vlong	ieeedtov(Ieee*);
 double	ieeedtod(Ieee*);
 long	ieeedtof(Ieee*);
+int	isint32(vlong);
+int	isuint32(uvlong);
 int	isnop(Prog*);
 void	ldobj(int, long, char*);
-void	loadlib(int, int);
+void	loadlib(void);
 void	listinit(void);
 Sym*	lookup(char*, int);
+void	llput(vlong);
+void	llputl(vlong);
 void	lput(long);
+void	lputl(long);
+void	bput(long);
 void	mkfwd(void);
 void*	mysbrk(ulong);
 void	names(void);
 void	nocache(Prog*);
 void	noops(void);
+void	nopstat(char*, Count*);
 void	nuxiinit(void);
 void	objfile(char*);
 int	ocmp(const void*, const void*);
@@ -317,15 +337,16 @@ void	prasm(Prog*);
 void	prepend(Prog*, Prog*);
 Prog*	prg(void);
 int	pseudo(Prog*);
-void	putsymb(char*, int, long, int);
+void	putsymb(char*, int, vlong, int);
 long	regoff(Adr*);
 int	relinv(int);
-vlong	rnd(vlong, vlong);
+vlong	rnd(vlong, long);
 void	sched(Prog*, Prog*);
 void	span(void);
 void	strnput(char*, int);
 void	undef(void);
-void	xdefine(char*, int, long);
+void	wput(long);
+void	wputl(long);
+void	xdefine(char*, int, vlong);
 void	xfol(Prog*);
 void	xfol(Prog*);
-void	nopstat(char*, Count*);

+ 12 - 16
sys/src/cmd/4l/list.c

@@ -137,7 +137,7 @@ Dconv(Fmt *fp)
 			sprint(str, "%N(HI)(REG)", a);
 		break;
 
-	case D_BRANCH:	/* botch */	/* XXX */
+	case D_BRANCH:	/* botch */
 		if(curp->cond != P) {
 			v = curp->cond->pc;
 			if(v >= INITTEXT)
@@ -148,13 +148,9 @@ Dconv(Fmt *fp)
 				sprint(str, "%.5lux(BRANCH)", v);
 		} else
 			if(a->sym != S)
-				sprint(str, "%s+%ld(APC)", a->sym->name, a->offset);
+				sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
 			else
-				sprint(str, "%ld(APC)", a->offset);
-		break;
-
-	case D_VCONST:
-		sprint(str, "$%lld", *a->vval);
+				sprint(str, "%lld(APC)", a->offset);
 		break;
 
 	case D_FCONST:
@@ -183,35 +179,35 @@ Nconv(Fmt *fp)
 		break;
 
 	case D_NONE:
-		sprint(str, "%ld", a->offset);
+		sprint(str, "%lld", a->offset);
 		break;
 
 	case D_EXTERN:
 		if(s == S)
-			sprint(str, "%ld(SB)", a->offset);
+			sprint(str, "%lld(SB)", a->offset);
 		else
-			sprint(str, "%s+%ld(SB)", s->name, a->offset);
+			sprint(str, "%s+%lld(SB)", s->name, a->offset);
 		break;
 
 	case D_STATIC:
 		if(s == S)
-			sprint(str, "<>+%ld(SB)", a->offset);
+			sprint(str, "<>+%lld(SB)", a->offset);
 		else
-			sprint(str, "%s<>+%ld(SB)", s->name, a->offset);
+			sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
 		break;
 
 	case D_AUTO:
 		if(s == S)
-			sprint(str, "%ld(SP)", a->offset);
+			sprint(str, "%lld(SP)", a->offset);
 		else
-			sprint(str, "%s-%ld(SP)", s->name, -a->offset);
+			sprint(str, "%s-%lld(SP)", s->name, -a->offset);
 		break;
 
 	case D_PARAM:
 		if(s == S)
-			sprint(str, "%ld(FP)", a->offset);
+			sprint(str, "%lld(FP)", a->offset);
 		else
-			sprint(str, "%s+%ld(FP)", s->name, a->offset);
+			sprint(str, "%s+%lld(FP)", s->name, a->offset);
 		break;
 	}
 

+ 8 - 11
sys/src/cmd/4l/mkfile

@@ -12,24 +12,21 @@ OFILES=\
 	span.$O\
 	enam.$O\
 	compat.$O\
+	elf.$O\
 
 HFILES=\
 	l.h\
-	../vc/v.out.h\
+	../4c/4.out.h\
+	../8l/elf.h\
 
 BIN=/$objtype/bin
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-
+CFLAGS=$CFLAGS -. -I.
 </sys/src/cmd/mkone
 
-#LDFLAGS=$LDFLAGS -p
-
-enam.c:	../vc/v.out.h
-	rc ../vc/mkenam
+enam.$O:	../4c/enam.c
+	$CC $CFLAGS ../4c/enam.c
+elf.$O:	../8l/elf.c
+	$CC $CFLAGS ../8l/elf.c
 
 test:V:	$O.out
 	rm -f xxx

+ 8 - 8
sys/src/cmd/4l/noop.c

@@ -194,7 +194,7 @@ noops(void)
 					Bprint(&bso, "odd stack in: %s\n",
 						curtext->from.sym->name);
 				q = prg();
-				q->as = AADD;
+				q->as = AADDV;
 				q->line = p->line;
 				q->from.type = D_CONST;
 				q->from.offset = -autosize;
@@ -219,7 +219,7 @@ noops(void)
 			}
 
 			q1 = prg();
-			q1->as = AMOVW;
+			q1->as = AMOVV;
 			q1->line = p->line;
 			q1->from.type = D_REG;
 			q1->from.reg = REGLINK;
@@ -246,7 +246,7 @@ noops(void)
 					break;
 				}
 
-				p->as = AADD;
+				p->as = AADDV;
 				p->from.type = D_CONST;
 				p->from.offset = autosize;
 				p->to.type = D_REG;
@@ -264,7 +264,7 @@ noops(void)
 				p->link = q;
 				break;
 			}
-			p->as = AMOVW;
+			p->as = AMOVV;
 			p->from.type = D_OREG;
 			p->from.offset = 0;
 			p->from.reg = REGSP;
@@ -274,7 +274,7 @@ noops(void)
 			q = p;
 			if(autosize) {
 				q = prg();
-				q->as = AADD;
+				q->as = AADDV;
 				q->line = p->line;
 				q->from.type = D_CONST;
 				q->from.offset = autosize;
@@ -310,7 +310,7 @@ noops(void)
 				q->mark |= BRANCH;
 				p->link = q;
 
-				p->as = AADD;
+				p->as = AADDV;
 				p->from = zprg.from;
 				p->from.type = D_CONST;
 				p->from.offset = autosize;
@@ -332,7 +332,7 @@ noops(void)
 
 			q = prg();
 			q->line = p->line;
-			q->as = AADD;
+			q->as = AADDV;
 			q->from.type = D_CONST;
 			q->from.offset = autosize;
 			q->to.type = D_REG;
@@ -340,7 +340,7 @@ noops(void)
 			q->link = p->link;
 			p->link = q;
 
-			p->as = AMOVW;
+			p->as = AMOVV;
 			p->from = zprg.from;
 			p->from.type = D_OREG;
 			p->from.offset = 0;

+ 251 - 83
sys/src/cmd/4l/obj.c

@@ -10,22 +10,36 @@ char	*noname		= "<none>";
 char	symname[]	= SYMDEF;
 char	thechar		= '4';
 char	*thestring 	= "mips64";
+int little;
+
+char**	libdir;
+int	nlibdir	= 0;
+static	int	maxlibdir = 0;
 
 /*
  *	-H0 -T0x40004C -D0x10000000	is abbrev unix
  *	-H1 -T0x80020000 -R4		is bootp() format for 3k
- *	-H2 -T4128 -R4096		is plan9 mips2 format
+ *	-H2 -T16416 -R16384		is plan9 mips64 format
  *	-H3 -T0x80020000 -R8		is bootp() format for 4k
  *	-H4 -T0x400000 -R4		is sgi unix coff executable
  *	-H5 -T0x4000A0 -R4		is sgi unix elf executable
- *	-H6 -T0x4000A0 -R4		is plan9 mips format
+ *	-H6 -T16416 -R16384		is plan9 mips format
+ *	-H7				is 64-bit elf executable
  */
 
+void
+usage(void)
+{
+	diag("usage: %s [-options] objects", argv0);
+	errorexit();
+}
+
 void
 main(int argc, char *argv[])
 {
 	int c;
 	char *a;
+	char name[LIBNAMELEN];
 
 	Binit(&bso, 1, OWRITE);
 	cout = -1;
@@ -35,6 +49,7 @@ main(int argc, char *argv[])
 	curtext = P;
 	HEADTYPE = -1;
 	INITTEXT = -1;
+	INITTEXTP = -1;
 	INITDAT = -1;
 	INITRND = -1;
 	INITENTRY = 0;
@@ -54,11 +69,21 @@ main(int argc, char *argv[])
 		if(a)
 			INITENTRY = a;
 		break;
+	case  'm':			/* for little-endian mips */
+		thechar = 'x';	/* XXX the char unknown */
+		thestring = "spim64";
+		little = 1;
+		break;
 	case 'T':
 		a = ARGF();
 		if(a)
 			INITTEXT = atolwhex(a);
 		break;
+	case 'P':
+		a = ARGF();
+		if(a)
+			INITTEXTP = atolwhex(a);
+		break;
 	case 'D':
 		a = ARGF();
 		if(a)
@@ -75,16 +100,27 @@ main(int argc, char *argv[])
 			HEADTYPE = atolwhex(a);
 		/* do something about setting INITTEXT */
 		break;
+	case 'L':
+		addlibpath(EARGF(usage()));
+		break;
 	} ARGEND
 
 	USED(argc);
 
-	if(*argv == 0) {
-		diag("usage: vl [-options] objects");
-		errorexit();
-	}
+	if(*argv == 0)
+		usage();
 	if(!debug['9'] && !debug['U'] && !debug['B'])
 		debug[DEFAULT] = 1;
+	a = getenv("ccroot");
+	if(a != nil && *a != '\0') {
+		if(!fileexists(a)) {
+			diag("nonexistent $ccroot: %s", a);
+			errorexit();
+		}
+	}else
+		a = "";
+	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
+	addlibpath(name);
 	if(HEADTYPE == -1) {
 		if(debug['U'])
 			HEADTYPE = 0;
@@ -116,14 +152,14 @@ main(int argc, char *argv[])
 		if(INITRND == -1)
 			INITRND = 4;
 		break;
-	case 2:	/* plan 9 mips2 */
+	case 2:	/* plan 9 mips64 */
 		HEADR = 32L;
-		if(INITTEXT == -1)
-			INITTEXT = 4128;
 		if(INITDAT == -1)
 			INITDAT = 0;
 		if(INITRND == -1)
-			INITRND = 4096;
+			INITRND = 16*1024;
+		if(INITTEXT == -1)
+			INITTEXT = INITRND + HEADR;
 		break;
 	case 3:	/* boot for 4k */
 		HEADR = 20L+56L+3*40L;
@@ -144,7 +180,7 @@ main(int argc, char *argv[])
 			INITRND = 0;
 		break;
 	case 5:	/* sgi unix elf executable */
-		HEADR = rnd(52L+3*32L, 16);
+		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
 		if(INITTEXT == -1)
 			INITTEXT = 0x00400000L+HEADR;
 		if(INITDAT == -1)
@@ -154,14 +190,14 @@ main(int argc, char *argv[])
 		break;
 	case 6:	/* plan 9 mips */
 		HEADR = 32L;
-		if(INITTEXT == -1)
-			INITTEXT = 4128;
 		if(INITDAT == -1)
 			INITDAT = 0;
 		if(INITRND == -1)
-			INITRND = 4096;
+			INITRND = 16*1024;
+		if(INITTEXT == -1)
+			INITTEXT = INITRND + HEADR;
 		break;
-	case 7:	/* elf64 boot  */
+	case 7:	/* 64-bit elf executable  */
 		HEADR = rnd(64L+3*56L, 16);
 		if(INITTEXT == -1)
 			INITTEXT = 0xa800000020040000ULL;
@@ -171,12 +207,13 @@ main(int argc, char *argv[])
 			INITRND = 8;
 		break;
 	}
-
+	if (INITTEXTP == -1)
+		INITTEXTP = INITTEXT;
 	if(INITDAT != 0 && INITRND != 0)
-		print("warning: -D0x%llux is ignored because of -R0x%llux\n",
+		print("warning: -D%#llux is ignored because of -R%#llux\n",
 			INITDAT, INITRND);
 	if(debug['v'])
-		Bprint(&bso, "HEADER = -H0x%d -T0x%llux -D0x%llux -R0x%llux\n",
+		Bprint(&bso, "HEADER = -H%d -T%#llux -D%#llux -R%#llux\n",
 			HEADTYPE, INITTEXT, INITDAT, INITRND);
 	Bflush(&bso);
 	zprg.as = AGOK;
@@ -191,11 +228,15 @@ main(int argc, char *argv[])
 	datap = P;
 	pc = 0;
 	dtype = 4;
-	if(outfile == 0)
-		outfile = "4.out";
+	if(outfile == 0) {
+		static char name[20];
+
+		snprint(name, sizeof name, "%c.out", thechar);
+		outfile = name;
+	}
 	cout = create(outfile, 1, 0775);
 	if(cout < 0) {
-		diag("%s: cannot create", outfile);
+		diag("cannot create %s: %r", outfile);
 		errorexit();
 	}
 	nuxiinit();
@@ -212,13 +253,13 @@ main(int argc, char *argv[])
 			INITENTRY = "_mainp";
 		if(!debug['l'])
 			lookup(INITENTRY, 0)->type = SXREF;
-	} else
+	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
 		lookup(INITENTRY, 0)->type = SXREF;
 
 	while(*argv)
 		objfile(*argv++);
 	if(!debug['l'])
-		loadlib(0, libraryp);
+		loadlib();
 	firstp = firstp->link;
 	if(firstp == P)
 		goto out;
@@ -249,18 +290,60 @@ out:
 }
 
 void
-loadlib(int beg, int end)
+addlibpath(char *arg)
+{
+	char **p;
+
+	if(nlibdir >= maxlibdir) {
+		if(maxlibdir == 0)
+			maxlibdir = 8;
+		else
+			maxlibdir *= 2;
+		p = malloc(maxlibdir*sizeof(*p));
+		if(p == nil) {
+			diag("out of memory");
+			errorexit();
+		}
+		memmove(p, libdir, nlibdir*sizeof(*p));
+		free(libdir);
+		libdir = p;
+	}
+	libdir[nlibdir++] = strdup(arg);
+}
+
+char*
+findlib(char *file)
+{
+	int i;
+	char name[LIBNAMELEN];
+
+	for(i = 0; i < nlibdir; i++) {
+		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
+		if(fileexists(name))
+			return libdir[i];
+	}
+	return nil;
+}
+
+void
+loadlib(void)
 {
-	int i, t;
+	int i;
+	long h;
+	Sym *s;
 
-	for(i=end-1; i>=beg; i--) {
-		t = libraryp;
+loop:
+	xrefresolv = 0;
+	for(i=0; i<libraryp; i++) {
 		if(debug['v'])
-			Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
+			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
 		objfile(library[i]);
-		if(t != libraryp)
-			loadlib(t, libraryp);
 	}
+	if(xrefresolv)
+	for(h=0; h<nelem(hash); h++)
+	for(s = hash[h]; s != S; s = s->link)
+		if(s->type == SXREF)
+			goto loop;
 }
 
 void
@@ -361,7 +444,8 @@ objfile(char *file)
 			l |= (e[3] & 0xff) << 16;
 			l |= (e[4] & 0xff) << 24;
 			seek(f, l, 0);
-			l = read(f, &arhdr, SAR_HDR);
+			/* need readn to read the dumps (at least) */
+			l = readn(f, &arhdr, SAR_HDR);
 			if(l != SAR_HDR)
 				goto bad;
 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
@@ -373,6 +457,7 @@ objfile(char *file)
 				errorexit();
 			}
 			work = 1;
+			xrefresolv = 1;
 		}
 	}
 	return;
@@ -391,8 +476,6 @@ zaddr(uchar *p, Adr *a, Sym *h[])
 	Sym *s;
 	Auto *u;
 
-	char *vc;
-
 	c = p[2];
 	if(c < 0 || c > NSYM){
 		print("sym out of range: %d\n", c);
@@ -430,19 +513,29 @@ zaddr(uchar *p, Adr *a, Sym *h[])
 	case D_OREG:
 	case D_CONST:
 	case D_OCONST:
-		a->offset = p[4] | (p[5]<<8) |
-			(p[6]<<16) | (p[7]<<24);
+		l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
+		a->offset = l;
 		c += 4;
 		break;
 
 	case D_SCONST:
-		a->sval = malloc(NSNAME);
+		while(nhunk < NSNAME)
+			gethunk();
+		a->sval = (char*)hunk;
+		nhunk -= NSNAME;
+		hunk += NSNAME;
+
 		memmove(a->sval, p+4, NSNAME);
 		c += NSNAME;
 		break;
 
 	case D_FCONST:
-		a->ieee = malloc(sizeof(Ieee));
+		while(nhunk < sizeof(Ieee))
+			gethunk();
+		a->ieee = (Ieee*)hunk;
+		nhunk -= sizeof(Ieee);
+		hunk += sizeof(Ieee);
+
 		a->ieee->l = p[4] | (p[5]<<8) |
 			(p[6]<<16) | (p[7]<<24);
 		a->ieee->h = p[8] | (p[9]<<8) |
@@ -451,20 +544,12 @@ zaddr(uchar *p, Adr *a, Sym *h[])
 		break;
 
 	case D_VCONST:
-		a->vval = malloc(sizeof(vlong));
-		/* *a->vval = p[4] | (p[5]<<8) | (p[6]<<16) |
-			(p[7]<<24) | ((vlong)p[8]<<32) | ((vlong)p[9]<<40) |
-			((vlong)p[10]<<48) | ((vlong)p[11]<<56); */
-		vc = (char*)a->vval;
-		vc[0] = p[4];
-		vc[1] = p[5];
-		vc[2] = p[6];
-		vc[3] = p[7];
-		vc[4] = p[8];
-		vc[5] = p[9];
-		vc[6] = p[10];
-		vc[7] = p[11];
+		l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
+		a->offset = (uvlong)l & 0xfffffffful;
+		l = p[8] | (p[9]<<8) | (p[10]<<16) | (p[11]<<24);
+		a->offset |= (vlong)l << 32;
 		c += 8;
+		a->type = D_CONST;
 		break;
 	}
 	s = a->sym;
@@ -500,25 +585,24 @@ zaddr(uchar *p, Adr *a, Sym *h[])
 void
 addlib(char *obj)
 {
-	char name[1024], comp[256], *p;
-	int i;
+	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
+	int i, search;
 
 	if(histfrogp <= 0)
 		return;
 
+	name = fn1;
+	search = 0;
 	if(histfrog[0]->name[1] == '/') {
 		sprint(name, "");
 		i = 1;
-	} else
-	if(histfrog[0]->name[1] == '.') {
+	} else if(histfrog[0]->name[1] == '.') {
 		sprint(name, ".");
 		i = 0;
 	} else {
-		if(debug['9'])
-			sprint(name, "/%s/lib", thestring);
-		else
-			sprint(name, "/usr/%clib", thechar);
+		sprint(name, "");
 		i = 0;
+		search = 1;
 	}
 
 	for(; i<histfrogp; i++) {
@@ -541,13 +625,25 @@ addlib(char *obj)
 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
 			memmove(p, thestring, strlen(thestring));
 		}
-		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
+		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
 			diag("library component too long");
 			return;
 		}
-		strcat(name, "/");
-		strcat(name, comp);
+		if(i > 0 || !search)
+			strcat(fn1, "/");
+		strcat(fn1, comp);
+	}
+
+	cleanname(name);
+
+	if(search){
+		p = findlib(name);
+		if(p != nil){
+			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
+			name = fn2;
+		}
 	}
+
 	for(i=0; i<libraryp; i++)
 		if(strcmp(name, library[i]) == 0)
 			return;
@@ -699,11 +795,15 @@ loop:
 	}
 	o = bloc[0];		/* as */
 	if(o <= AXXX || o >= ALAST) {
-		diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
-		print("	probably not a .v file\n");
+		diag("%s: line %lld: opcode out of range %d", pn, pc-ipc, o);
+		print("	probably not a .%c file\n", thechar);
 		errorexit();
 	}
-	if(o == ANAME) {
+	if(o == ANAME || o == ASIGNAME) {
+		if(o == ASIGNAME) {
+			bloc += 4;
+			c -= 4;
+		}
 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
 		if(stop == 0){
 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
@@ -929,6 +1029,18 @@ loop:
 		}
 		goto casedef;
 
+	case ASUBV:
+	case ASUBVU:
+		if(p->from.type == D_CONST)
+		if(p->from.name == D_NONE) {
+			p->from.offset = -p->from.offset;
+			if(p->as == ASUBV)
+				p->as = AADDV;
+			else
+				p->as = AADDVU;
+		}
+		goto casedef;
+
 	case AMOVF:
 		if(skip)
 			goto casedef;
@@ -965,7 +1077,7 @@ loop:
 		if(p->from.type == D_FCONST) {
 			/* size sb 18 max */
 			sprint(literal, "$%lux.%lux",
-				p->from.ieee->h, p->from.ieee->l);
+				p->from.ieee->l, p->from.ieee->h);
 			s = lookup(literal, 0);
 			if(s->type == 0) {
 				s->type = SBSS;
@@ -992,9 +1104,10 @@ loop:
 		if(skip)
 			goto casedef;
 
-		if(p->from.type == D_VCONST) {
+		if(p->from.type == D_CONST)
+		if(!isint32(p->from.offset)) {
 			/* size sb 18 max */
-			sprint(literal, "$%llux", *p->from.vval);
+			sprint(literal, "$%llux", p->from.offset);
 			s = lookup(literal, 0);
 			if(s->type == 0) {
 				s->type = SBSS;
@@ -1050,6 +1163,7 @@ lookup(char *symb, int v)
 	l = (p - symb) + 1;
 	if(h < 0)
 		h = ~h;
+	h &= 0xffffff;		// XXX
 	h %= NHASH;
 	for(s = hash[h]; s != S; s = s->link)
 		if(s->version == v)
@@ -1202,15 +1316,24 @@ void
 doprof2(void)
 {
 	Sym *s2, *s4;
-	Prog *p, *q, *ps2, *ps4;
+	Prog *p, *q, *q2, *ps2, *ps4;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f profile 2\n", cputime());
 	Bflush(&bso);
-	s2 = lookup("_profin", 0);
-	s4 = lookup("_profout", 0);
+
+	if(debug['e']){
+		s2 = lookup("_tracein", 0);
+		s4 = lookup("_traceout", 0);
+	}else{
+		s2 = lookup("_profin", 0);
+		s4 = lookup("_profout", 0);
+	}
 	if(s2->type != STEXT || s4->type != STEXT) {
-		diag("_profin/_profout not defined");
+		if(debug['e'])
+			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
+		else
+			diag("_profin/_profout not defined");
 		return;
 	}
 
@@ -1249,7 +1372,20 @@ doprof2(void)
 			q->line = p->line;
 			q->pc = p->pc;
 			q->link = p->link;
-			p->link = q;
+			if(debug['e']){		/* embedded tracing */
+				q2 = prg();
+				p->link = q2;
+				q2->link = q;
+
+				q2->line = p->line;
+				q2->pc = p->pc;
+
+				q2->as = AJMP;
+				q2->to.type = D_BRANCH;
+				q2->to.sym = p->to.sym;
+				q2->cond = q->link;
+			}else
+				p->link = q;
 			p = q;
 			p->as = AJAL;
 			p->to.type = D_BRANCH;
@@ -1259,6 +1395,17 @@ doprof2(void)
 			continue;
 		}
 		if(p->as == ARET) {
+			/*
+			 * RET (default)
+			 */
+			if(debug['e']){		/* embedded tracing */
+				q = prg();
+				q->line = p->line;
+				q->pc = p->pc;
+				q->link = p->link;
+				p->link = q;
+				p = q;
+			}
 			/*
 			 * RET
 			 */
@@ -1291,17 +1438,32 @@ nuxiinit(void)
 {
 	int i, c;
 
-	for(i=0; i<4; i++) {
-		c = find1(0x01020304L, i+1);
-		if(i >= 2)
-			inuxi2[i-2] = c;
-		if(i >= 3)
-			inuxi1[i-3] = c;
-		inuxi4[i] = c;
-
-		fnuxi8[i] = c+4;
-		fnuxi8[i+4] = c;
-	}
+	for(i=0; i<4; i++)
+		if (!little) {			/* normal big-endian case */
+			c = find1(0x01020304L, i+1);
+			if(i >= 2)
+				inuxi2[i-2] = c;
+			if(i >= 3)
+				inuxi1[i-3] = c;
+			inuxi4[i] = c;
+			inuxi8[i] = c+4;
+			inuxi8[i+4] = c;
+			fnuxi4[i] = c;
+			fnuxi8[i] = c+4;
+			fnuxi8[i+4] = c;
+		} else {			/* oddball little-endian case */
+			c = find1(0x04030201L, i+1);
+			if(i < 2)
+				inuxi2[i] = c;
+			if(i < 1)
+				inuxi1[i] = c;
+			inuxi4[i] = c;
+			inuxi8[i] = c;
+			inuxi8[i+4] = c+4;
+			fnuxi4[i] = c;
+			fnuxi8[i] = c;
+			fnuxi8[i+4] = c+4;
+		}
 	if(debug['v']) {
 		Bprint(&bso, "inuxi = ");
 		for(i=0; i<1; i++)
@@ -1313,6 +1475,12 @@ nuxiinit(void)
 		for(i=0; i<4; i++)
 			Bprint(&bso, "%d", inuxi4[i]);
 		Bprint(&bso, "\nfnuxi = ");
+		for(i=0; i<8; i++)
+			Bprint(&bso, "%d", inuxi8[i]);
+		Bprint(&bso, "\n");
+		for(i=0; i<4; i++)
+			Bprint(&bso, "%d", fnuxi4[i]);
+		Bprint(&bso, "\nfnuxi = ");
 		for(i=0; i<8; i++)
 			Bprint(&bso, "%d", fnuxi8[i]);
 		Bprint(&bso, "\n");

+ 8 - 1
sys/src/cmd/4l/optab.c

@@ -7,7 +7,7 @@ Optab	optab[] =
 	{ ATEXT,	C_LEXT,	C_NONE,	C_LCON, 	 0, 0, 0 },
 	{ ATEXT,	C_LEXT,	C_REG,	C_LCON, 	 0, 0, 0 },
 
-	{ AMOVW,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
+	{ AMOVW,	C_REG,	C_NONE,	C_REG,		14, 8, 0 },
 	{ AMOVV,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
 	{ AMOVB,	C_REG,	C_NONE,	C_REG,		12, 8, 0 },
 	{ AMOVBU,	C_REG,	C_NONE,	C_REG,		13, 4, 0 },
@@ -89,9 +89,13 @@ Optab	optab[] =
 	{ AMOVBU,	C_LOREG,C_NONE,	C_REG,		36, 16, REGZERO },
 
 	{ AMOVW,	C_SECON,C_NONE,	C_REG,		 3, 4, REGSB },
+	{ AMOVV,	C_SECON,C_NONE,	C_REG,		 3, 4, REGSB },
 	{ AMOVW,	C_SACON,C_NONE,	C_REG,		 3, 4, REGSP },
+	{ AMOVV,	C_SACON,C_NONE,	C_REG,		 3, 4, REGSP },
 	{ AMOVW,	C_LECON,C_NONE,	C_REG,		26, 12, REGSB },
+	{ AMOVV,	C_LECON,C_NONE,	C_REG,		26, 12, REGSB },
 	{ AMOVW,	C_LACON,C_NONE,	C_REG,		26, 12, REGSP },
+	{ AMOVV,	C_LACON,C_NONE,	C_REG,		26, 12, REGSP },
 	{ AMOVW,	C_ADDCON,C_NONE,C_REG,		 3, 4, REGZERO },
 	{ AMOVV,	C_ADDCON,C_NONE,C_REG,		 3, 4, REGZERO },
 	{ AMOVW,	C_ANDCON,C_NONE,C_REG,		 3, 4, REGZERO },
@@ -217,5 +221,8 @@ Optab	optab[] =
 	{ ABREAK,	C_REG,	C_NONE,	C_SOREG,	 7, 4, REGZERO },
 	{ ABREAK,	C_NONE,	C_NONE,	C_NONE,		 5, 4, 0 },
 
+	{ ACASE,	C_REG,	C_NONE,	C_NONE,		 45, 28, 0 },
+	{ ABCASE,	C_LCON,	C_NONE,	C_LBRA,		 46, 4, 0 },
+
 	{ AXXX,		C_NONE,	C_NONE,	C_NONE,		 0, 4, 0 },
 };

+ 19 - 7
sys/src/cmd/4l/pass.c

@@ -26,6 +26,17 @@ dodata(void)
 				s->value, s->name, p);
 	}
 
+	if(debug['t']) {
+		/*
+		 * pull out string constants
+		 */
+		for(p = datap; p != P; p = p->link) {
+			s = p->from.sym;
+			if(p->to.type == D_SCONST)
+				s->type = SSTRING;
+		}
+	}
+
 	/*
 	 * pass 1
 	 *	assign 'small' variables to data segment
@@ -126,9 +137,10 @@ dodata(void)
 				continue;
 			/* size should be 19 max */
 			if(strlen(s->name) >= 10)	/* has loader address */
-				sprint(literal, "$%lux.%lux", (long)s, p->from.offset);
+				sprint(literal, "$%p.%llux", s, p->from.offset);
 			else
-				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
+				sprint(literal, "$%s.%d.%llux", s->name,
+					s->version, p->from.offset);
 		} else {
 			if(p->from.name != D_NONE)
 				continue;
@@ -371,7 +383,7 @@ patch(void)
 			q = q->link;
 		}
 		if(q == P) {
-			diag("branch out of range %ld\n%P", c, p);
+			diag("branch out of range %lld\n%P", c, p);
 			p->to.type = D_NONE;
 		}
 		p->cond = q;
@@ -442,10 +454,10 @@ brloop(Prog *p)
 	return P;
 }
 
-long
+vlong
 atolwhex(char *s)
 {
-	long n;
+	vlong n;
 	int f;
 
 	n = 0;
@@ -523,9 +535,9 @@ atovlwhex(char *s)
 }
 
 vlong
-rnd(vlong v, vlong r)
+rnd(vlong v, long r)
 {
-	vlong c;
+	long c;
 
 	if(r <= 0)
 		return v;

+ 1 - 2
sys/src/cmd/4l/sched.c

@@ -144,8 +144,7 @@ sched(Prog *p0, Prog *pe)
 		}
 		if(debug['X'])
 			Bprint(&bso, "?l%P\n", &s->p);
-		if(s->p.mark & BRANCH)
-			s->nop = 1;
+		s->nop = 1;
 		if(debug['v']) {
 			if(s->p.mark & LOAD) {
 				nop.load.count++;

+ 86 - 18
sys/src/cmd/4l/span.c

@@ -1,13 +1,43 @@
 #include	"l.h"
 
+void
+pagebug(Prog *p)
+{
+	Prog *q;
+
+	switch(p->as) {
+	case ABGEZAL:
+	case ABLTZAL:
+	case AJAL:
+	case ABEQ:
+	case ABGEZ:
+	case ABGTZ:
+	case ABLEZ:
+	case ABLTZ:
+	case ABNE:
+	case ABFPT:
+	case ABFPF:
+	case AJMP:
+		q = prg();
+		*q = *p;
+		p->link = q;
+		p->as = ANOR;
+		p->optab = 0;
+		p->from = zprg.from;
+		p->from.type = D_REG;
+		p->from.reg = REGZERO;
+		p->to = p->from;
+	}
+}
+
 void
 span(void)
 {
 	Prog *p, *q;
-	Sym *setext;
+	Sym *setext, *s;
 	Optab *o;
-	int m, bflag;
-	vlong c, otxt;
+	int m, bflag, i;
+	vlong c, otxt, v;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f span\n", cputime());
@@ -17,6 +47,9 @@ span(void)
 	c = INITTEXT;
 	otxt = c;
 	for(p = firstp; p != P; p = p->link) {
+		/* bug in early 4000 chips delayslot on page boundary */
+		if((c&(0x1000-1)) == 0xffc)
+			pagebug(p);
 		p->pc = c;
 		o = oplook(p);
 		m = o->size;
@@ -50,6 +83,9 @@ span(void)
 		bflag = 0;
 		c = INITTEXT;
 		for(p = firstp; p != P; p = p->link) {
+			/* bug in early 4000 chips delayslot on page boundary */
+			if((c&(0x1000-1)) == 0xffc)
+				pagebug(p);
 			p->pc = c;
 			o = oplook(p);
 			if(o->type == 6 && p->cond) {
@@ -90,6 +126,24 @@ span(void)
 			c += m;
 		}
 	}
+
+	if(debug['t']) {
+		/*
+		 * add strings to text segment
+		 */
+		c = rnd(c, 8);
+		for(i=0; i<NHASH; i++)
+		for(s = hash[i]; s != S; s = s->link) {
+			if(s->type != SSTRING)
+				continue;
+			v = s->value;
+			while(v & 3)
+				v++;
+			s->value = c;
+			c += v;
+		}
+	}
+
 	c = rnd(c, 8);
 
 	setext = lookup("etext", 0);
@@ -100,12 +154,12 @@ span(void)
 	if(INITRND)
 		INITDAT = rnd(c, INITRND);
 	if(debug['v'])
-		Bprint(&bso, "tsize = %lux\n", textsize);
+		Bprint(&bso, "tsize = %llux\n", textsize);
 	Bflush(&bso);
 }
 
 void
-xdefine(char *p, int t, long v)
+xdefine(char *p, int t, vlong v)
 {
 	Sym *s;
 
@@ -125,6 +179,24 @@ regoff(Adr *a)
 	return instoffset;
 }
 
+int
+isint32(vlong v)
+{
+	long l;
+
+	l = v;
+	return (vlong)l == v;
+}
+
+int
+isuint32(uvlong v)
+{
+	ulong l;
+
+	l = v;
+	return (uvlong)l == v;
+}
+
 int
 aclass(Adr *a)
 {
@@ -212,7 +284,6 @@ aclass(Adr *a)
 
 	case D_CONST:
 		switch(a->name) {
-
 		case D_NONE:
 			instoffset = a->offset;
 		consize:
@@ -221,7 +292,7 @@ aclass(Adr *a)
 					return C_SCON;
 				if(instoffset <= 0xffff)
 					return C_ANDCON;
-				if((instoffset & 0xffff) == 0)
+				if((instoffset & 0xffff) == 0 && isuint32(instoffset))
 					return C_UCON;
 				return C_LCON;
 			}
@@ -229,7 +300,7 @@ aclass(Adr *a)
 				return C_ZCON;
 			if(instoffset >= -0x8000)
 				return C_ADDCON;
-			if((instoffset & 0xffff) == 0)
+			if((instoffset & 0xffff) == 0 && isint32(instoffset))
 				return C_UCON;
 			return C_LCON;
 
@@ -283,7 +354,7 @@ aclass(Adr *a)
 Optab*
 oplook(Prog *p)
 {
-	int a1, a2, a3, r, t;
+	int a1, a2, a3, r;
 	char *c1, *c3;
 	Optab *o, *e;
 
@@ -308,10 +379,10 @@ oplook(Prog *p)
 	r = p->as;
 	o = oprange[r].start;
 	if(o == 0) {
-		t = opcross[repop[r]][a1][a2][a3];
-		if(t) {
-			p->optab = t+1;
-			return optab+t;
+		a1 = opcross[repop[r]][a1][a2][a3];
+		if(a1) {
+			p->optab = a1+1;
+			return optab+a1;
 		}
 		o = oprange[r].stop; /* just generate an error */
 	}
@@ -326,7 +397,7 @@ oplook(Prog *p)
 			return o;
 		}
 	diag("illegal combination %A %d %d %d",
-		p->as, a1, a2, a3);
+		p->as, p->from.class-1, a2, a3);
 	if(!debug['a'])
 		prasm(p);
 	o = optab;
@@ -595,10 +666,7 @@ buildrep(int x, int as)
 	Optab *e, *s, *o;
 	int a1, a2, a3, n;
 
-	if(C_NONE != 0 ||
-	   C_REG != 1 ||
-	   C_GOK >= 32 ||
-	   x >= nelem(opcross)) {
+	if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
 		diag("assumptions fail in buildrep");
 		errorexit();
 	}

+ 22 - 0
sys/src/libc/9syscall/mkfile

@@ -44,6 +44,28 @@ install:V:
 				MOVW R1,4(R5)'
 			}
 			echo RET
+		case mips64
+			if(~ $i seek || ~ $i nsec)
+				echo TEXT _$i'(SB)', 1, '$0'
+			if not
+				echo TEXT $i'(SB)', 1, '$0'
+			echo MOVV R1, '0(FP)'
+			echo MOVW '$'$n, R1
+			echo ADDV '$8',R29
+			echo SYSCALL
+			echo ADDV '$-8',R29
+			echo RET
+		case spim64
+			if(~ $i seek || ~ $i nsec)
+				echo TEXT _$i'(SB)', 1, '$0'
+			if not
+				echo TEXT $i'(SB)', 1, '$0'
+			echo MOVV R1, '0(FP)'
+			echo MOVW '$'$n, R1
+			echo ADDV '$8',R29
+			echo SYSCALL
+			echo ADDV '$-8',R29
+			echo RET
 		case 386
 			echo TEXT $i'(SB)', 1, '$0'
 			echo MOVL '$'$n, AX

+ 14 - 0
sys/src/libc/mips64/_nsec.c

@@ -0,0 +1,14 @@
+#include <u.h>
+#include <libc.h>
+
+extern int _nsec(vlong*);
+
+vlong
+nsec(void)
+{
+	vlong l;
+
+	if(_nsec(&l) < 0)
+		l = -1LL;
+	return l;
+}

+ 14 - 0
sys/src/libc/mips64/_seek.c

@@ -0,0 +1,14 @@
+#include <u.h>
+#include <libc.h>
+
+extern int _seek(vlong*, int, vlong, int);
+
+vlong
+seek(int fd, vlong o, int p)
+{
+	vlong l;
+
+	if(_seek(&l, fd, o, p) < 0)
+		l = -1LL;
+	return l;
+}

+ 4 - 0
sys/src/libc/mips64/argv0.s

@@ -0,0 +1,4 @@
+GLOBL	argv0(SB), $8
+GLOBL	_tos(SB), $8
+GLOBL	_privates(SB), $8
+GLOBL	_nprivates(SB), $4

+ 52 - 0
sys/src/libc/mips64/atom.s

@@ -0,0 +1,52 @@
+/*
+ *	R4000 user-level atomic operations
+ */
+
+#define	LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define	SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define	NOOP		WORD	$0x27
+
+TEXT ainc(SB), 1, $-8			/* long ainc(long *); */
+TEXT _xinc(SB), 1, $-8			/* void _xinc(long *); */
+	MOVV	R1, R2			/* address of counter */
+loop:	MOVW	$1, R3
+	LL(2, 1)
+	NOOP
+	ADDU	R1, R3
+	MOVV	R3, R1			/* return new value */
+	SC(2, 3)
+	NOOP
+	BEQ	R3,loop
+	RET
+
+TEXT adec(SB), 1, $-8			/* long adec(long*); */
+TEXT _xdec(SB), 1, $-8			/* long _xdec(long *); */
+	MOVV	R1, R2			/* address of counter */
+loop1:	MOVW	$-1, R3
+	LL(2, 1)
+	NOOP
+	ADDU	R1, R3
+	MOVV	R3, R1			/* return new value */
+	SC(2, 3)
+	NOOP
+	BEQ	R3,loop1
+	RET
+
+/*
+ * int cas(uint* p, int ov, int nv);
+ */
+TEXT cas(SB), 1, $-8
+	MOVW	ov+12(FP), R2
+	MOVW	nv+20(FP), R3
+spincas:
+	LL(1, 4)			/* R4 = *R1 */
+	NOOP
+	BNE	R2, R4, fail
+	SC(1, 3)			/* *R1 = R3 */
+	NOOP
+	BEQ	R3, spincas		/* R3 == 0 means store failed */
+	MOVW	$1, R1
+	RET
+fail:
+	MOVV	$0, R1
+	RET

+ 3 - 0
sys/src/libc/mips64/c_fcr0.s

@@ -0,0 +1,3 @@
+	TEXT	C_fcr0(SB), $0
+	MOVW	FCR0, R1
+	RET

+ 10 - 0
sys/src/libc/mips64/cycles.c

@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+
+#pragma profile off
+
+void
+cycles(uvlong*u)
+{
+	*u = 0LL;
+}

+ 3 - 0
sys/src/libc/mips64/getcallerpc.s

@@ -0,0 +1,3 @@
+TEXT	getcallerpc(SB), $0
+	MOVV	0(SP), R1
+	RET

+ 15 - 0
sys/src/libc/mips64/getfcr.s

@@ -0,0 +1,15 @@
+TEXT	getfsr(SB), $0
+	MOVW	FCR31, R1
+	RET
+
+TEXT	setfsr(SB), $0
+	MOVW	R1, FCR31
+	RET
+
+TEXT	getfcr(SB), $0
+	MOVW	FCR31, R1
+	RET
+
+TEXT	setfcr(SB), $0
+	MOVW	R1, FCR31
+	RET

+ 25 - 0
sys/src/libc/mips64/main9.s

@@ -0,0 +1,25 @@
+#define NPRIVATES	16
+
+TEXT	_main(SB), 1, $(16 + NPRIVATES*8)
+
+	MOVV	$setR30(SB), R30
+	MOVV	R1, _tos(SB)
+
+	MOVV	$p-(NPRIVATES*8)(SP), R1
+	MOVV	R1, _privates(SB)
+	MOVW	$NPRIVATES, R1
+	MOVW	R1, _nprivates(SB)
+
+	MOVW	inargc-4(FP), R1
+	MOVV	$inargv+0(FP), R2
+	MOVW	R1, 12(R29)
+	MOVV	R2, 16(R29)
+	JAL	main(SB)
+loop:
+	MOVV	$_exitstr<>(SB), R1
+	MOVV	R1, 8(R29)
+	JAL	exits(SB)
+	JMP	loop
+
+DATA	_exitstr<>+0(SB)/4, $"main"
+GLOBL	_exitstr<>+0(SB), $5

+ 41 - 0
sys/src/libc/mips64/main9p.s

@@ -0,0 +1,41 @@
+#define NPRIVATES	16
+
+TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
+
+	MOVW	$setR30(SB), R30
+	/* _tos = arg */
+	MOVW	R1, _tos(SB)
+
+	MOVW	$p-64(SP), R1
+	MOVW	R1, _privates(SB)
+	MOVW	$NPRIVATES, R1
+	MOVW	R1, _nprivates(SB)
+
+	/* _profmain(); */
+	JAL	_profmain(SB)
+	/* _tos->prof.pp = _tos->prof.next; */
+	MOVW	_tos(SB), R1
+	MOVW	4(R1), R2
+	MOVW	R2, 0(R1)
+	/* main(argc, argv); */
+	MOVW	inargc-4(FP), R1
+	MOVW	$inargv+0(FP), R2
+	MOVW	R1, 4(R29)
+	MOVW	R2, 8(R29)
+	JAL	main(SB)
+loop:
+	MOVW	$exits<>(SB), R1
+	MOVW	R1, 4(R29)
+	JAL	exits(SB)
+	MOVW	$_profin(SB), R0	/* force loading of profile */
+	JMP	loop
+
+TEXT	_savearg(SB), 1, $0
+	RET
+
+TEXT	_callpc(SB), 1, $0
+	MOVW	argp-4(FP), R1
+	RET
+
+DATA	exits<>+0(SB)/4, $"main"
+GLOBL	exits<>+0(SB), $5

+ 40 - 0
sys/src/libc/mips64/mkfile

@@ -0,0 +1,40 @@
+objtype=mips64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libc.a
+SFILES=\
+	argv0.s\
+	atom.s\
+	c_fcr0.s\
+	getcallerpc.s\
+	getfcr.s\
+	main9.s\
+	main9p.s\
+#	memccpy.s\
+#	memchr.s\
+#	memcmp.s\
+#	memmove.s\
+#	memset.s\
+	setjmp.s\
+#	strchr.s\
+#	strcmp.s\
+#	strcpy.s\
+	tas.s\
+
+CFILES=\
+	_nsec.c\
+	_seek.c\
+	cycles.c\
+	notejmp.c\
+	sqrt.c\
+
+HFILES=/sys/include/libc.h
+
+OFILES=${CFILES:%.c=%.$O} ${SFILES:%.s=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$CFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

+ 16 - 0
sys/src/libc/mips64/notejmp.c

@@ -0,0 +1,16 @@
+#include <u.h>
+#include <libc.h>
+#include <ureg.h>
+
+void
+notejmp(void *vr, jmp_buf j, int ret)
+{
+	struct Ureg *r = vr;
+
+	r->r1 = ret;
+	if(ret == 0)
+		r->r1 = 1;
+	r->pc = j[JMPBUFPC];
+	r->sp = j[JMPBUFSP];
+	noted(NCONT);
+}

+ 14 - 0
sys/src/libc/mips64/setjmp.s

@@ -0,0 +1,14 @@
+TEXT	setjmp(SB), 1, $-8
+	MOVV	R29, (R1)
+	MOVV	R31, 8(R1)
+	MOVV	$0, R1
+	RET
+
+TEXT	longjmp(SB), 1, $-8
+	MOVW	r+12(FP), R3
+	BNE	R3, ok		/* ansi: "longjmp(0) => longjmp(1)" */
+	MOVW	$1, R3		/* bless their pointed heads */
+ok:	MOVV	(R1), R29
+	MOVV	8(R1), R31
+	MOVV	R3, R1
+	RET

+ 103 - 0
sys/src/libc/mips64/sqrt.c

@@ -0,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+
+static	long	sqtab[64] =
+{
+	0x6cdb2, 0x726d4, 0x77ea3, 0x7d52f, 0x82a85, 0x87eb1, 0x8d1c0, 0x923bd,
+	0x974b2, 0x9c4a8, 0xa13a9, 0xa61be, 0xaaeee, 0xafb41, 0xb46bf, 0xb916e,
+	0xbdb55, 0xc247a, 0xc6ce3, 0xcb495, 0xcfb95, 0xd41ea, 0xd8796, 0xdcca0,
+	0xe110c, 0xe54dd, 0xe9818, 0xedac0, 0xf1cd9, 0xf5e67, 0xf9f6e, 0xfdfef,
+	0x01fe0, 0x05ee6, 0x09cfd, 0x0da30, 0x11687, 0x1520c, 0x18cc8, 0x1c6c1,
+	0x20000, 0x2388a, 0x27068, 0x2a79e, 0x2de32, 0x3142b, 0x3498c, 0x37e5b,
+	0x3b29d, 0x3e655, 0x41989, 0x44c3b, 0x47e70, 0x4b02b, 0x4e16f, 0x51241,
+	0x542a2, 0x57296, 0x5a220, 0x5d142, 0x60000, 0x62e5a, 0x65c55, 0x689f2,
+};
+
+double
+sqrt(double arg)
+{
+	int e, ms;
+	double a, t;
+	union
+	{
+		double	d;
+		struct
+		{
+			long	ms;
+			long	ls;
+		};
+	} u;
+
+	u.d = arg;
+	ms = u.ms;
+
+	/*
+	 * sign extend the mantissa with
+	 * exponent. result should be > 0 for
+	 * normal case.
+	 */
+	e = ms >> 20;
+	if(e <= 0) {
+		if(e == 0)
+			return 0;
+		return NaN();
+	}
+
+	/*
+	 * pick up arg/4 by adjusting exponent
+	 */
+	u.ms = ms - (2 << 20);
+	a = u.d;
+
+	/*
+	 * use 5 bits of mantissa and 1 bit
+	 * of exponent to form table index.
+	 * insert exponent/2 - 1.
+	 */
+	e = (((e - 1023) >> 1) + 1022) << 20;
+	u.ms = *(long*)((char*)sqtab + ((ms >> 13) & 0xfc)) | e;
+	u.ls = 0;
+
+	/*
+	 * three laps of newton
+	 */
+	e = 1 << 20;
+	t = u.d;
+	u.d = t + a/t;
+	u.ms -= e;		/* u.d /= 2; */
+	t = u.d;
+	u.d = t + a/t;
+	u.ms -= e;		/* u.d /= 2; */
+	t = u.d;
+
+	return t + a/t;
+}
+
+/*
+ * this is the program that generated the table.
+ * it calls sqrt by some other means.
+ *
+ * void
+ * main(void)
+ * {
+ * 	int i;
+ * 	union	U
+ * 	{
+ * 		double	d;
+ * 		struct
+ * 		{
+ * 			long	ms;
+ * 			long	ls;
+ * 		};
+ * 	} u;
+ *
+ * 	for(i=0; i<64; i++) {
+ * 		u.ms = (i<<15) | 0x3fe04000;
+ * 		u.ls = 0;
+ * 		u.d = sqrt(u.d);
+ * 		print(" 0x%.5lux,", u.ms & 0xfffff);
+ * 	}
+ * 	print("\n");
+ * 	exits(0);
+ * }
+ */

+ 19 - 0
sys/src/libc/mips64/tas.s

@@ -0,0 +1,19 @@
+/*
+ *	mips user level lock code
+ */
+
+#define	LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define	SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define	NOOP		WORD	$0x27
+
+	TEXT	_tas(SB), $0
+	TEXT	C_4ktas(SB), $0
+	MOVV	R1, R2		/* address of key */
+tas1:
+	MOVW	$1, R3
+	LL(2, 1)
+	NOOP
+	SC(2, 3)
+	NOOP
+	BEQ	R3, tas1
+	RET

+ 14 - 0
sys/src/libc/spim64/_nsec.c

@@ -0,0 +1,14 @@
+#include <u.h>
+#include <libc.h>
+
+extern int _nsec(vlong*);
+
+vlong
+nsec(void)
+{
+	vlong l;
+
+	if(_nsec(&l) < 0)
+		l = -1LL;
+	return l;
+}

+ 14 - 0
sys/src/libc/spim64/_seek.c

@@ -0,0 +1,14 @@
+#include <u.h>
+#include <libc.h>
+
+extern int _seek(vlong*, int, vlong, int);
+
+vlong
+seek(int fd, vlong o, int p)
+{
+	vlong l;
+
+	if(_seek(&l, fd, o, p) < 0)
+		l = -1LL;
+	return l;
+}

+ 4 - 0
sys/src/libc/spim64/argv0.s

@@ -0,0 +1,4 @@
+GLOBL	argv0(SB), $8
+GLOBL	_tos(SB), $8
+GLOBL	_privates(SB), $8
+GLOBL	_nprivates(SB), $4

+ 52 - 0
sys/src/libc/spim64/atom.s

@@ -0,0 +1,52 @@
+/*
+ *	R4000 user-level atomic operations
+ */
+
+#define	LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define	SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define	NOOP		WORD	$0x27
+
+TEXT ainc(SB), 1, $-8			/* long ainc(long *); */
+TEXT _xinc(SB), 1, $-8			/* void _xinc(long *); */
+	MOVV	R1, R2			/* address of counter */
+loop:	MOVW	$1, R3
+	LL(2, 1)
+	NOOP
+	ADDU	R1, R3
+	MOVV	R3, R1			/* return new value */
+	SC(2, 3)
+	NOOP
+	BEQ	R3,loop
+	RET
+
+TEXT adec(SB), 1, $-8			/* long adec(long*); */
+TEXT _xdec(SB), 1, $-8			/* long _xdec(long *); */
+	MOVV	R1, R2			/* address of counter */
+loop1:	MOVW	$-1, R3
+	LL(2, 1)
+	NOOP
+	ADDU	R1, R3
+	MOVV	R3, R1			/* return new value */
+	SC(2, 3)
+	NOOP
+	BEQ	R3,loop1
+	RET
+
+/*
+ * int cas(uint* p, int ov, int nv);
+ */
+TEXT cas(SB), 1, $-8
+	MOVW	ov+8(FP), R2
+	MOVW	nv+16(FP), R3
+spincas:
+	LL(1, 4)			/* R4 = *R1 */
+	NOOP
+	BNE	R2, R4, fail
+	SC(1, 3)			/* *R1 = R3 */
+	NOOP
+	BEQ	R3, spincas		/* R3 == 0 means store failed */
+	MOVW	$1, R1
+	RET
+fail:
+	MOVV	$0, R1
+	RET

+ 3 - 0
sys/src/libc/spim64/c_fcr0.s

@@ -0,0 +1,3 @@
+	TEXT	C_fcr0(SB), $0
+	MOVW	FCR0, R1
+	RET

+ 10 - 0
sys/src/libc/spim64/cycles.c

@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+
+#pragma profile off
+
+void
+cycles(uvlong*u)
+{
+	*u = 0LL;
+}

+ 3 - 0
sys/src/libc/spim64/getcallerpc.s

@@ -0,0 +1,3 @@
+TEXT	getcallerpc(SB), $0
+	MOVV	0(SP), R1
+	RET

+ 15 - 0
sys/src/libc/spim64/getfcr.s

@@ -0,0 +1,15 @@
+TEXT	getfsr(SB), $0
+	MOVW	FCR31, R1
+	RET
+
+TEXT	setfsr(SB), $0
+	MOVW	R1, FCR31
+	RET
+
+TEXT	getfcr(SB), $0
+	MOVW	FCR31, R1
+	RET
+
+TEXT	setfcr(SB), $0
+	MOVW	R1, FCR31
+	RET

+ 25 - 0
sys/src/libc/spim64/main9.s

@@ -0,0 +1,25 @@
+#define NPRIVATES	16
+
+TEXT	_main(SB), 1, $(16 + NPRIVATES*8)
+
+	MOVV	$setR30(SB), R30
+	MOVV	R1, _tos(SB)
+
+	MOVV	$p-(NPRIVATES*8)(SP), R1
+	MOVV	R1, _privates(SB)
+	MOVW	$NPRIVATES, R1
+	MOVW	R1, _nprivates(SB)
+
+	MOVW	inargc-8(FP), R1
+	MOVV	$inargv+0(FP), R2
+	MOVW	R1, 8(R29)
+	MOVV	R2, 16(R29)
+	JAL	main(SB)
+loop:
+	MOVV	$_exitstr<>(SB), R1
+	MOVV	R1, 8(R29)
+	JAL	exits(SB)
+	JMP	loop
+
+DATA	_exitstr<>+0(SB)/4, $"main"
+GLOBL	_exitstr<>+0(SB), $5

+ 41 - 0
sys/src/libc/spim64/main9p.s

@@ -0,0 +1,41 @@
+#define NPRIVATES	16
+
+TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
+
+	MOVW	$setR30(SB), R30
+	/* _tos = arg */
+	MOVW	R1, _tos(SB)
+
+	MOVW	$p-64(SP), R1
+	MOVW	R1, _privates(SB)
+	MOVW	$NPRIVATES, R1
+	MOVW	R1, _nprivates(SB)
+
+	/* _profmain(); */
+	JAL	_profmain(SB)
+	/* _tos->prof.pp = _tos->prof.next; */
+	MOVW	_tos(SB), R1
+	MOVW	4(R1), R2
+	MOVW	R2, 0(R1)
+	/* main(argc, argv); */
+	MOVW	inargc-4(FP), R1
+	MOVW	$inargv+0(FP), R2
+	MOVW	R1, 4(R29)
+	MOVW	R2, 8(R29)
+	JAL	main(SB)
+loop:
+	MOVW	$exits<>(SB), R1
+	MOVW	R1, 4(R29)
+	JAL	exits(SB)
+	MOVW	$_profin(SB), R0	/* force loading of profile */
+	JMP	loop
+
+TEXT	_savearg(SB), 1, $0
+	RET
+
+TEXT	_callpc(SB), 1, $0
+	MOVW	argp-4(FP), R1
+	RET
+
+DATA	exits<>+0(SB)/4, $"main"
+GLOBL	exits<>+0(SB), $5

+ 20 - 0
sys/src/libc/spim64/memccpy.s

@@ -0,0 +1,20 @@
+	TEXT	memccpy(SB), $0
+MOVV R1, 0(FP)
+	MOVW	n+24(FP), R1
+	BEQ	R1, ret
+	MOVV	s1+0(FP), R3
+	MOVV	s2+8(FP), R2
+	MOVBU	c+16(FP), R4	/* little endian */
+	ADDVU	R1, R2, R5
+
+l1:	MOVBU	(R2), R6
+	ADDVU	$1, R2
+	MOVBU	R6, (R3)
+	ADDVU	$1, R3
+	BEQ	R4, R6, eq
+	BNE	R2, R5, l1
+	MOVV	$0, R1
+	RET
+
+eq:	MOVV	R3, R1
+ret:	RET

+ 39 - 0
sys/src/libc/spim64/memchr.s

@@ -0,0 +1,39 @@
+	TEXT	memchr(SB), $0
+MOVV R1, 0(FP)
+
+	MOVW	n+16(FP), R1
+	MOVV	s1+0(FP), R2
+	MOVBU	c+8(FP), R3
+	ADDVU	R1, R2, R6
+
+	AND	$(~1), R1, R5
+	ADDVU	R2, R5
+	BEQ	R2, R5, lt2
+
+l1:
+	MOVBU	0(R2), R4
+	MOVBU	1(R2), R7
+	BEQ	R3, R4, eq0
+	ADDVU	$2, R2
+	BEQ	R3, R7, eq
+	BNE	R2, R5, l1
+
+lt2:
+	BEQ	R2, R6, zret
+
+l2:
+	MOVBU	(R2), R4
+	ADDVU	$1, R2
+	BEQ	R3, R4, eq
+	BNE	R2, R6, l2
+zret:
+	MOVV	R0, R1
+	RET
+
+eq0:
+	MOVV	R2, R1
+	RET
+
+eq:
+	SUBVU	$1,R2, R1
+	RET

+ 237 - 0
sys/src/libc/spim64/memmove.s

@@ -0,0 +1,237 @@
+	TEXT	memmove(SB), $0
+
+	JMP	move
+
+	TEXT	memcpy(SB), $0
+move:
+	MOVV	R1, s1+0(FP)
+
+	MOVW	n+16(FP), R3		/* R3 is count */
+	MOVV	R1, R4			/* R4 is to-pointer */
+	SGT	R0, R3, R5
+	BEQ	R5, ok
+	MOVW	(R0), R0		/* abort if negative count */
+ok:
+	MOVV	s2+8(FP), R5	/* R5 is from-pointer */
+	ADDVU	R3,R5, R7		/* R7 is end from-pointer */
+	ADDVU	R3,R4, R6		/* R6 is end to-pointer */
+
+/*
+ * easiest test is copy backwards if
+ * destination string has higher mem address
+ */
+	SGT	$4,R3, R2
+	SGTU	R4,R5, R1
+	BNE	R1, back
+
+/*
+ * if not at least 4 chars,
+ * don't even mess around.
+ * 3 chars to guarantee any
+ * rounding up to a word
+ * boundary and 4 characters
+ * to get at least maybe one
+ * full word store.
+ */
+	BNE	R2, fout
+
+
+/*
+ * byte at a time to word align destination
+ */
+f1:
+	AND	$3,R4, R1
+	BEQ	R1, f2
+	MOVB	0(R5), R8
+	ADDVU	$1, R5
+	MOVB	R8, 0(R4)
+	ADDVU	$1, R4
+	JMP	f1
+
+/*
+ * test if source is now word aligned
+ */
+f2:
+	AND	$3, R5, R1
+	BNE	R1, fun2
+/*
+ * turn R3 into to-end pointer-15
+ * copy 16 at a time while theres room.
+ * R6 is smaller than R7 --
+ * there are problems if R7 is 0.
+ */
+	ADDVU	$-15,R6, R3
+f3:
+	SGTU	R3,R4, R1
+	BEQ	R1, f4
+	MOVW	0(R5), R8
+	MOVW	4(R5), R9
+	MOVW	R8, 0(R4)
+	MOVW	8(R5), R8
+	MOVW	R9, 4(R4)
+	MOVW	12(R5), R9
+	ADDVU	$16, R5
+	MOVW	R8, 8(R4)
+	MOVW	R9, 12(R4)
+	ADDVU	$16, R4
+	JMP	f3
+
+/*
+ * turn R3 into to-end pointer-3
+ * copy 4 at a time while theres room
+ */
+f4:
+	ADDVU	$-3,R6, R3
+f5:
+	SGTU	R3,R4, R1
+	BEQ	R1, fout
+	MOVW	0(R5), R8
+	ADDVU	$4, R5
+	MOVW	R8, 0(R4)
+	ADDVU	$4, R4
+	JMP	f5
+
+/*
+ * forward copy, unaligned
+ * turn R3 into to-end pointer-15
+ * copy 16 at a time while theres room.
+ * R6 is smaller than R7 --
+ * there are problems if R7 is 0.
+ */
+fun2:
+	ADDVU	$-15,R6, R3
+fun3:
+	SGTU	R3,R4, R1
+	BEQ	R1, fun4
+	MOVWR	0(R5), R8
+	MOVWL	3(R5), R8
+	MOVWR	4(R5), R9
+	MOVWL	7(R5), R9
+	MOVW	R8, 0(R4)
+	MOVWR	8(R5), R8
+	MOVWL	11(R5), R8
+	MOVW	R9, 4(R4)
+	MOVWR	12(R5), R9
+	MOVWL	15(R5), R9
+	ADDVU	$16, R5
+	MOVW	R8, 8(R4)
+	MOVW	R9, 12(R4)
+	ADDVU	$16, R4
+	JMP	fun3
+
+/*
+ * turn R3 into to-end pointer-3
+ * copy 4 at a time while theres room
+ */
+fun4:
+	ADDVU	$-3,R6, R3
+fun5:
+	SGTU	R3,R4, R1
+	BEQ	R1, fout
+	MOVWR	0(R5), R8
+	MOVWL	3(R5), R8
+	ADDVU	$4, R5
+	MOVW	R8, 0(R4)
+	ADDVU	$4, R4
+	JMP	fun5
+
+/*
+ * last loop, copy byte at a time
+ */
+fout:
+	BEQ	R7,R5, ret
+	MOVB	0(R5), R8
+	ADDVU	$1, R5
+	MOVB	R8, 0(R4)
+	ADDVU	$1, R4
+	JMP	fout
+
+/*
+ * whole thing repeated for backwards
+ */
+back:
+	BNE	R2, bout
+b1:
+	AND	$3,R6, R1
+	BEQ	R1, b2
+	MOVB	-1(R7), R8
+	ADDVU	$-1, R7
+	MOVB	R8, -1(R6)
+	ADDVU	$-1, R6
+	JMP	b1
+
+b2:
+	AND	$3, R7, R1
+	BNE	R1, bun2
+
+	ADDVU	$15,R5, R3
+b3:
+	SGTU	R7,R3, R1
+	BEQ	R1, b4
+	MOVW	-4(R7), R8
+	MOVW	-8(R7), R9
+	MOVW	R8, -4(R6)
+	MOVW	-12(R7), R8
+	MOVW	R9, -8(R6)
+	MOVW	-16(R7), R9
+	ADDVU	$-16, R7
+	MOVW	R8, -12(R6)
+	MOVW	R9, -16(R6)
+	ADDVU	$-16, R6
+	JMP	b3
+b4:
+	ADDVU	$3,R5, R3
+b5:
+	SGTU	R7,R3, R1
+	BEQ	R1, bout
+	MOVW	-4(R7), R8
+	ADDVU	$-4, R7
+	MOVW	R8, -4(R6)
+	ADDVU	$-4, R6
+	JMP	b5
+
+bun2:
+	ADDVU	$15,R5, R3
+bun3:
+	SGTU	R7,R3, R1
+	BEQ	R1, bun4
+	MOVWR	-4(R7), R8
+	MOVWL	-1(R7), R8
+	MOVWR	-8(R7), R9
+	MOVWL	-5(R7), R9
+	MOVW	R8, -4(R6)
+	MOVWR	-12(R7), R8
+	MOVWL	-9(R7), R8
+	MOVW	R9, -8(R6)
+	MOVWR	-16(R7), R9
+	MOVWL	-13(R7), R9
+	ADDVU	$-16, R7
+	MOVW	R8, -12(R6)
+	MOVW	R9, -16(R6)
+	ADDVU	$-16, R6
+	JMP	bun3
+
+bun4:
+	ADDVU	$3,R5, R3
+bun5:
+	SGTU	R7,R3, R1
+	BEQ	R1, bout
+	MOVWR	-4(R7), R8
+	MOVWL	-1(R7), R8
+	ADDVU	$-4, R7
+	MOVW	R8, -4(R6)
+	ADDVU	$-4, R6
+	JMP	bun5
+
+bout:
+	BEQ	R7,R5, ret
+	MOVB	-1(R7), R8
+	ADDVU	$-1, R7
+	MOVB	R8, -1(R6)
+	ADDVU	$-1, R6
+	JMP	bout
+
+ret:
+	MOVV	s1+0(FP), R1
+	RET
+	END

+ 88 - 0
sys/src/libc/spim64/memset.s

@@ -0,0 +1,88 @@
+	TEXT	memset(SB), $0
+MOVV R1, 0(FP)
+
+/*
+ * performance:
+ *	about 1us/call and 28mb/sec
+ */
+
+	MOVW	n+16(FP), R3		/* R3 is count */
+	MOVV	p+0(FP), R4		/* R4 is pointer */
+	MOVW	c+8(FP), R5		/* R5 is char */
+	ADDVU	R3,R4, R6		/* R6 is end pointer */
+
+/*
+ * if not at least 4 chars,
+ * dont even mess around.
+ * 3 chars to guarantee any
+ * rounding up to a word
+ * boundary and 4 characters
+ * to get at least maybe one
+ * full word store.
+ */
+	SGT	$4,R3, R1
+	BNE	R1, out
+
+/*
+ * turn R5 into a word of characters
+ */
+	AND	$0xff, R5
+	SLL	$8,R5, R1
+	OR	R1, R5
+	SLL	$16,R5, R1
+	OR	R1, R5
+
+/*
+ * store one byte at a time until pointer
+ * is alligned on a word boundary
+ */
+l1:
+	AND	$3,R4, R1
+	BEQ	R1, l2
+	MOVB	R5, 0(R4)
+	ADDVU	$1, R4
+	JMP	l1
+
+/*
+ * turn R3 into end pointer-15
+ * store 16 at a time while theres room
+ */
+l2:
+	ADDVU	$-15,R6, R3
+l3:
+	SGTU	R3,R4, R1
+	BEQ	R1, l4
+	MOVW	R5, 0(R4)
+	MOVW	R5, 4(R4)
+	ADDVU	$16, R4
+	MOVW	R5, -8(R4)
+	MOVW	R5, -4(R4)
+	JMP	l3
+
+/*
+ * turn R3 into end pointer-3
+ * store 4 at a time while theres room
+ */
+l4:
+	ADDVU	$-3,R6, R3
+l5:
+	SGTU	R3,R4, R1
+	BEQ	R1, out
+	MOVW	R5, 0(R4)
+	ADDVU	$4, R4
+	JMP	l5
+
+/*
+ * last loop, store byte at a time
+ */
+out:
+	SGTU	R6,R4 ,R1
+	BEQ	R1, ret
+	MOVB	R5, 0(R4)
+	ADDVU	$1, R4
+	JMP	out
+
+ret:
+	MOVV	s1+0(FP), R1
+	RET
+	END

+ 40 - 0
sys/src/libc/spim64/mkfile

@@ -0,0 +1,40 @@
+objtype=spim64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libc.a
+SFILES=\
+	argv0.s\
+	atom.s\
+	c_fcr0.s\
+	getcallerpc.s\
+	getfcr.s\
+	main9.s\
+	main9p.s\
+	memccpy.s\
+	memchr.s\
+#	memcmp.s\
+	memmove.s\
+	memset.s\
+	setjmp.s\
+	strchr.s\
+	strcmp.s\
+	strcpy.s\
+	tas.s\
+
+CFILES=\
+	_nsec.c\
+	_seek.c\
+	cycles.c\
+	notejmp.c\
+	sqrt.c\
+
+HFILES=/sys/include/libc.h
+
+OFILES=${CFILES:%.c=%.$O} ${SFILES:%.s=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$CFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

+ 16 - 0
sys/src/libc/spim64/notejmp.c

@@ -0,0 +1,16 @@
+#include <u.h>
+#include <libc.h>
+#include <ureg.h>
+
+void
+notejmp(void *vr, jmp_buf j, int ret)
+{
+	struct Ureg *r = vr;
+
+	r->r1 = ret;
+	if(ret == 0)
+		r->r1 = 1;
+	r->pc = j[JMPBUFPC];
+	r->sp = j[JMPBUFSP];
+	noted(NCONT);
+}

+ 14 - 0
sys/src/libc/spim64/setjmp.s

@@ -0,0 +1,14 @@
+TEXT	setjmp(SB), 1, $-8
+	MOVV	R29, (R1)
+	MOVV	R31, 8(R1)
+	MOVV	$0, R1
+	RET
+
+TEXT	longjmp(SB), 1, $-8
+	MOVW	r+8(FP), R3
+	BNE	R3, ok		/* ansi: "longjmp(0) => longjmp(1)" */
+	MOVW	$1, R3		/* bless their pointed heads */
+ok:	MOVV	(R1), R29
+	MOVV	8(R1), R31
+	MOVV	R3, R1
+	RET

+ 103 - 0
sys/src/libc/spim64/sqrt.c

@@ -0,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+
+static	long	sqtab[64] =
+{
+	0x6cdb2, 0x726d4, 0x77ea3, 0x7d52f, 0x82a85, 0x87eb1, 0x8d1c0, 0x923bd,
+	0x974b2, 0x9c4a8, 0xa13a9, 0xa61be, 0xaaeee, 0xafb41, 0xb46bf, 0xb916e,
+	0xbdb55, 0xc247a, 0xc6ce3, 0xcb495, 0xcfb95, 0xd41ea, 0xd8796, 0xdcca0,
+	0xe110c, 0xe54dd, 0xe9818, 0xedac0, 0xf1cd9, 0xf5e67, 0xf9f6e, 0xfdfef,
+	0x01fe0, 0x05ee6, 0x09cfd, 0x0da30, 0x11687, 0x1520c, 0x18cc8, 0x1c6c1,
+	0x20000, 0x2388a, 0x27068, 0x2a79e, 0x2de32, 0x3142b, 0x3498c, 0x37e5b,
+	0x3b29d, 0x3e655, 0x41989, 0x44c3b, 0x47e70, 0x4b02b, 0x4e16f, 0x51241,
+	0x542a2, 0x57296, 0x5a220, 0x5d142, 0x60000, 0x62e5a, 0x65c55, 0x689f2,
+};
+
+double
+sqrt(double arg)
+{
+	int e, ms;
+	double a, t;
+	union
+	{
+		double	d;
+		struct
+		{
+			long	ls;
+			long	ms;
+		};
+	} u;
+
+	u.d = arg;
+	ms = u.ms;
+
+	/*
+	 * sign extend the mantissa with
+	 * exponent. result should be > 0 for
+	 * normal case.
+	 */
+	e = ms >> 20;
+	if(e <= 0) {
+		if(e == 0)
+			return 0;
+		return NaN();
+	}
+
+	/*
+	 * pick up arg/4 by adjusting exponent
+	 */
+	u.ms = ms - (2 << 20);
+	a = u.d;
+
+	/*
+	 * use 5 bits of mantissa and 1 bit
+	 * of exponent to form table index.
+	 * insert exponent/2 - 1.
+	 */
+	e = (((e - 1023) >> 1) + 1022) << 20;
+	u.ms = *(long*)((char*)sqtab + ((ms >> 13) & 0xfc)) | e;
+	u.ls = 0;
+
+	/*
+	 * three laps of newton
+	 */
+	e = 1 << 20;
+	t = u.d;
+	u.d = t + a/t;
+	u.ms -= e;		/* u.d /= 2; */
+	t = u.d;
+	u.d = t + a/t;
+	u.ms -= e;		/* u.d /= 2; */
+	t = u.d;
+
+	return t + a/t;
+}
+
+/*
+ * this is the program that generated the table.
+ * it calls sqrt by some other means.
+ *
+ * void
+ * main(void)
+ * {
+ * 	int i;
+ * 	union	U
+ * 	{
+ * 		double	d;
+ * 		struct
+ * 		{
+ * 			long	ls;
+ * 			long	ms;
+ * 		};
+ * 	} u;
+ *
+ * 	for(i=0; i<64; i++) {
+ * 		u.ms = (i<<15) | 0x3fe04000;
+ * 		u.ls = 0;
+ * 		u.d = sqrt(u.d);
+ * 		print(" 0x%.5lux,", u.ms & 0xfffff);
+ * 	}
+ * 	print("\n");
+ * 	exits(0);
+ * }
+ */

+ 63 - 0
sys/src/libc/spim64/strchr.s

@@ -0,0 +1,63 @@
+	TEXT	strchr(SB), $0
+MOVV R1, 0(FP)
+	MOVB	c+8(FP), R4
+	MOVV	s+0(FP), R3
+
+	BEQ	R4, l2
+
+/*
+ * char is not null
+ */
+l1:
+	MOVB	(R3), R1
+	ADDVU	$1, R3
+	BEQ	R1, ret
+	BNE	R1,R4, l1
+	JMP	rm1
+
+/*
+ * char is null
+ * align to word
+ */
+l2:
+	AND	$3,R3, R1
+	BEQ	R1, l3
+	MOVB	(R3), R1
+	ADDVU	$1, R3
+	BNE	R1, l2
+	JMP	rm1
+
+l3:
+	MOVW	$0xff000000, R6
+	MOVW	$0x00ff0000, R7
+
+l4:
+	MOVW	(R3), R5
+	ADDVU	$4, R3
+	AND	$0xff,R5, R1	/* byte 0 */
+	AND	$0xff00,R5, R2	/* byte 1 */
+	BEQ	R1, b0
+	AND	R7,R5, R1	/* byte 2 */
+	BEQ	R2, b1
+	AND	R6,R5, R2	/* byte 3 */
+	BEQ	R1, b2
+	BNE	R2, l4
+
+rm1:
+	ADDVU	$-1,R3, R1
+	JMP	ret
+
+b2:
+	ADDVU	$-2,R3, R1
+	JMP	ret
+
+b1:
+	ADDVU	$-3,R3, R1
+	JMP	ret
+
+b0:
+	ADDVU	$-4,R3, R1
+	JMP	ret
+
+ret:
+	RET

+ 21 - 0
sys/src/libc/spim64/strcmp.s

@@ -0,0 +1,21 @@
+TEXT	strcmp(SB), $0
+
+	MOVV	s2+8(FP), R2
+
+l1:
+	MOVB	(R2), R3
+	MOVB	(R1), R4
+	ADDVU	$1, R1
+	BEQ	R3, end
+	ADDVU	$1, R2
+	BEQ	R3, R4, l1
+
+	SGTU	R4, R3, R1
+	BNE	R1, ret
+	MOVW	$-1, R1
+	RET
+
+end:
+	SGTU	R4, R3, R1
+ret:
+	RET

+ 92 - 0
sys/src/libc/spim64/strcpy.s

@@ -0,0 +1,92 @@
+TEXT	strcpy(SB), $0
+
+	MOVV	s2+8(FP),R2		/* R2 is from pointer */
+	MOVV	R1, R3			/* R3 is to pointer */
+
+/*
+ * align 'from' pointer
+ */
+l1:
+	AND	$3, R2, R5
+	ADDVU	$1, R2
+	BEQ	R5, l2
+	MOVB	-1(R2), R5
+	ADDVU	$1, R3
+	MOVB	R5, -1(R3)
+	BNE	R5, l1
+	RET
+
+/*
+ * test if 'to' is also alligned
+ */
+l2:
+	AND	$3,R3, R5
+	BEQ	R5, l4
+
+/*
+ * copy 4 at a time, 'to' not aligned
+ */
+l3:
+	MOVW	-1(R2), R4
+	ADDVU	$4, R2
+	ADDVU	$4, R3
+	AND	$0xff,R4, R5
+	MOVB	R5, -4(R3)
+	BEQ	R5, out
+
+	SRL	$8,R4, R5
+	AND	$0xff, R5
+	MOVB	R5, -3(R3)
+	BEQ	R5, out
+
+	SRL	$16,R4, R5
+	AND	$0xff, R5
+	MOVB	R5, -2(R3)
+	BEQ	R5, out
+
+	SRL	$24,R4, R5
+	MOVB	R5, -1(R3)
+	BNE	R5, l3
+
+out:
+	RET
+
+/*
+ * word at a time both aligned
+ */
+l4:
+	MOVW	$0xff000000, R7
+	MOVW	$0x00ff0000, R8
+
+l5:
+	ADDVU	$4, R3
+	MOVW	-1(R2), R4	/* fetch */
+
+	ADDVU	$4, R2
+	AND	$0xff,R4, R5	/* is it byte 0 */
+	AND	$0xff00,R4, R6	/* is it byte 1 */
+	BEQ	R5, b0
+
+	AND	R8,R4, R5	/* is it byte 2 */
+	BEQ	R6, b1
+
+	AND	R7,R4, R6	/* is it byte 3 */
+	BEQ	R5, b2
+
+	MOVW	R4, -4(R3)	/* store */
+	BNE	R6, l5
+	JMP	out
+
+b0:
+	MOVB	$0, -4(R3)
+	JMP	out
+
+b1:
+	MOVB	R4, -4(R3)
+	MOVB	$0, -3(R3)
+	JMP	out
+
+b2:
+	MOVH	R4, -4(R3)
+	MOVB	$0, -2(R3)
+	JMP	out

+ 19 - 0
sys/src/libc/spim64/tas.s

@@ -0,0 +1,19 @@
+/*
+ *	mips user level lock code
+ */
+
+#define	LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define	SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define	NOOP		WORD	$0x27
+
+	TEXT	_tas(SB), $0
+	TEXT	C_4ktas(SB), $0
+	MOVV	R1, R2		/* address of key */
+tas1:
+	MOVW	$1, R3
+	LL(2, 1)
+	NOOP
+	SC(2, 3)
+	NOOP
+	BEQ	R3, tas1
+	RET

+ 118 - 0
sys/src/libmach/4.c

@@ -0,0 +1,118 @@
+/*
+ * mips64 definition
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "/mips64/include/ureg.h"
+#include <mach.h>
+
+#define	REGOFF(x)	(ulong)(&((struct Ureg *) 0)->x)
+
+#define SP		REGOFF(sp)
+#define PC		REGOFF(pc)
+#define	R1		REGOFF(r1)
+#define	R31		REGOFF(r31)
+#define	FP_REG(x)	(R1+8+4*(x))
+
+#define	REGSIZE		sizeof(struct Ureg)
+#define	FPREGSIZE	(4*33)
+
+Reglist mips64reglist[] = {
+	{"STATUS",	REGOFF(status),		RINT|RRDONLY, 'X'},
+	{"CAUSE",	REGOFF(cause),		RINT|RRDONLY, 'X'},
+	{"BADVADDR",	REGOFF(badvaddr),	RINT|RRDONLY, 'Y'},
+	{"TLBVIRT",	REGOFF(tlbvirt),	RINT|RRDONLY, 'Y'},
+	{"HI",		REGOFF(hi),		RINT|RRDONLY, 'Y'},
+	{"LO",		REGOFF(lo),		RINT|RRDONLY, 'Y'},
+	{"PC",		PC,		RINT, 'Y'},
+	{"SP",		SP,		RINT, 'Y'},
+	{"R31",		R31,		RINT, 'Y'},
+	{"R30",		REGOFF(r30),	RINT, 'Y'},
+	{"R28",		REGOFF(r28),	RINT, 'Y'},
+	{"R27",		REGOFF(r27),	RINT, 'Y'},
+	{"R26",		REGOFF(r26),	RINT, 'Y'},
+	{"R25",		REGOFF(r25),	RINT, 'Y'},
+	{"R24",		REGOFF(r24),	RINT, 'Y'},
+	{"R23",		REGOFF(r23),	RINT, 'Y'},
+	{"R22",		REGOFF(r22),	RINT, 'Y'},
+	{"R21",		REGOFF(r21),	RINT, 'Y'},
+	{"R20",		REGOFF(r20),	RINT, 'Y'},
+	{"R19",		REGOFF(r19),	RINT, 'Y'},
+	{"R18",		REGOFF(r18),	RINT, 'Y'},
+	{"R17",		REGOFF(r17),	RINT, 'Y'},
+	{"R16",		REGOFF(r16),	RINT, 'Y'},
+	{"R15",		REGOFF(r15),	RINT, 'Y'},
+	{"R14",		REGOFF(r14),	RINT, 'Y'},
+	{"R13",		REGOFF(r13),	RINT, 'Y'},
+	{"R12",		REGOFF(r12),	RINT, 'Y'},
+	{"R11",		REGOFF(r11),	RINT, 'Y'},
+	{"R10",		REGOFF(r10),	RINT, 'Y'},
+	{"R9",		REGOFF(r9),	RINT, 'Y'},
+	{"R8",		REGOFF(r8),	RINT, 'Y'},
+	{"R7",		REGOFF(r7),	RINT, 'Y'},
+	{"R6",		REGOFF(r6),	RINT, 'Y'},
+	{"R5",		REGOFF(r5),	RINT, 'Y'},
+	{"R4",		REGOFF(r4),	RINT, 'Y'},
+	{"R3",		REGOFF(r3),	RINT, 'Y'},
+	{"R2",		REGOFF(r2),	RINT, 'Y'},
+	{"R1",		REGOFF(r1),	RINT, 'Y'},
+	{"F0",		FP_REG(0),	RFLT, 'F'},
+	{"F1",		FP_REG(1),	RFLT, 'f'},
+	{"F2",		FP_REG(2),	RFLT, 'F'},
+	{"F3",		FP_REG(3),	RFLT, 'f'},
+	{"F4",		FP_REG(4),	RFLT, 'F'},
+	{"F5",		FP_REG(5),	RFLT, 'f'},
+	{"F6",		FP_REG(6),	RFLT, 'F'},
+	{"F7",		FP_REG(7),	RFLT, 'f'},
+	{"F8",		FP_REG(8),	RFLT, 'F'},
+	{"F9",		FP_REG(9),	RFLT, 'f'},
+	{"F10",		FP_REG(10),	RFLT, 'F'},
+	{"F11",		FP_REG(11),	RFLT, 'f'},
+	{"F12",		FP_REG(12),	RFLT, 'F'},
+	{"F13",		FP_REG(13),	RFLT, 'f'},
+	{"F14",		FP_REG(14),	RFLT, 'F'},
+	{"F15",		FP_REG(15),	RFLT, 'f'},
+	{"F16",		FP_REG(16),	RFLT, 'F'},
+	{"F17",		FP_REG(17),	RFLT, 'f'},
+	{"F18",		FP_REG(18),	RFLT, 'F'},
+	{"F19",		FP_REG(19),	RFLT, 'f'},
+	{"F20",		FP_REG(20),	RFLT, 'F'},
+	{"F21",		FP_REG(21),	RFLT, 'f'},
+	{"F22",		FP_REG(22),	RFLT, 'F'},
+	{"F23",		FP_REG(23),	RFLT, 'f'},
+	{"F24",		FP_REG(24),	RFLT, 'F'},
+	{"F25",		FP_REG(25),	RFLT, 'f'},
+	{"F26",		FP_REG(26),	RFLT, 'F'},
+	{"F27",		FP_REG(27),	RFLT, 'f'},
+	{"F28",		FP_REG(28),	RFLT, 'F'},
+	{"F29",		FP_REG(29),	RFLT, 'f'},
+	{"F30",		FP_REG(30),	RFLT, 'F'},
+	{"F31",		FP_REG(31),	RFLT, 'f'},
+	{"FPCR",	FP_REG(32),	RFLT, 'X'},
+	{  0 }
+};
+
+	/* the machine description */
+Mach mmips64 =
+{
+	"mips64",
+	MMIPS2,		/* machine type */
+	mips64reglist,	/* register set */
+	REGSIZE,	/* number of bytes in reg set */
+	FPREGSIZE,	/* number of bytes in fp reg set */
+	"PC",		/* name of PC */
+	"SP",		/* name of SP */
+	"R31",		/* name of link register */
+	"setR30",	/* static base register name */
+	0,		/* value */
+	16*1024,	/* page size */
+	0xFFFFFFFF80000000ULL,	/* kernel base */
+	0xFFFFFFFF80000000ULL,	/* kernel text mask */
+	0x7FFFFFFFULL,	/* user stack top */
+	4,		/* quantization of pc */
+	8,		/* szaddr */
+	8,		/* szreg */
+	4,		/* szfloat */
+	8,		/* szdouble */
+};

+ 202 - 0
sys/src/libmach/4c/4.out.h

@@ -0,0 +1,202 @@
+#define	NSNAME	8
+#define	NSYM	50
+#define	NREG	32
+
+#define NOPROF	(1<<0)
+#define DUPOK	(1<<1)
+
+#define	REGZERO		0
+#define	REGRET		1
+#define	REGARG		1
+/* compiler allocates R1 up as temps */
+/* compiler allocates register variables R3-R23 */
+#define	REGEXT		25
+/* compiler allocates external registers R25 down */
+/* dont use R26 R27 */
+#define	REGTMP		28
+#define	REGSP		29
+#define	REGSB		30
+#define	REGLINK		31
+
+#define	FREGRET		0
+/* compiler allocates register variables F4-F22 */
+/* compiler allocates external registers F22 down */
+#define	FREGEXT		22
+#define	FREGZERO	24	/* both float and double */
+#define	FREGHALF	26	/* double */
+#define	FREGONE		28	/* double */
+#define	FREGTWO		30	/* double */
+
+enum	as
+{
+	AXXX,
+
+	AABSD,
+	AABSF,
+	AABSW,
+	AADD,
+	AADDD,
+	AADDF,
+	AADDU,
+	AADDW,
+	AAND,
+	ABEQ,
+	ABFPF,
+	ABFPT,
+	ABGEZ,
+	ABGEZAL,
+	ABGTZ,
+	ABLEZ,
+	ABLTZ,
+	ABLTZAL,
+	ABNE,
+	ABREAK,
+	ACMPEQD,
+	ACMPEQF,
+	ACMPGED,
+	ACMPGEF,
+	ACMPGTD,
+	ACMPGTF,
+	ADATA,
+	ADIV,
+	ADIVD,
+	ADIVF,
+	ADIVU,
+	ADIVW,
+	AGLOBL,
+	AGOK,
+	AHISTORY,
+	AJAL,
+	AJMP,
+	AMOVB,
+	AMOVBU,
+	AMOVD,
+	AMOVDF,
+	AMOVDW,
+	AMOVF,
+	AMOVFD,
+	AMOVFW,
+	AMOVH,
+	AMOVHU,
+	AMOVW,
+	AMOVWD,
+	AMOVWF,
+	AMOVWL,
+	AMOVWR,
+	AMUL,
+	AMULD,
+	AMULF,
+	AMULU,
+	AMULW,
+	ANAME32,
+	ANAME,
+	ANEGD,
+	ANEGF,
+	ANEGW,
+	ANOP,
+	ANOR,
+	AOR,
+	AREM,
+	AREMU,
+	ARET,
+	ARFE,
+	ASGT,
+	ASGTU,
+	ASLL,
+	ASRA,
+	ASRL,
+	ASUB,
+	ASUBD,
+	ASUBF,
+	ASUBU,
+	ASUBW,
+	ASYSCALL,
+	ATEXT,
+	ATLBP,
+	ATLBR,
+	ATLBWI,
+	ATLBWR,
+	AWORD,
+	AXOR,
+
+	AEND,
+
+	AMOVV,
+	AMOVVL,
+	AMOVVR,
+	ASLLV,
+	ASRAV,
+	ASRLV,
+	ADIVV,
+	ADIVVU,
+	AREMV,
+	AREMVU,
+	AMULV,
+	AMULVU,
+	AADDV,
+	AADDVU,
+	ASUBV,
+	ASUBVU,
+
+	ADYNT,
+	AINIT,
+
+	ABCASE,
+	ACASE,
+
+	ATRUNCFV,
+	ATRUNCDV,
+	ATRUNCFW,
+	ATRUNCDW,
+	AMOVWU,
+	AMOVFV,
+	AMOVDV,
+	AMOVVF,
+	AMOVVD,
+
+	ASIGNAME,
+
+	ALAST,
+};
+
+/* type/name */
+#define	D_GOK	0
+#define	D_NONE	1
+
+/* type */
+#define	D_BRANCH (D_NONE+1)
+#define	D_OREG	(D_NONE+2)
+#define	D_EXTERN (D_NONE+3)	/* name */
+#define	D_STATIC (D_NONE+4)	/* name */
+#define	D_AUTO	(D_NONE+5)	/* name */
+#define	D_PARAM	(D_NONE+6)	/* name */
+#define	D_CONST	(D_NONE+7)
+#define	D_FCONST (D_NONE+8)
+#define	D_SCONST (D_NONE+9)
+#define	D_HI	(D_NONE+10)
+#define	D_LO	(D_NONE+11)
+#define	D_REG	(D_NONE+12)
+#define	D_FREG	(D_NONE+13)
+#define	D_FCREG	(D_NONE+14)
+#define	D_MREG	(D_NONE+15)
+#define	D_FILE	(D_NONE+16)
+#define	D_OCONST (D_NONE+17)
+#define	D_FILE1	(D_NONE+18)
+#define	D_VCONST (D_NONE+19)
+
+/*
+ * this is the ranlib header
+ */
+#define	SYMDEF	"__.SYMDEF"
+
+/*
+ * this is the simulated IEEE floating point
+ */
+typedef	struct	ieee	Ieee;
+struct	ieee
+{
+	long	l;	/* contains ls-man	0xffffffff */
+	long	h;	/* contains sign	0x80000000
+				    exp		0x7ff00000
+				    ms-man	0x000fffff */
+};

+ 145 - 0
sys/src/libmach/4obj.c

@@ -0,0 +1,145 @@
+/*
+ * 4obj.c - identify and parse a mips object file
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+#include "4c/4.out.h"
+#include "obj.h"
+
+typedef struct Addr	Addr;
+struct Addr
+{
+	char	type;
+	char	sym;
+	char	name;
+};
+static Addr addr(Biobuf*);
+static char type2char(int);
+static void skip(Biobuf*, int);
+
+int
+_is4(char *s)
+{
+	return  s[0] == ANAME				/* ANAME */
+		&& s[1] == D_FILE			/* type */
+		&& s[2] == 1				/* sym */
+		&& s[3] == '<';				/* name of file */
+}
+
+int
+_read4(Biobuf *bp, Prog *p)
+{
+	int as, n;
+	Addr a;
+
+	as = Bgetc(bp);			/* as */
+	if(as < 0)
+		return 0;
+	p->kind = aNone;
+	p->sig = 0;
+	if(as == ANAME || as == ASIGNAME){
+		if(as == ASIGNAME){
+			Bread(bp, &p->sig, 4);
+			p->sig = leswal(p->sig);
+		}
+		p->kind = aName;
+		p->type = type2char(Bgetc(bp));		/* type */
+		p->sym = Bgetc(bp);			/* sym */
+		n = 0;
+		for(;;) {
+			as = Bgetc(bp);
+			if(as < 0)
+				return 0;
+			n++;
+			if(as == 0)
+				break;
+		}
+		p->id = malloc(n);
+		if(p->id == 0)
+			return 0;
+		Bseek(bp, -n, 1);
+		if(Bread(bp, p->id, n) != n)
+			return 0;
+		return 1;
+	}
+	if(as == ATEXT)
+		p->kind = aText;
+	else if(as == AGLOBL)
+		p->kind = aData;
+	skip(bp, 5);		/* reg(1), lineno(4) */
+	a = addr(bp);
+	addr(bp);
+	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
+		p->kind = aNone;
+	p->sym = a.sym;
+	return 1;
+}
+
+static Addr
+addr(Biobuf *bp)
+{
+	Addr a;
+	vlong off;
+	long l;
+
+	a.type = Bgetc(bp);	/* a.type */
+	skip(bp,1);		/* reg */
+	a.sym = Bgetc(bp);	/* sym index */
+	a.name = Bgetc(bp);	/* sym type */
+	switch(a.type){
+	default:
+	case D_NONE: case D_REG: case D_FREG: case D_MREG:
+	case D_FCREG: case D_LO: case D_HI:
+		break;
+	case D_OREG:
+	case D_CONST:
+	case D_BRANCH:
+	case D_VCONST:
+		l = Bgetc(bp);
+		l |= Bgetc(bp) << 8;
+		l |= Bgetc(bp) << 16;
+		l |= Bgetc(bp) << 24;
+		off = l;
+		if(a.type == D_VCONST){
+			l = Bgetc(bp);
+			l |= Bgetc(bp) << 8;
+			l |= Bgetc(bp) << 16;
+			l |= Bgetc(bp) << 24;
+			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
+			a.type = D_CONST;		/* perhaps */
+		}
+		if(off < 0)
+			off = -off;
+		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
+			_offset(a.sym, off);
+		break;
+	case D_SCONST:
+		skip(bp, NSNAME);
+		break;
+	case D_FCONST:
+		skip(bp, 8);
+		break;
+	}
+	return a;
+}
+
+static char
+type2char(int t)
+{
+	switch(t){
+	case D_EXTERN:		return 'U';
+	case D_STATIC:		return 'b';
+	case D_AUTO:		return 'a';
+	case D_PARAM:		return 'p';
+	default:		return UNKNOWN;
+	}
+}
+
+static void
+skip(Biobuf *bp, int n)
+{
+	while (n-- > 0)
+		Bgetc(bp);
+}

+ 12 - 11
sys/src/libmach/executable.c

@@ -58,8 +58,9 @@ typedef struct Exectable{
 } ExecTable;
 
 extern	Mach	mmips;
-extern	Mach	mmips2le;
-extern	Mach	mmips2be;
+//extern	Mach	mmips2le;
+//extern	Mach	mmips2be;
+extern	Mach	mmips64;
 extern	Mach	msparc;
 extern	Mach	msparc64;
 extern	Mach	m68020;
@@ -90,21 +91,21 @@ ExecTable exectab[] =
 		sizeof(Exec),
 		beswal,
 		adotout },
-	{ M_MAGIC,			/* Mips 4.out */
-		"mips 4k plan 9 executable BE",
-		"mips 4k plan 9 dlm BE",
+	{ M_MAGIC,			/* Mips64 4.out */
+		"mips64 plan 9 executable BE",
+		"mips64 plan 9 dlm BE",
 		FMIPS2BE,
 		1,
-		&mmips2be,
+		&mmips64,
 		sizeof(Exec),
 		beswal,
 		adotout },
-	{ N_MAGIC,			/* Mips 0.out */
-		"mips 4k plan 9 executable LE",
-		"mips 4k plan 9 dlm LE",
+	{ N_MAGIC,			/* Mips64 x.out */
+		"mips64 plan 9 executable LE",
+		"mips64 plan 9 dlm LE",
 		FMIPS2LE,
 		1,
-		&mmips2le,
+		&mmips64,
 		sizeof(Exec),
 		beswal,
 		adotout },
@@ -122,7 +123,7 @@ ExecTable exectab[] =
 		nil,
 		FMIPSB,
 		0,
-		&mmips2be,
+		&mmips64,
 		sizeof(struct mips4kexec),
 		beswal,
 		mips4kboot },

+ 4 - 1
sys/src/libmach/mkfile

@@ -14,7 +14,8 @@ FILES=\
 	k\
 	sparc64\
 	q\
-	0\
+#	0\
+	4\
 	68020\
 	5\
 	6\
@@ -39,6 +40,7 @@ FILES=\
 	8obj\
 	9obj\
 	qobj\
+	4obj\
 	vcodas\
 
 HFILES=/sys/include/mach.h elf.h obj.h
@@ -57,6 +59,7 @@ UPDATE=mkfile\
 CFLAGS=$CFLAGS -I/sys/src/cmd
 
 68020obj.$O: 68020/2.out.h
+4obj.$O: 4c/4.out.h
 5obj.$O: /sys/src/cmd/5c/5.out.h
 6obj.$O: /sys/src/cmd/6c/6.out.h
 alphaobj.$O: alpha/7.out.h

+ 3 - 0
sys/src/libmach/obj.c

@@ -21,6 +21,7 @@ enum
 };
 
 int	_is2(char*),		/* in [$OS].c */
+	_is4(char*),
 	_is5(char*),
 	_is6(char*),
 	_is7(char*),
@@ -31,6 +32,7 @@ int	_is2(char*),		/* in [$OS].c */
 	_isv(char*),
 	_isu(char*),
 	_read2(Biobuf*, Prog*),
+	_read4(Biobuf*, Prog*),
 	_read5(Biobuf*, Prog*),
 	_read6(Biobuf*, Prog*),
 	_read7(Biobuf*, Prog*),
@@ -63,6 +65,7 @@ static Obj	obj[] =
 	[ObjMips]	"mips .v",	_isv, _readv,
 	[ObjSparc64]	"sparc64 .u",	_isu, _readu,
 	[ObjPower64]	"power64 .9",	_is9, _read9,
+	[ObjMips2]	"mips64 .4",	_is4, _read4,
 	[Maxobjtype]	0, 0
 };
 

+ 6 - 6
sys/src/libmach/setmach.c

@@ -16,8 +16,8 @@ struct machtab
 	Machdata	*machdata;		/* machine functions */
 };
 
-extern	Mach		mmips, msparc, m68020, mi386, mamd64,
-			marm, mmips2be, mmips2le, mpower, mpower64, malpha, msparc64;
+extern	Mach		mmips, mmips64, msparc, m68020, mi386, mamd64,
+			marm, /* mmips2be, mmips2le, */ mpower, mpower64, malpha, msparc64;
 extern	Machdata	mipsmach, mipsmachle, sparcmach, m68020mach, i386mach,
 			armmach, mipsmach2le, powermach, alphamach, sparc64mach;
 
@@ -40,11 +40,11 @@ Machtab	machines[] =
 		A68020,
 		&m68020,
 		&m68020mach,	},
-	{	"mips2LE",			/*plan 9 mips2 little endian*/
+	{	"mips64LE",			/*plan 9 mips64 little endian*/
 		FMIPS2LE,
 		0,
 		AMIPS,
-		&mmips2le,
+		&mmips64,
 		&mipsmach2le, 	},
 	{	"mipsLE",				/*plan 9 mips little endian*/
 		FMIPSLE,
@@ -58,11 +58,11 @@ Machtab	machines[] =
 		AMIPS,
 		&mmips,
 		&mipsmach, 	},
-	{	"mips2",			/*plan 9 mips2*/
+	{	"mips64",			/*plan 9 mips64*/
 		FMIPS2BE,
 		FMIPSB,
 		AMIPS,
-		&mmips2be,
+		&mmips64,
 		&mipsmach, 	},		/* shares debuggers with native mips */
 	{	"mipsco",			/*native mips - must follow plan 9*/
 		FMIPS,

+ 25 - 25
sys/src/libmach/vdb.c

@@ -541,8 +541,8 @@ static Opcode opcodes[64] = {
 	"BNEL",	   branch,	0,
 	"BLEZL",   branch,	0,
 	"BGTZL",   branch,	0,
-	"instr18",	0,	mipscoxxx,
-	"instr19",	0,	mipscoxxx,
+	"ADDV",		 addi,	mipsalui,
+	"ADDVU",	 addi,	mipsalui,
 	"MOVVL",     load,	mipsload,
 	"MOVVR",     load,	mipsload,
 	"instr1C",	0,	mipscoxxx,
@@ -551,25 +551,25 @@ static Opcode opcodes[64] = {
 	"instr1F",	0,	mipscoxxx,
 	"MOVB",	     load,	mipsload,
 	"MOVH",	     load,	mipsload,
-	"lwl",		0,	mipscoload,
+	"MOVWL",	 load,	mipsload,
 	"MOVW",	     load,	mipsload,
 	"MOVBU",     load,	mipsload,
 	"MOVHU",     load,	mipsload,
-	"lwr",		0,	mipscoload,
-	"instr27",	0,	mipscoxxx,
+	"MOVWR",	 load,	mipsload,
+	"lwu",		0,	mipscoload,
 	"MOVB",	    store,	mipsstore,
 	"MOVH",	    store,	mipsstore,
-	"swl",		0,	mipscoload,
+	"MOVWL",	store,	mipsstore,
 	"MOVW",	    store,	mipsstore,
 	"MOVVL",    store,	mipsstore,
 	"MOVVR",    store,	mipsstore,
-	"swr",		0,	mipscoload,
+	"MOVWR",	store,	mipsstore,
 	"CACHE",	0,	"%C,%l",
 	"ll",		0,	mipscoload,
 	"MOVW",	     lwc1,	mipscoload,
 	"lwc2",		0,	mipscoload,
 	"lwc3",		0,	mipscoload,
-	"instr34",	0,	mipscoxxx,
+	"lld",		0,	mipscoload,
 	"ldc1",		0,	mipscoload,
 	"ldc2",		0,	mipscoload,
 	"MOVV",	    load,	mipsload,
@@ -577,7 +577,7 @@ static Opcode opcodes[64] = {
 	"swc1",	     swc1,	mipscoload,
 	"swc2",		0,	mipscoload,
 	"swc3",		0,	mipscoload,
-	"instr3C",	0,	mipscoxxx,
+	"scd",		0,	mipscoload,
 	"sdc1",		0,	mipscoload,
 	"sdc2",		0,	mipscoload,
 	"MOVV",	    store,	mipsstore,
@@ -612,10 +612,10 @@ static Opcode sopcodes[64] = {
 	"MULU",		0,	mipsrtrs,
 	"DIV",		0,	mipsrtrs,
 	"DIVU",		0,	mipsrtrs,
-	"special1C",	0,	mipscoxxx,
-	"special1D",	0,	mipscoxxx,
-	"DDIV",		0,	"R%s,R%t",
-	"special1F",	0,	mipscoxxx,
+	"MULV",		0,	mipsrtrs,
+	"MULVU",	0,	mipsrtrs,
+	"DIVV",		0,	mipsrtrs,
+	"DIVVU",	0,	mipsrtrs,
 	"ADD",	      add,	mipsalu3op,
 	"ADDU",	      add,	mipsalu3op,
 	"SUB",	      sub,	mipsalu3op,
@@ -628,10 +628,10 @@ static Opcode sopcodes[64] = {
 	"special29",	0,	mipscoxxx,
 	"SGT",		0,	mipsalu3op,
 	"SGTU",		0,	mipsalu3op,
-	"special2C",	0,	mipscoxxx,
-	"special2D",	0,	mipscoxxx,
-	"special2E",	0,	mipscoxxx,
-	"DSUBU",	0,	"R%s,R%t,R%d",
+	"ADDV",		  add,	mipsalu3op,
+	"ADDVU",	  add,	mipsalu3op,
+	"SUBV",		  sub,	mipsalu3op,
+	"SUBVU",	  sub,	mipsalu3op,
 	"tge",		0,	mipscorsrt,
 	"tgeu",		0,	mipscorsrt,
 	"tlt",		0,	mipscorsrt,
@@ -694,14 +694,14 @@ static Opcode fopcodes[64] = {
 	"ABS%f",	0,	mipsfp2,
 	"MOV%f",	0,	mipsfp2,
 	"NEG%f",	0,	mipsfp2,
-	"finstr08",	0,	mipscoxxx,
-	"finstr09",	0,	mipscoxxx,
-	"finstr0A",	0,	mipscoxxx,
-	"finstr0B",	0,	mipscoxxx,
+	"round.l.%f",	0,	mipscofp2,
+	"trunc.l.%f",	0,	mipscofp2,
+	"ceil.l.%f",	0,	mipscofp2,
+	"floor.l.%f",	0,	mipscofp2,
 	"round.w.%f",	0,	mipscofp2,
-	"trunc.w%f",	0,	mipscofp2,
-	"ceil.w%f",	0,	mipscofp2,
-	"floor.w%f",	0,	mipscofp2,
+	"trunc.w.%f",	0,	mipscofp2,
+	"ceil.w.%f",	0,	mipscofp2,
+	"floor.w.%f",	0,	mipscofp2,
 	"finstr10",	0,	mipscoxxx,
 	"finstr11",	0,	mipscoxxx,
 	"finstr12",	0,	mipscoxxx,
@@ -723,7 +723,7 @@ static Opcode fopcodes[64] = {
 	"cvt.e.%f",	0,	mipscofp2,
 	"cvt.q.%f",	0,	mipscofp2,
 	"cvt.w.%f",	0,	mipscofp2,
-	"finstr25",	0,	mipscoxxx,
+	"cvt.l.%f",	0,	mipscofp2,
 	"finstr26",	0,	mipscoxxx,
 	"finstr27",	0,	mipscoxxx,
 	"finstr28",	0,	mipscoxxx,

+ 22 - 0
sys/src/libmp/mips64/mkfile

@@ -0,0 +1,22 @@
+objtype=mips64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libmp.a
+
+SFILES=\
+#	mpvecadd.s\
+#	mpvecsub.s\
+#	mpvecdigmuladd.s\
+#	mpvecdigmulsub.s\
+#	mpdigdiv.s\
+
+HFILES=/$objtype/include/u.h /sys/include/mp.h ../port/dat.h
+
+OFILES=\
+#	${SFILES:%.s=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

+ 22 - 0
sys/src/libmp/spim64/mkfile

@@ -0,0 +1,22 @@
+objtype=spim64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libmp.a
+
+SFILES=\
+#	mpvecadd.s\
+#	mpvecsub.s\
+#	mpvecdigmuladd.s\
+#	mpvecdigmulsub.s\
+#	mpdigdiv.s\
+
+HFILES=/$objtype/include/u.h /sys/include/mp.h ../port/dat.h
+
+OFILES=\
+#	${SFILES:%.s=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

+ 20 - 0
sys/src/libsec/mips64/mkfile

@@ -0,0 +1,20 @@
+objtype=mips64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libsec.a
+#FILES=\
+#	md5block\
+#	sha1block\
+
+HFILES=/sys/include/libsec.h
+
+SFILES=${FILES:%=%.s}
+
+OFILES= \
+#	${FILES:%=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

+ 20 - 0
sys/src/libsec/spim64/mkfile

@@ -0,0 +1,20 @@
+objtype=spim64
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libsec.a
+#FILES=\
+#	md5block\
+#	sha1block\
+
+HFILES=/sys/include/libsec.h
+
+SFILES=${FILES:%=%.s}
+
+OFILES= \
+#	${FILES:%=%.$O}
+
+UPDATE=mkfile\
+	$HFILES\
+	$SFILES\
+
+</sys/src/cmd/mksyslib

Some files were not shown because too many files changed in this diff