--- /dev/null +++ /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 */ --- /dev/null +++ /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 */ --- /dev/null +++ /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 */ --- /dev/null +++ /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 --- /dev/null +++ /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]) --- /dev/null +++ /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; +}; --- /dev/null +++ /mips64/mkfile @@ -0,0 +1,9 @@ +> 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 */ --- /dev/null +++ /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 */ --- /dev/null +++ /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 --- /dev/null +++ /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]) --- /dev/null +++ /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; +}; --- /dev/null +++ /spim64/mkfile @@ -0,0 +1,9 @@ +=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"); --- /sys/src/cmd/4a/a.h +++ /sys/src/cmd/4a/a.h @@ -1,19 +1,18 @@ #include #include #include -#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); --- /sys/src/cmd/4a/a.y +++ /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; } --- /sys/src/cmd/4a/lex.c +++ /sys/src/cmd/4a/lex.c @@ -1,7 +1,7 @@ -#include #define EXTERN #include "a.h" #include "y.tab.h" +#include 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" --- /sys/src/cmd/4a/mkfile +++ /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 --- /dev/null +++ /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 */ +}; deleted file mode 100644 --- /sys/src/cmd/4c/bits.c +++ /dev/null @@ -1,127 +0,0 @@ -#define EXTERN -#include "gc.h" - -/* -Bits -bor(Bits a, Bits b) -{ - Bits c; - int i; - - for(i=0; ib[i]) - return 1; - return 0; -} - -/* -int -beq(Bits a, Bits b) -{ - int i; - - for(i=0; iname; - if(strlen(str) + strlen(s) + 1 >= STRINGSZ) - break; - strcat(str, s); - bits.b[i/32] &= ~(1L << (i%32)); - } - strconv(str, fp); - return 0; -} --- /sys/src/cmd/4c/cgen.c +++ /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) --- /dev/null +++ /sys/src/cmd/4c/enam.c @@ -0,0 +1,123 @@ +char* anames[] = +{ + "XXX", + "ABSD", + "ABSF", + "ABSW", + "ADD", + "ADDD", + "ADDF", + "ADDU", + "ADDW", + "AND", + "BEQ", + "BFPF", + "BFPT", + "BGEZ", + "BGEZAL", + "BGTZ", + "BLEZ", + "BLTZ", + "BLTZAL", + "BNE", + "BREAK", + "CMPEQD", + "CMPEQF", + "CMPGED", + "CMPGEF", + "CMPGTD", + "CMPGTF", + "DATA", + "DIV", + "DIVD", + "DIVF", + "DIVU", + "DIVW", + "GLOBL", + "GOK", + "HISTORY", + "JAL", + "JMP", + "MOVB", + "MOVBU", + "MOVD", + "MOVDF", + "MOVDW", + "MOVF", + "MOVFD", + "MOVFW", + "MOVH", + "MOVHU", + "MOVW", + "MOVWD", + "MOVWF", + "MOVWL", + "MOVWR", + "MUL", + "MULD", + "MULF", + "MULU", + "MULW", + "NAME32", + "NAME", + "NEGD", + "NEGF", + "NEGW", + "NOP", + "NOR", + "OR", + "REM", + "REMU", + "RET", + "RFE", + "SGT", + "SGTU", + "SLL", + "SRA", + "SRL", + "SUB", + "SUBD", + "SUBF", + "SUBU", + "SUBW", + "SYSCALL", + "TEXT", + "TLBP", + "TLBR", + "TLBWI", + "TLBWR", + "WORD", + "XOR", + "END", + "MOVV", + "MOVVL", + "MOVVR", + "SLLV", + "SRAV", + "SRLV", + "DIVV", + "DIVVU", + "REMV", + "REMVU", + "MULV", + "MULVU", + "ADDV", + "ADDVU", + "SUBV", + "SUBVU", + "DYNT", + "INIT", + "BCASE", + "CASE", + "TRUNCFV", + "TRUNCDV", + "TRUNCFW", + "TRUNCDW", + "MOVWU", + "MOVFV", + "MOVDV", + "MOVVF", + "MOVVD", + "SIGNAME", + "LAST", +}; --- /sys/src/cmd/4c/gc.h +++ /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); --- /dev/null +++ /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<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, "\"\""); + 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\""); + 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= 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; ilexical = 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, ""); + 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 = ""; + 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; + } +} --- /sys/src/cmd/4c/list.c +++ /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: --- /dev/null +++ /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; +} --- /sys/src/cmd/4c/mkenam +++ /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/// --- /sys/src/cmd/4c/mkfile +++ /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}\ - 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: --- /sys/src/cmd/4c/reg.c +++ /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; zetype != et || !typechlpfd[et]) /* funny punning */ + if(v->etype != et || (!typechlpfd[et] && !typev[et])) /* funny punning */ for(z=0; z= 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]; --- /sys/src/cmd/4c/sgen.c +++ /sys/src/cmd/4c/sgen.c @@ -1,345 +1,6 @@ #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); -} --- /sys/src/cmd/4c/swt.c +++ /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; ival); + 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) { @@ -314,41 +236,20 @@ 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; efrom.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; } --- /sys/src/cmd/4c/txt.c +++ /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 && ((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); @@ -219,6 +226,13 @@ nodconst(long v) } Node* +nod32const(vlong v) +{ + constnode.vconst = v & MASK(32); + return &constnode; +} + +Node* nodfconst(double d) { fconstnode.fconst = 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; --- /sys/src/cmd/4l/asm.c +++ /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(); @@ -431,13 +463,6 @@ strnput(char *s, int n) } void -lput(long l) -{ - - LPUT(l); -} - -void cflush(void) { int n; @@ -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(; ito.ieee); cast = (char*)&fl; for(; ito.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(; ifrom.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; +} --- /sys/src/cmd/4l/compat.c +++ /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; +} deleted file mode 100644 --- /sys/src/cmd/4l/enam.c +++ /dev/null @@ -1,121 +0,0 @@ -char* anames[] = -{ - "XXX", - "ABSD", - "ABSF", - "ABSW", - "ADD", - "ADDD", - "ADDF", - "ADDU", - "ADDW", - "AND", - "BEQ", - "BFPF", - "BFPT", - "BGEZ", - "BGEZAL", - "BGTZ", - "BLEZ", - "BLTZ", - "BLTZAL", - "BNE", - "BREAK", - "CMPEQD", - "CMPEQF", - "CMPGED", - "CMPGEF", - "CMPGTD", - "CMPGTF", - "DATA", - "DIV", - "DIVD", - "DIVF", - "DIVU", - "DIVW", - "GLOBL", - "GOK", - "HISTORY", - "JAL", - "JMP", - "MOVB", - "MOVBU", - "MOVD", - "MOVDF", - "MOVDW", - "MOVF", - "MOVFD", - "MOVFW", - "MOVH", - "MOVHU", - "MOVW", - "MOVWD", - "MOVWF", - "MOVWL", - "MOVWR", - "MUL", - "MULD", - "MULF", - "MULU", - "MULW", - "NAME", - "NEGD", - "NEGF", - "NEGW", - "NOP", - "NOR", - "OR", - "REM", - "REMU", - "RET", - "RFE", - "SGT", - "SGTU", - "SLL", - "SRA", - "SRL", - "SUB", - "SUBD", - "SUBF", - "SUBU", - "SUBW", - "SYSCALL", - "TEXT", - "TLBP", - "TLBR", - "TLBWI", - "TLBWR", - "WORD", - "XOR", - "END", - "MOVV", - "MOVVL", - "MOVVR", - "SLLV", - "SRAV", - "SRLV", - "DIVV", - "DIVVU", - "REMV", - "REMVU", - "MULV", - "MULVU", - "ADDV", - "ADDVU", - "SUBV", - "SUBVU", - "DYNT", - "INIT", - "BCASE", - "CASE", - "TRUNCFV", - "TRUNCDV", - "TRUNCFW", - "TRUNCDW", - "MOVWU", - "MOVFV", - "MOVDV", - "MOVVF", - "MOVVD", - "LAST", -}; --- /sys/src/cmd/4l/l.h +++ /sys/src/cmd/4l/l.h @@ -1,12 +1,15 @@ #include #include #include -#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*); --- /sys/src/cmd/4l/list.c +++ /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; } --- /sys/src/cmd/4l/mkfile +++ /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. 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; --- /sys/src/cmd/4l/obj.c +++ /sys/src/cmd/4l/obj.c @@ -10,22 +10,36 @@ char *noname = ""; 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; ilink) + 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= 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= 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; @@ -1260,6 +1396,17 @@ doprof2(void) } 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 */ q = prg(); @@ -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++) @@ -1314,6 +1476,12 @@ nuxiinit(void) 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"); } --- /sys/src/cmd/4l/optab.c +++ /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 }, }; --- /sys/src/cmd/4l/pass.c +++ /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; --- /sys/src/cmd/4l/sched.c +++ /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++; --- /sys/src/cmd/4l/span.c +++ /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; ilink) { + 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; @@ -126,6 +180,24 @@ regoff(Adr *a) } 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) { Sym *s; @@ -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(); } --- /sys/src/libc/9syscall/mkfile +++ /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 --- /dev/null +++ /sys/src/libc/mips64/_nsec.c @@ -0,0 +1,14 @@ +#include +#include + +extern int _nsec(vlong*); + +vlong +nsec(void) +{ + vlong l; + + if(_nsec(&l) < 0) + l = -1LL; + return l; +} --- /dev/null +++ /sys/src/libc/mips64/_seek.c @@ -0,0 +1,14 @@ +#include +#include + +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; +} --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/mips64/c_fcr0.s @@ -0,0 +1,3 @@ + TEXT C_fcr0(SB), $0 + MOVW FCR0, R1 + RET --- /dev/null +++ /sys/src/libc/mips64/cycles.c @@ -0,0 +1,10 @@ +#include +#include + +#pragma profile off + +void +cycles(uvlong*u) +{ + *u = 0LL; +} --- /dev/null +++ /sys/src/libc/mips64/getcallerpc.s @@ -0,0 +1,3 @@ +TEXT getcallerpc(SB), $0 + MOVV 0(SP), R1 + RET --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/mips64/mkfile @@ -0,0 +1,40 @@ +objtype=mips64 + +#include +#include + +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); +} --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/mips64/sqrt.c @@ -0,0 +1,103 @@ +#include +#include + +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); + * } + */ --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/spim64/_nsec.c @@ -0,0 +1,14 @@ +#include +#include + +extern int _nsec(vlong*); + +vlong +nsec(void) +{ + vlong l; + + if(_nsec(&l) < 0) + l = -1LL; + return l; +} --- /dev/null +++ /sys/src/libc/spim64/_seek.c @@ -0,0 +1,14 @@ +#include +#include + +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; +} --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/spim64/c_fcr0.s @@ -0,0 +1,3 @@ + TEXT C_fcr0(SB), $0 + MOVW FCR0, R1 + RET --- /dev/null +++ /sys/src/libc/spim64/cycles.c @@ -0,0 +1,10 @@ +#include +#include + +#pragma profile off + +void +cycles(uvlong*u) +{ + *u = 0LL; +} --- /dev/null +++ /sys/src/libc/spim64/getcallerpc.s @@ -0,0 +1,3 @@ +TEXT getcallerpc(SB), $0 + MOVV 0(SP), R1 + RET --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/spim64/mkfile @@ -0,0 +1,40 @@ +objtype=spim64 + +#include +#include + +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); +} --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libc/spim64/sqrt.c @@ -0,0 +1,103 @@ +#include +#include + +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); + * } + */ --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /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 --- /dev/null +++ /sys/src/libmach/4.c @@ -0,0 +1,118 @@ +/* + * mips64 definition + */ +#include +#include +#include +#include "/mips64/include/ureg.h" +#include + +#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 */ +}; --- /dev/null +++ /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 */ +}; --- /dev/null +++ /sys/src/libmach/4obj.c @@ -0,0 +1,145 @@ +/* + * 4obj.c - identify and parse a mips object file + */ +#include +#include +#include +#include +#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); +} --- /sys/src/libmach/executable.c +++ /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 }, --- /sys/src/libmach/mkfile +++ /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 --- /sys/src/libmach/obj.c +++ /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 }; --- /sys/src/libmach/setmach.c +++ /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, --- /sys/src/libmach/vdb.c +++ /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, --- /dev/null +++ /sys/src/libmp/mips64/mkfile @@ -0,0 +1,22 @@ +objtype=mips64 + +#include +#include +#include "threadimpl.h" + +/* first argument goes in a register; simplest just to ignore it */ +static void +launchermips64(int, void (*f)(void *arg), void *arg) +{ + (*f)(arg); + threadexits(nil); +} + +void +_threadinitstack(Thread *t, void (*f)(void*), void *arg) +{ + uvlong *tos; + + tos = (uvlong*)&t->stk[t->stksize&~7]; + *--tos = (uvlong)arg; + *--tos = (uvlong)f; + *--tos = 0; /* first arg to launchermips64 */ + *--tos = 0; /* place to store return PC */ + t->sched[JMPBUFPC] = (uvlong)launchermips64+JMPBUFDPC; + t->sched[JMPBUFSP] = (uvlong)tos; +} --- /dev/null +++ /sys/src/libthread/spim64.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include "threadimpl.h" + +/* first argument goes in a register; simplest just to ignore it */ +static void +launcherspim64(int, void (*f)(void *arg), void *arg) +{ + (*f)(arg); + threadexits(nil); +} + +void +_threadinitstack(Thread *t, void (*f)(void*), void *arg) +{ + uvlong *tos; + + tos = (uvlong*)&t->stk[t->stksize&~7]; + *--tos = (uvlong)arg; + *--tos = (uvlong)f; + *--tos = 0; /* first arg to launcherspim64 */ + *--tos = 0; /* place to store return PC */ + t->sched[JMPBUFPC] = (uvlong)launcherspim64+JMPBUFDPC; + t->sched[JMPBUFSP] = (uvlong)tos; +}