summaryrefslogtreecommitdiff
path: root/sys/src/cmd/va
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/va
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/va')
-rwxr-xr-xsys/src/cmd/va/a.h182
-rwxr-xr-xsys/src/cmd/va/a.y588
-rwxr-xr-xsys/src/cmd/va/l.s703
-rwxr-xr-xsys/src/cmd/va/lex.c702
-rwxr-xr-xsys/src/cmd/va/mkfile19
5 files changed, 2194 insertions, 0 deletions
diff --git a/sys/src/cmd/va/a.h b/sys/src/cmd/va/a.h
new file mode 100755
index 000000000..9b1f4da38
--- /dev/null
+++ b/sys/src/cmd/va/a.h
@@ -0,0 +1,182 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "../vc/v.out.h"
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+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
+#define HISTSZ 20
+#define NINCLUDE 10
+#define NHUNK 10000
+#define EOF (-1)
+#define IGN (-2)
+#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
+#define NHASH 503
+#define STRINGSZ 200
+#define NMACRO 10
+
+struct Sym
+{
+ Sym* link;
+ char* macro;
+ long value;
+ ushort type;
+ char *name;
+ char sym;
+};
+#define S ((Sym*)0)
+
+EXTERN struct
+{
+ char* p;
+ int c;
+} fi;
+
+struct Io
+{
+ Io* link;
+ char b[BUFSIZ];
+ char* p;
+ short c;
+ short f;
+};
+#define I ((Io*)0)
+
+EXTERN struct
+{
+ Sym* sym;
+ short type;
+} h[NSYM];
+
+struct Gen
+{
+ Sym* sym;
+ long offset;
+ short type;
+ short reg;
+ short name;
+ double dval;
+ char sval[8];
+};
+
+struct Hist
+{
+ Hist* link;
+ char* name;
+ long line;
+ long offset;
+};
+#define H ((Hist*)0)
+
+enum
+{
+ CLAST,
+ CMACARG,
+ CMACRO,
+ CPREPROC
+};
+
+EXTERN char debug[256];
+EXTERN Sym* hash[NHASH];
+EXTERN char* Dlist[30];
+EXTERN int nDlist;
+EXTERN Hist* ehist;
+EXTERN int newflag;
+EXTERN Hist* hist;
+EXTERN char* hunk;
+EXTERN char* include[NINCLUDE];
+EXTERN Io* iofree;
+EXTERN Io* ionext;
+EXTERN Io* iostack;
+EXTERN long lineno;
+EXTERN int nerrors;
+EXTERN long nhunk;
+EXTERN int nosched;
+EXTERN int ninclude;
+EXTERN Gen nullgen;
+EXTERN char* outfile;
+EXTERN int pass;
+EXTERN char* pathname;
+EXTERN long pc;
+EXTERN int peekc;
+EXTERN int sym;
+EXTERN char symb[NSYMB];
+EXTERN int thechar;
+EXTERN char* thestring;
+EXTERN long thunk;
+EXTERN Biobuf obuf;
+
+void* alloc(long);
+void* allocn(void*, long, long);
+void errorexit(void);
+void pushio(void);
+void newio(void);
+void newfile(char*, int);
+Sym* slookup(char*);
+Sym* lookup(void);
+void syminit(Sym*);
+long yylex(void);
+int getc(void);
+int getnsc(void);
+void unget(int);
+int escchar(int);
+void cinit(void);
+void pinit(char*);
+void cclean(void);
+int isreg(Gen*);
+void outcode(int, Gen*, int, Gen*);
+void zname(char*, int, int);
+void zaddr(Gen*, int);
+void ieeedtod(Ieee*, double);
+int filbuf(void);
+Sym* getsym(void);
+void domacro(void);
+void macund(void);
+void macdef(void);
+void macexpand(Sym*, char*);
+void macinc(void);
+void maclin(void);
+void macprag(void);
+void macif(int);
+void macend(void);
+void outhist(void);
+void dodefine(char*);
+void prfile(long);
+void linehist(char*, int);
+void gethunk(void);
+void yyerror(char*, ...);
+int yyparse(void);
+void setinclude(char*);
+int assemble(char*);
+
+/*
+ * system-dependent stuff from ../cc/compat.c
+ */
+
+enum /* keep in synch with ../cc/cc.h */
+{
+ Plan9 = 1<<0,
+ Unix = 1<<1,
+ Windows = 1<<2
+};
+int mywait(int*);
+int mycreat(char*, int);
+int systemtype(int);
+int pathchar(void);
+char* mygetwd(char*, int);
+int myexec(char*, char*[]);
+int mydup(int, int);
+int myfork(void);
+int mypipe(int*);
+void* mysbrk(ulong);
diff --git a/sys/src/cmd/va/a.y b/sys/src/cmd/va/a.y
new file mode 100755
index 000000000..cbc07fd75
--- /dev/null
+++ b/sys/src/cmd/va/a.y
@@ -0,0 +1,588 @@
+%{
+#include "a.h"
+%}
+%union
+{
+ Sym *sym;
+ long lval;
+ double dval;
+ char sval[8];
+ Gen gen;
+}
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
+%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
+%token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
+%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
+%token <lval> LCONST LSP LSB LFP LPC LHI LLO LMREG
+%token <lval> LTYPEX LREG LFREG LFCREG LR LM LF
+%token <lval> LFCR LSCHED
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr pointer offset sreg
+%type <gen> gen vgen lgen vlgen rel reg freg mreg fcreg
+%type <gen> imm ximm ireg name oreg imr nireg fgen
+%%
+prog:
+| prog line
+
+line:
+ LLAB ':'
+ {
+ if($1->value != pc)
+ yyerror("redeclaration of %s", $1->name);
+ $1->value = pc;
+ }
+ line
+| LNAME ':'
+ {
+ $1->type = LLAB;
+ $1->value = pc;
+ }
+ line
+| LNAME '=' expr ';'
+ {
+ $1->type = LVAR;
+ $1->value = $3;
+ }
+| LVAR '=' expr ';'
+ {
+ if($1->value != $3)
+ yyerror("redeclaration of %s", $1->name);
+ $1->value = $3;
+ }
+| LSCHED ';'
+ {
+ nosched = $1;
+ }
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+/*
+ * Immed-type
+ */
+ LTYPE1 imr ',' sreg ',' reg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LTYPE1 imr ',' reg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * NOR
+ */
+| LTYPE2 imr ',' sreg ',' imr
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LTYPE2 imr ',' imr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * LOAD/STORE, but not MOVW
+ */
+| LTYPE3 lgen ',' gen
+ {
+ if(!isreg(&$2) && !isreg(&$4))
+ print("one side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * SPECIAL
+ */
+| LTYPE4 comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+/*
+ * MOVW
+ */
+| LTYPE5 vlgen ',' vgen
+ {
+ if(!isreg(&$2) && !isreg(&$4))
+ print("one side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * MUL/DIV
+ */
+| LTYPE6 reg ',' sreg comma
+ {
+ outcode($1, &$2, $4, &nullgen);
+ }
+| LTYPE6 reg ',' sreg ',' reg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * JMP/JAL
+ */
+| LTYPE7 comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE7 comma nireg
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE8 comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE8 comma nireg
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE8 sreg ',' nireg
+ {
+ outcode($1, &nullgen, $2, &$4);
+ }
+/*
+ * BEQ/BNE
+ */
+| LTYPE9 gen ',' rel
+ {
+ if(!isreg(&$2))
+ print("left side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPE9 gen ',' sreg ',' rel
+ {
+ if(!isreg(&$2))
+ print("left side must be register\n");
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * B-other
+ */
+| LTYPEA gen ',' rel
+ {
+ if(!isreg(&$2))
+ print("left side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * TEXT/GLOBL
+ */
+| LTYPEB name ',' imm
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPEB name ',' con ',' imm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * DATA
+ */
+| LTYPEC name '/' con ',' ximm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * floating-type
+ */
+| LTYPED freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPEE freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPEE freg ',' LFREG ',' freg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LTYPEF freg ',' LFREG comma
+ {
+ outcode($1, &$2, $4, &nullgen);
+ }
+/*
+ * coprocessor branch
+ */
+| LTYPEG comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+/*
+ * word
+ */
+| LTYPEH comma ximm
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+/*
+ * NOP
+ */
+| LTYPEI comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+| LTYPEI ',' vgen
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPEI vgen comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+/*
+ * BREAK -- overloaded with CACHE opcode
+ */
+| LTYPEJ comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+| LTYPEJ vgen ',' vgen
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+
+comma:
+| ','
+
+rel:
+ con '(' LPC ')'
+ {
+ $$ = nullgen;
+ $$.type = D_BRANCH;
+ $$.offset = $1 + pc;
+ }
+| LNAME offset
+ {
+ $$ = nullgen;
+ if(pass == 2)
+ yyerror("undefined label: %s", $1->name);
+ $$.type = D_BRANCH;
+ $$.sym = $1;
+ $$.offset = $2;
+ }
+| LLAB offset
+ {
+ $$ = nullgen;
+ $$.type = D_BRANCH;
+ $$.sym = $1;
+ $$.offset = $1->value + $2;
+ }
+
+vlgen:
+ lgen
+| fgen
+| mreg
+| fcreg
+| LHI
+ {
+ $$ = nullgen;
+ $$.type = D_HI;
+ }
+| LLO
+ {
+ $$ = nullgen;
+ $$.type = D_LO;
+ }
+
+vgen:
+ gen
+| fgen
+| mreg
+| fcreg
+| LHI
+ {
+ $$ = nullgen;
+ $$.type = D_HI;
+ }
+| LLO
+ {
+ $$ = nullgen;
+ $$.type = D_LO;
+ }
+
+lgen:
+ gen
+| ximm
+
+fgen:
+ freg
+
+mreg:
+ LMREG
+ {
+ $$ = nullgen;
+ $$.type = D_MREG;
+ $$.reg = $1;
+ }
+| LM '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_MREG;
+ $$.reg = $3;
+ }
+
+fcreg:
+ LFCREG
+ {
+ $$ = nullgen;
+ $$.type = D_FCREG;
+ $$.reg = $1;
+ }
+| LFCR '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_FCREG;
+ $$.reg = $3;
+ }
+
+freg:
+ LFREG
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $1;
+ }
+| LF '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $3;
+ }
+
+ximm: '$' con
+ {
+ $$ = nullgen;
+ $$.type = D_CONST;
+ $$.offset = $2;
+ }
+| '$' oreg
+ {
+ $$ = $2;
+ $$.type = D_CONST;
+ }
+| '$' '*' '$' oreg
+ {
+ $$ = $4;
+ $$.type = D_OCONST;
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.type = D_SCONST;
+ memcpy($$.sval, $2, sizeof($$.sval));
+ }
+| '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.type = D_FCONST;
+ $$.dval = $2;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.type = D_FCONST;
+ $$.dval = -$3;
+ }
+
+nireg:
+ ireg
+| con ireg
+ {
+ if($1 != 0)
+ yyerror("offset must be zero");
+ $$ = $2;
+ }
+| name
+ {
+ $$ = $1;
+ if($1.name != D_EXTERN && $1.name != D_STATIC) {
+ }
+ }
+
+ireg:
+ '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $2;
+ $$.offset = 0;
+ }
+
+gen:
+ reg
+| con
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.offset = $1;
+ }
+| oreg
+
+oreg:
+ name
+| name '(' sreg ')'
+ {
+ $$ = $1;
+ $$.type = D_OREG;
+ $$.reg = $3;
+ }
+| '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $2;
+ $$.offset = 0;
+ }
+| con '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $3;
+ $$.offset = $1;
+ }
+
+imr:
+ reg
+| imm
+
+imm: '$' con
+ {
+ $$ = nullgen;
+ $$.type = D_CONST;
+ $$.offset = $2;
+ }
+
+reg:
+ sreg
+ {
+ $$ = nullgen;
+ $$.type = D_REG;
+ $$.reg = $1;
+ }
+
+sreg:
+ LREG
+| LR '(' con ')'
+ {
+ if($$ < 0 || $$ >= NREG)
+ print("register value out of range\n");
+ $$ = $3;
+ }
+
+name:
+ con '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.name = $3;
+ $$.sym = S;
+ $$.offset = $1;
+ }
+| LNAME offset '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.name = $4;
+ $$.sym = $1;
+ $$.offset = $2;
+ }
+| LNAME '<' '>' offset '(' LSB ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.name = D_STATIC;
+ $$.sym = $1;
+ $$.offset = $4;
+ }
+
+offset:
+ {
+ $$ = 0;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+
+pointer:
+ LSB
+| LSP
+| LFP
+
+con:
+ LCONST
+| LVAR
+ {
+ $$ = $1->value;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '~' con
+ {
+ $$ = ~$2;
+ }
+| '(' expr ')'
+ {
+ $$ = $2;
+ }
+
+expr:
+ con
+| expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+| expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+| expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+| expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+| expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+| expr '<' '<' expr
+ {
+ $$ = $1 << $4;
+ }
+| expr '>' '>' expr
+ {
+ $$ = $1 >> $4;
+ }
+| expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+| expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+| expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
diff --git a/sys/src/cmd/va/l.s b/sys/src/cmd/va/l.s
new file mode 100755
index 000000000..2f8e6341f
--- /dev/null
+++ b/sys/src/cmd/va/l.s
@@ -0,0 +1,703 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+
+#define MAXMACH 4 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define MS2HZ 50 /* millisec per clock tick */
+#define TK2SEC(t) ((t)/20) /* ticks to seconds */
+#define TK2MS(t) ((t)*MS2HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((t)/MS2HZ) /* milliseconds to ticks */
+
+/*
+ * CP0 registers
+ */
+
+#define INDEX 0
+#define RANDOM 1
+#define TLBPHYS 2
+#define CONTEXT 4
+#define BADVADDR 8
+#define TLBVIRT 10
+#define STATUS 12
+#define CAUSE 13
+#define EPC 14
+#define PRID 15
+
+/*
+ * M(STATUS) bits
+ */
+#define IEC 0x00000001
+#define KUC 0x00000002
+#define IEP 0x00000004
+#define KUP 0x00000008
+#define INTMASK 0x0000ff00
+#define SW0 0x00000100
+#define SW1 0x00000200
+#define INTR0 0x00000400
+#define INTR1 0x00000800
+#define INTR2 0x00001000
+#define INTR3 0x00002000
+#define INTR4 0x00004000
+#define INTR5 0x00008000
+#define ISC 0x00010000
+#define SWC 0x00020000
+#define CU1 0x20000000
+
+/*
+ * Traps
+ */
+
+#define UTLBMISS (KSEG0+0x00)
+#define EXCEPTION (KSEG0+0x80)
+
+/*
+ * Magic registers
+ */
+
+#define MACH 25 /* R25 is m-> */
+#define USER 24 /* R24 is u-> */
+#define MPID 0xBF000000 /* long; low 3 bits identify mp bus slot */
+#define WBFLUSH 0xBC000000 /* D-CACHE data; used for write buffer flush */
+
+/*
+ * Fundamental addresses
+ */
+
+#define MACHADDR 0x80014000
+#define USERADDR 0xC0000000
+#define UREGADDR (USERADDR+BY2PG-4-0xA0)
+/*
+ * MMU
+ */
+
+#define KUSEG 0x00000000
+#define KSEG0 0x80000000
+#define KSEG1 0xA0000000
+#define KSEG2 0xC0000000
+#define KSEGM 0xE0000000 /* mask to check which seg */
+
+#define PTEGLOBL (1<<8)
+#define PTEVALID (1<<9)
+#define PTEWRITE (1<<10)
+#define PTEPID(n) ((n)<<6)
+
+#define NTLBPID 64 /* number of pids */
+#define NTLB 64 /* number of entries */
+#define TLBROFF 8 /* offset of first randomly indexed entry */
+
+/*
+ * Address spaces
+ */
+
+#define UZERO KUSEG /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define USTKTOP KZERO /* byte just beyond user stack */
+#define TSTKTOP (USERADDR+100*BY2PG) /* top of temporary stack */
+#define KZERO KSEG0 /* base of kernel address space */
+#define KTZERO (KSEG0+0x20000) /* first address in kernel text */
+#define USTACKSIZE (4*1024*1024) /* size of user stack */
+/*
+ * Exception codes
+ */
+#define CINT 0 /* external interrupt */
+#define CTLBM 1 /* TLB modification */
+#define CTLBL 2 /* TLB miss (load or fetch) */
+#define CTLBS 3 /* TLB miss (store) */
+#define CADREL 4 /* address error (load or fetch) */
+#define CADRES 5 /* address error (store) */
+#define CBUSI 6 /* bus error (fetch) */
+#define CBUSD 7 /* bus error (data load or store) */
+#define CSYS 8 /* system call */
+#define CBRK 9 /* breakpoint */
+#define CRES 10 /* reserved instruction */
+#define CCPU 11 /* coprocessor unusable */
+#define COVF 12 /* arithmetic overflow */
+#define CUNK13 13 /* undefined 13 */
+#define CUNK14 14 /* undefined 14 */
+#define CUNK15 15 /* undefined 15 */
+
+#define NSEG 5
+
+#define SP R29
+
+#define PROM (KSEG1+0x1FC00000)
+#define NOOP NOR R0,R0
+#define WAIT NOOP; NOOP
+
+/*
+ * Boot first processor
+ * - why is the processor number loaded from R0 ?????
+ */
+TEXT start(SB), $-4
+
+ MOVW $setR30(SB), R30
+ MOVW $(CU1|INTR5|INTR4|INTR3|INTR2|INTR1|SW1|SW0), R1
+ MOVW R1, M(STATUS)
+ WAIT
+
+ MOVW $(0x1C<<7), R1
+ MOVW R1, FCR31 /* permit only inexact and underflow */
+ NOOP
+ MOVD $0.5, F26
+ SUBD F26, F26, F24
+ ADDD F26, F26, F28
+ ADDD F28, F28, F30
+
+ MOVD F24, F0
+ MOVD F24, F2
+ MOVD F24, F4
+ MOVD F24, F6
+ MOVD F24, F8
+ MOVD F24, F10
+ MOVD F24, F12
+ MOVD F24, F14
+ MOVD F24, F16
+ MOVD F24, F18
+ MOVD F24, F20
+ MOVD F24, F22
+
+ MOVW $MACHADDR, R(MACH)
+ ADDU $(BY2PG-4), R(MACH), SP
+ MOVW $0, R(USER)
+ MOVW R0, 0(R(MACH))
+
+ MOVW $edata(SB), R1
+ MOVW $end(SB), R2
+
+clrbss:
+ MOVB $0, (R1)
+ ADDU $1, R1
+ BNE R1, R2, clrbss
+
+ MOVW R4, _argc(SB)
+ MOVW R5, _argv(SB)
+ MOVW R6, _env(SB)
+ JAL main(SB)
+ JMP (R0)
+
+/*
+ * Take first processor into user mode
+ * - argument is stack pointer to user
+ */
+
+TEXT touser(SB), $-4
+
+ MOVW M(STATUS), R1
+ OR $(KUP|IEP), R1
+ MOVW R1, M(STATUS)
+ NOOP
+ MOVW 0(FP), SP
+ MOVW $(UTZERO+32), R26 /* header appears in text */
+ RFE (R26)
+
+/*
+ * Bring subsequent processors on line
+ */
+TEXT newstart(SB), $0
+
+ MOVW $setR30(SB), R30
+ MOVW $(INTR5|INTR4|INTR3|INTR2|INTR1|SW1|SW0), R1
+ MOVW R1, M(STATUS)
+ NOOP
+ MOVW $MACHADDR, R(MACH)
+ MOVB (MPID+3), R1
+ AND $7, R1
+ SLL $PGSHIFT, R1, R2
+ ADDU R2, R(MACH)
+ ADDU $(BY2PG-4), R(MACH), SP
+ MOVW $0, R(USER)
+ MOVW R1, 0(R(MACH))
+ JAL online(SB)
+ JMP (R0)
+
+TEXT firmware(SB), $0
+
+ MOVW $(PROM+0x18), R1 /**/
+/* MOVW $(PROM+0x00), R1 /**/
+ JMP (R1)
+
+TEXT splhi(SB), $0
+
+ MOVW M(STATUS), R1
+ AND $~IEC, R1, R2
+ MOVW R2, M(STATUS)
+ NOOP
+ RET
+
+TEXT spllo(SB), $0
+
+ MOVW M(STATUS), R1
+ OR $IEC, R1, R2
+ MOVW R2, M(STATUS)
+ NOOP
+ RET
+
+TEXT splx(SB), $0
+
+ MOVW 0(FP), R1
+ MOVW M(STATUS), R2
+ AND $IEC, R1
+ AND $~IEC, R2
+ OR R2, R1
+ MOVW R1, M(STATUS)
+ NOOP
+ RET
+
+TEXT wbflush(SB), $-4
+
+ MOVW $WBFLUSH, R1
+ MOVW 0(R1), R1
+ RET
+
+TEXT setlabel(SB), $0
+
+ MOVW 0(FP), R2
+ MOVW $0, R1
+ MOVW R31, 0(R2)
+ MOVW R29, 4(R2)
+ RET
+
+TEXT gotolabel(SB), $0
+
+ MOVW 0(FP), R2
+ MOVW $1, R1
+ MOVW 0(R2), R31
+ MOVW 4(R2), R29
+ RET
+
+TEXT gotopc(SB), $8
+
+ MOVW 0(FP), R7 /* save arguments for later */
+ MOVW _argc(SB), R4
+ MOVW _argv(SB), R5
+ MOVW _env(SB), R6
+ MOVW R0, 4(SP)
+ MOVW $(64*1024), R1
+ MOVW R1, 8(SP)
+ JAL icflush(SB)
+ JMP (R7)
+
+TEXT puttlb(SB), $4
+
+ JAL splhi(SB)
+ MOVW 0(FP), R2
+ MOVW 4(FP), R3
+ MOVW R1, 4(SP)
+ MOVW R2, M(TLBVIRT)
+ MOVW R3, M(TLBPHYS)
+ NOOP
+ TLBP
+ NOOP
+ MOVW M(INDEX), R4
+ BGEZ R4, index
+ TLBWR
+ NOOP
+ JAL splx(SB)
+ RET
+index:
+ TLBWI
+ NOOP
+ JAL splx(SB)
+ RET
+
+TEXT puttlbx(SB), $0
+
+ MOVW 0(FP), R4
+ MOVW 4(FP), R2
+ MOVW 8(FP), R3
+ SLL $8, R4
+ MOVW R2, M(TLBVIRT)
+ MOVW R3, M(TLBPHYS)
+ MOVW R4, M(INDEX)
+ NOOP
+ TLBWI
+ NOOP
+ RET
+
+TEXT tlbp(SB), $0
+ TLBP
+ NOOP
+ MOVW M(INDEX), R1
+ RET
+
+TEXT tlbvirt(SB), $0
+ TLBP
+ NOOP
+ MOVW M(TLBVIRT), R1
+ RET
+
+
+TEXT gettlb(SB), $0
+
+ MOVW 0(FP), R3
+ MOVW 4(FP), R4
+ SLL $8, R3
+ MOVW R3, M(INDEX)
+ NOOP
+ TLBR
+ NOOP
+ MOVW M(TLBVIRT), R1
+ MOVW M(TLBPHYS), R2
+ NOOP
+ MOVW R1, 0(R4)
+ MOVW R2, 4(R4)
+ RET
+
+TEXT gettlbvirt(SB), $0
+
+ MOVW 0(FP), R3
+ SLL $8, R3
+ MOVW R3, M(INDEX)
+ NOOP
+ TLBR
+ NOOP
+ MOVW M(TLBVIRT), R1
+ NOOP
+ RET
+
+TEXT vector80(SB), $-4
+
+ MOVW $exception(SB), R26
+ JMP (R26)
+
+TEXT exception(SB), $-4
+
+ MOVW M(STATUS), R26
+ AND $KUP, R26
+ BEQ R26, waskernel
+
+wasuser:
+ MOVW SP, R26
+ /*
+ * set kernel sp: ureg - ureg* - pc
+ * done in 2 steps because R30 is not set
+ * and the loader will make a literal
+ */
+ MOVW $((UREGADDR-2*BY2WD) & 0xffff0000), SP
+ OR $((UREGADDR-2*BY2WD) & 0xffff), SP
+ MOVW R26, 0x10(SP) /* user SP */
+ MOVW R31, 0x28(SP)
+ MOVW R30, 0x2C(SP)
+ MOVW M(CAUSE), R26
+ MOVW R(MACH), 0x3C(SP)
+ MOVW R(USER), 0x40(SP)
+ AND $(0xF<<2), R26
+ SUB $(CSYS<<2), R26
+
+ JAL saveregs(SB)
+
+ MOVW $setR30(SB), R30
+ SUBU $(UREGADDR-2*BY2WD-USERADDR), SP, R(USER)
+ MOVW $MPID, R1
+ MOVB 3(R1), R1
+ MOVW $MACHADDR, R(MACH) /* locn of mach 0 */
+ AND $7, R1
+ SLL $PGSHIFT, R1
+ ADDU R1, R(MACH) /* add offset for mach # */
+
+ BNE R26, notsys
+
+ JAL syscall(SB)
+
+ MOVW 0x28(SP), R31
+ MOVW 0x08(SP), R26
+ MOVW 0x2C(SP), R30
+ MOVW R26, M(STATUS)
+ NOOP
+ MOVW 0x0C(SP), R26 /* old pc */
+ MOVW 0x10(SP), SP
+ RFE (R26)
+
+notsys:
+ JAL trap(SB)
+
+restore:
+ JAL restregs(SB)
+ MOVW 0x28(SP), R31
+ MOVW 0x2C(SP), R30
+ MOVW 0x3C(SP), R(MACH)
+ MOVW 0x40(SP), R(USER)
+ MOVW 0x10(SP), SP
+ RFE (R26)
+
+waskernel:
+ MOVW $1, R26 /* not sys call */
+ MOVW SP, -0x90(SP) /* drop this if possible */
+ SUB $0xA0, SP
+ MOVW R31, 0x28(SP)
+ JAL saveregs(SB)
+ JAL trap(SB)
+ JAL restregs(SB)
+ MOVW 0x28(SP), R31
+ ADD $0xA0, SP
+ RFE (R26)
+
+TEXT saveregs(SB), $-4
+ MOVW R1, 0x9C(SP)
+ MOVW R2, 0x98(SP)
+ ADDU $8, SP, R1
+ MOVW R1, 0x04(SP) /* arg to base of regs */
+ MOVW M(STATUS), R1
+ MOVW M(EPC), R2
+ MOVW R1, 0x08(SP)
+ MOVW R2, 0x0C(SP)
+
+ BEQ R26, return /* sys call, don't save */
+
+ MOVW M(CAUSE), R1
+ MOVW M(BADVADDR), R2
+ MOVW R1, 0x14(SP)
+ MOVW M(TLBVIRT), R1
+ MOVW R2, 0x18(SP)
+ MOVW R1, 0x1C(SP)
+ MOVW HI, R1
+ MOVW LO, R2
+ MOVW R1, 0x20(SP)
+ MOVW R2, 0x24(SP)
+ /* LINK,SB,SP missing */
+ MOVW R28, 0x30(SP)
+ /* R27, R26 not saved */
+ /* R25, R24 missing */
+ MOVW R23, 0x44(SP)
+ MOVW R22, 0x48(SP)
+ MOVW R21, 0x4C(SP)
+ MOVW R20, 0x50(SP)
+ MOVW R19, 0x54(SP)
+ MOVW R18, 0x58(SP)
+ MOVW R17, 0x5C(SP)
+ MOVW R16, 0x60(SP)
+ MOVW R15, 0x64(SP)
+ MOVW R14, 0x68(SP)
+ MOVW R13, 0x6C(SP)
+ MOVW R12, 0x70(SP)
+ MOVW R11, 0x74(SP)
+ MOVW R10, 0x78(SP)
+ MOVW R9, 0x7C(SP)
+ MOVW R8, 0x80(SP)
+ MOVW R7, 0x84(SP)
+ MOVW R6, 0x88(SP)
+ MOVW R5, 0x8C(SP)
+ MOVW R4, 0x90(SP)
+ MOVW R3, 0x94(SP)
+return:
+ RET
+
+TEXT restregs(SB), $-4
+ /* LINK,SB,SP missing */
+ MOVW 0x30(SP), R28
+ /* R27, R26 not saved */
+ /* R25, R24 missing */
+ MOVW 0x44(SP), R23
+ MOVW 0x48(SP), R22
+ MOVW 0x4C(SP), R21
+ MOVW 0x50(SP), R20
+ MOVW 0x54(SP), R19
+ MOVW 0x58(SP), R18
+ MOVW 0x5C(SP), R17
+ MOVW 0x60(SP), R16
+ MOVW 0x64(SP), R15
+ MOVW 0x68(SP), R14
+ MOVW 0x6C(SP), R13
+ MOVW 0x70(SP), R12
+ MOVW 0x74(SP), R11
+ MOVW 0x78(SP), R10
+ MOVW 0x7C(SP), R9
+ MOVW 0x80(SP), R8
+ MOVW 0x84(SP), R7
+ MOVW 0x88(SP), R6
+ MOVW 0x8C(SP), R5
+ MOVW 0x90(SP), R4
+ MOVW 0x94(SP), R3
+ MOVW 0x24(SP), R2
+ MOVW 0x20(SP), R1
+ MOVW R2, LO
+ MOVW R1, HI
+ MOVW 0x08(SP), R1
+ MOVW 0x98(SP), R2
+ MOVW R1, M(STATUS)
+ NOOP
+ MOVW 0x9C(SP), R1
+ MOVW 0x0C(SP), R26 /* old pc */
+ RET
+
+TEXT rfnote(SB), $0
+ MOVW 0(FP), R26 /* 1st arg is &uregpointer */
+ SUBU $(BY2WD), R26, SP /* pc hole */
+ BNE R26, restore
+
+
+TEXT clrfpintr(SB), $0
+ MOVW FCR31, R1
+ MOVW R1, R2
+ AND $~(0x3F<<12), R2
+ MOVW R2, FCR31
+ RET
+
+TEXT savefpregs(SB), $0
+ MOVW M(STATUS), R3
+ MOVW 0(FP), R1
+ MOVW FCR31, R2
+
+ MOVD F0, 0x00(R1)
+ MOVD F2, 0x08(R1)
+ MOVD F4, 0x10(R1)
+ MOVD F6, 0x18(R1)
+ MOVD F8, 0x20(R1)
+ MOVD F10, 0x28(R1)
+ MOVD F12, 0x30(R1)
+ MOVD F14, 0x38(R1)
+ MOVD F16, 0x40(R1)
+ MOVD F18, 0x48(R1)
+ MOVD F20, 0x50(R1)
+ MOVD F22, 0x58(R1)
+ MOVD F24, 0x60(R1)
+ MOVD F26, 0x68(R1)
+ MOVD F28, 0x70(R1)
+ MOVD F30, 0x78(R1)
+
+ MOVW R2, 0x80(R1)
+ AND $~CU1, R3
+ MOVW R3, M(STATUS)
+ RET
+
+TEXT restfpregs(SB), $0
+
+ MOVW M(STATUS), R3
+ MOVW 0(FP), R1
+ OR $CU1, R3
+ MOVW R3, M(STATUS)
+ MOVW 0x80(R1), R2
+
+ MOVD 0x00(R1), F0
+ MOVD 0x08(R1), F2
+ MOVD 0x10(R1), F4
+ MOVD 0x18(R1), F6
+ MOVD 0x20(R1), F8
+ MOVD 0x28(R1), F10
+ MOVD 0x30(R1), F12
+ MOVD 0x38(R1), F14
+ MOVD 0x40(R1), F16
+ MOVD 0x48(R1), F18
+ MOVD 0x50(R1), F20
+ MOVD 0x58(R1), F22
+ MOVD 0x60(R1), F24
+ MOVD 0x68(R1), F26
+ MOVD 0x70(R1), F28
+ MOVD 0x78(R1), F30
+
+ MOVW R2, FCR31
+ AND $~CU1, R3
+ MOVW R3, M(STATUS)
+ RET
+
+/*
+ * we avoid using R4, R5, R6, and R7 so gotopc can call us without saving them
+ */
+TEXT icflush(SB), $-4 /* icflush(physaddr, nbytes) */
+
+ MOVW M(STATUS), R10
+ MOVW 0(FP), R8
+ MOVW 4(FP), R9
+ MOVW $KSEG0, R3
+ OR R3, R8
+ MOVW $0, M(STATUS)
+ MOVW $WBFLUSH, R1 /* wbflush */
+ MOVW 0(R1), R1
+ NOOP
+ MOVW $KSEG1, R3
+ MOVW $icflush0(SB), R2 /* make sure PC is in uncached address space */
+ MOVW $(SWC|ISC), R1
+ OR R3, R2
+ JMP (R2)
+
+TEXT icflush0(SB), $-4
+
+ MOVW R1, M(STATUS) /* swap and isolate cache, splhi */
+ MOVW $icflush1(SB), R2
+ JMP (R2)
+
+TEXT icflush1(SB), $-4
+
+_icflush1:
+ MOVBU R0, 0x00(R8)
+ MOVBU R0, 0x04(R8)
+ MOVBU R0, 0x08(R8)
+ MOVBU R0, 0x0C(R8)
+ MOVBU R0, 0x10(R8)
+ MOVBU R0, 0x14(R8)
+ MOVBU R0, 0x18(R8)
+ MOVBU R0, 0x1C(R8)
+ MOVBU R0, 0x20(R8)
+ MOVBU R0, 0x24(R8)
+ MOVBU R0, 0x28(R8)
+ MOVBU R0, 0x2C(R8)
+ MOVBU R0, 0x30(R8)
+ MOVBU R0, 0x34(R8)
+ MOVBU R0, 0x38(R8)
+ MOVBU R0, 0x3C(R8)
+ SUB $0x40, R9
+ ADD $0x40, R8
+ BGTZ R9, _icflush1
+ MOVW $icflush2(SB), R2 /* make sure PC is in uncached address space */
+ OR R3, R2
+ JMP (R2)
+
+TEXT icflush2(SB), $-4
+
+ MOVW $0, M(STATUS) /* swap back caches, de-isolate them, and stay splhi */
+ NOOP /* +++ */
+ MOVW R10, M(STATUS)
+ RET
+
+TEXT dcflush(SB), $-4 /* dcflush(physaddr, nbytes) */
+
+ MOVW M(STATUS), R6
+ MOVW 0(FP), R4
+ MOVW 4(FP), R5
+ MOVW $KSEG0, R3
+ OR R3, R4
+ MOVW $0, M(STATUS)
+ MOVW $WBFLUSH, R1
+ MOVW 0(R1), R1
+ NOOP
+ MOVW $ISC, R1
+ MOVW R1, M(STATUS)
+_dcflush0:
+ MOVBU R0, 0x00(R4)
+ MOVBU R0, 0x04(R4)
+ MOVBU R0, 0x08(R4)
+ MOVBU R0, 0x0C(R4)
+ MOVBU R0, 0x10(R4)
+ MOVBU R0, 0x14(R4)
+ MOVBU R0, 0x18(R4)
+ MOVBU R0, 0x1C(R4)
+ MOVBU R0, 0x20(R4)
+ MOVBU R0, 0x24(R4)
+ MOVBU R0, 0x28(R4)
+ MOVBU R0, 0x2C(R4)
+ MOVBU R0, 0x30(R4)
+ MOVBU R0, 0x34(R4)
+ MOVBU R0, 0x38(R4)
+ MOVBU R0, 0x3C(R4)
+ SUB $0x40, R5
+ ADD $0x40, R4
+ BGTZ R5, _dcflush0
+ MOVW $0, M(STATUS)
+ NOOP /* +++ */
+ MOVW R6, M(STATUS)
+ RET
diff --git a/sys/src/cmd/va/lex.c b/sys/src/cmd/va/lex.c
new file mode 100755
index 000000000..61448d2eb
--- /dev/null
+++ b/sys/src/cmd/va/lex.c
@@ -0,0 +1,702 @@
+#define EXTERN
+#include "a.h"
+#include "y.tab.h"
+#include <ctype.h>
+
+void
+main(int argc, char *argv[])
+{
+ char *p;
+ int nout, nproc, status, i, c;
+
+ thechar = 'v';
+ thestring = "mips";
+ memset(debug, 0, sizeof(debug));
+ cinit();
+ outfile = 0;
+ include[ninclude++] = ".";
+ ARGBEGIN {
+ default:
+ c = ARGC();
+ if(c >= 0 || c < sizeof(debug))
+ debug[c] = 1;
+ break;
+
+ case 'o':
+ outfile = ARGF();
+ break;
+
+ case 'D':
+ p = ARGF();
+ if(p)
+ Dlist[nDlist++] = p;
+ break;
+
+ case 'I':
+ p = ARGF();
+ setinclude(p);
+ break;
+ case 'L': /* for little-endian mips */
+ thechar = '0';
+ thestring = "spim";
+ break;
+ } ARGEND
+ if(*argv == 0) {
+ print("usage: %ca [-options] file.s\n", thechar);
+ errorexit();
+ }
+ if(argc > 1 && systemtype(Windows)){
+ print("can't assemble multiple files on windows\n");
+ errorexit();
+ }
+ if(argc > 1 && !systemtype(Windows)) {
+ nproc = 1;
+ if(p = getenv("NPROC"))
+ nproc = atol(p); /* */
+ c = 0;
+ nout = 0;
+ for(;;) {
+ while(nout < nproc && argc > 0) {
+ i = myfork();
+ if(i < 0) {
+ i = mywait(&status);
+ if(i < 0)
+ errorexit();
+ if(status)
+ c++;
+ nout--;
+ continue;
+ }
+ if(i == 0) {
+ print("%s:\n", *argv);
+ if(assemble(*argv))
+ errorexit();
+ exits(0);
+ }
+ nout++;
+ argc--;
+ argv++;
+ }
+ i = mywait(&status);
+ if(i < 0) {
+ if(c)
+ errorexit();
+ exits(0);
+ }
+ if(status)
+ c++;
+ nout--;
+ }
+ }
+ if(assemble(argv[0]))
+ errorexit();
+ exits(0);
+}
+
+int
+assemble(char *file)
+{
+ char ofile[100], incfile[20], *p;
+ int i, of;
+
+ strcpy(ofile, file);
+ p = utfrrune(ofile, pathchar());
+ if(p) {
+ include[0] = ofile;
+ *p++ = 0;
+ } else
+ p = ofile;
+ if(outfile == 0) {
+ outfile = p;
+ if(outfile){
+ p = utfrrune(outfile, '.');
+ if(p)
+ if(p[1] == 's' && p[2] == 0)
+ p[0] = 0;
+ p = utfrune(outfile, 0);
+ p[0] = '.';
+ p[1] = thechar;
+ p[2] = 0;
+ } else
+ outfile = "/dev/null";
+ }
+ p = getenv("INCLUDE");
+ if(p) {
+ setinclude(p);
+ } else {
+ if(systemtype(Plan9)) {
+ sprint(incfile,"/%s/include", thestring);
+ setinclude(strdup(incfile));
+ }
+ }
+
+ of = mycreat(outfile, 0664);
+ if(of < 0) {
+ yyerror("%ca: cannot create %s", thechar, outfile);
+ errorexit();
+ }
+ Binit(&obuf, of, OWRITE);
+
+ pass = 1;
+ pinit(file);
+ for(i=0; i<nDlist; i++)
+ dodefine(Dlist[i]);
+ yyparse();
+ if(nerrors) {
+ cclean();
+ return nerrors;
+ }
+
+ pass = 2;
+ outhist();
+ pinit(file);
+ for(i=0; i<nDlist; i++)
+ dodefine(Dlist[i]);
+ yyparse();
+ cclean();
+ return nerrors;
+}
+
+struct
+{
+ char *name;
+ ushort type;
+ ushort value;
+} itab[] =
+{
+ "SP", LSP, D_AUTO,
+ "SB", LSB, D_EXTERN,
+ "FP", LFP, D_PARAM,
+ "PC", LPC, D_BRANCH,
+ "HI", LHI, D_HI,
+ "LO", LLO, D_LO,
+
+ "R", LR, 0,
+ "R0", LREG, 0,
+ "R1", LREG, 1,
+ "R2", LREG, 2,
+ "R3", LREG, 3,
+ "R4", LREG, 4,
+ "R5", LREG, 5,
+ "R6", LREG, 6,
+ "R7", LREG, 7,
+ "R8", LREG, 8,
+ "R9", LREG, 9,
+ "R10", LREG, 10,
+ "R11", LREG, 11,
+ "R12", LREG, 12,
+ "R13", LREG, 13,
+ "R14", LREG, 14,
+ "R15", LREG, 15,
+ "R16", LREG, 16,
+ "R17", LREG, 17,
+ "R18", LREG, 18,
+ "R19", LREG, 19,
+ "R20", LREG, 20,
+ "R21", LREG, 21,
+ "R22", LREG, 22,
+ "R23", LREG, 23,
+ "R24", LREG, 24,
+ "R25", LREG, 25,
+ "R26", LREG, 26,
+ "R27", LREG, 27,
+ "R28", LREG, 28,
+ "R29", LREG, 29,
+ "R30", LREG, 30,
+ "R31", LREG, 31,
+
+ "M", LM, 0,
+ "M0", LMREG, 0,
+ "M1", LMREG, 1,
+ "M2", LMREG, 2,
+ "M3", LMREG, 3,
+ "M4", LMREG, 4,
+ "M5", LMREG, 5,
+ "M6", LMREG, 6,
+ "M7", LMREG, 7,
+ "M8", LMREG, 8,
+ "M9", LMREG, 9,
+ "M10", LMREG, 10,
+ "M11", LMREG, 11,
+ "M12", LMREG, 12,
+ "M13", LMREG, 13,
+ "M14", LMREG, 14,
+ "M15", LMREG, 15,
+ "M16", LMREG, 16,
+ "M17", LMREG, 17,
+ "M18", LMREG, 18,
+ "M19", LMREG, 19,
+ "M20", LMREG, 20,
+ "M21", LMREG, 21,
+ "M22", LMREG, 22,
+ "M23", LMREG, 23,
+ "M24", LMREG, 24,
+ "M25", LMREG, 25,
+ "M26", LMREG, 26,
+ "M27", LMREG, 27,
+ "M28", LMREG, 28,
+ "M29", LMREG, 29,
+ "M30", LMREG, 30,
+ "M31", LMREG, 31,
+
+ "F", LF, 0,
+
+ "F0", LFREG, 0,
+ "F1", LFREG, 1,
+ "F2", LFREG, 2,
+ "F3", LFREG, 3,
+ "F4", LFREG, 4,
+ "F5", LFREG, 5,
+ "F6", LFREG, 6,
+ "F7", LFREG, 7,
+ "F8", LFREG, 8,
+ "F9", LFREG, 9,
+ "F10", LFREG, 10,
+ "F11", LFREG, 11,
+ "F12", LFREG, 12,
+ "F13", LFREG, 13,
+ "F14", LFREG, 14,
+ "F15", LFREG, 15,
+ "F16", LFREG, 16,
+ "F17", LFREG, 17,
+ "F18", LFREG, 18,
+ "F19", LFREG, 19,
+ "F20", LFREG, 20,
+ "F21", LFREG, 21,
+ "F22", LFREG, 22,
+ "F23", LFREG, 23,
+ "F24", LFREG, 24,
+ "F25", LFREG, 25,
+ "F26", LFREG, 26,
+ "F27", LFREG, 27,
+ "F28", LFREG, 28,
+ "F29", LFREG, 29,
+ "F30", LFREG, 30,
+ "F31", LFREG, 31,
+
+ "FCR", LFCR, 0,
+ "FCR0", LFCREG, 0,
+ "FCR1", LFCREG, 1,
+ "FCR2", LFCREG, 2,
+ "FCR3", LFCREG, 3,
+ "FCR4", LFCREG, 4,
+ "FCR5", LFCREG, 5,
+ "FCR6", LFCREG, 6,
+ "FCR7", LFCREG, 7,
+ "FCR8", LFCREG, 8,
+ "FCR9", LFCREG, 9,
+ "FCR10", LFCREG, 10,
+ "FCR11", LFCREG, 11,
+ "FCR12", LFCREG, 12,
+ "FCR13", LFCREG, 13,
+ "FCR14", LFCREG, 14,
+ "FCR15", LFCREG, 15,
+ "FCR16", LFCREG, 16,
+ "FCR17", LFCREG, 17,
+ "FCR18", LFCREG, 18,
+ "FCR19", LFCREG, 19,
+ "FCR20", LFCREG, 20,
+ "FCR21", LFCREG, 21,
+ "FCR22", LFCREG, 22,
+ "FCR23", LFCREG, 23,
+ "FCR24", LFCREG, 24,
+ "FCR25", LFCREG, 25,
+ "FCR26", LFCREG, 26,
+ "FCR27", LFCREG, 27,
+ "FCR28", LFCREG, 28,
+ "FCR29", LFCREG, 29,
+ "FCR30", LFCREG, 30,
+ "FCR31", LFCREG, 31,
+
+ "ADD", LTYPE1, AADD,
+ "ADDU", LTYPE1, AADDU,
+ "SUB", LTYPE1, ASUB, /* converted to ADD(-) in loader */
+ "SUBU", LTYPE1, ASUBU,
+ "SGT", LTYPE1, ASGT,
+ "SGTU", LTYPE1, ASGTU,
+ "AND", LTYPE1, AAND,
+ "OR", LTYPE1, AOR,
+ "XOR", LTYPE1, AXOR,
+ "SLL", LTYPE1, ASLL,
+ "SRL", LTYPE1, ASRL,
+ "SRA", LTYPE1, ASRA,
+
+ "ADDV", LTYPE1, AADDV,
+ "ADDVU", LTYPE1, AADDVU,
+ "SUBV", LTYPE1, ASUBV, /* converted to ADD(-) in loader */
+ "SUBVU", LTYPE1, ASUBVU,
+ "SLLV", LTYPE1, ASLLV,
+ "SRLV", LTYPE1, ASRLV,
+ "SRAV", LTYPE1, ASRAV,
+
+ "NOR", LTYPE2, ANOR,
+
+ "MOVB", LTYPE3, AMOVB,
+ "MOVBU", LTYPE3, AMOVBU,
+ "MOVH", LTYPE3, AMOVH,
+ "MOVHU", LTYPE3, AMOVHU,
+ "MOVWL", LTYPE3, AMOVWL,
+ "MOVWR", LTYPE3, AMOVWR,
+ "MOVVL", LTYPE3, AMOVVL,
+ "MOVVR", LTYPE3, AMOVVR,
+
+ "BREAK", LTYPEJ, ABREAK, /* overloaded CACHE opcode */
+ "END", LTYPE4, AEND,
+ "REM", LTYPE6, AREM,
+ "REMU", LTYPE6, AREMU,
+ "RET", LTYPE4, ARET,
+ "SYSCALL", LTYPE4, ASYSCALL,
+ "TLBP", LTYPE4, ATLBP,
+ "TLBR", LTYPE4, ATLBR,
+ "TLBWI", LTYPE4, ATLBWI,
+ "TLBWR", LTYPE4, ATLBWR,
+
+ "MOVW", LTYPE5, AMOVW,
+ "MOVV", LTYPE5, AMOVV,
+ "MOVD", LTYPE5, AMOVD,
+ "MOVF", LTYPE5, AMOVF,
+
+ "DIV", LTYPE6, ADIV,
+ "DIVU", LTYPE6, ADIVU,
+ "MUL", LTYPE6, AMUL,
+ "MULU", LTYPE6, AMULU,
+ "DIVV", LTYPE6, ADIVV,
+ "DIVVU", LTYPE6, ADIVVU,
+ "MULV", LTYPE6, AMULV,
+ "MULVU", LTYPE6, AMULVU,
+
+ "RFE", LTYPE7, ARFE,
+ "JMP", LTYPE7, AJMP,
+
+ "JAL", LTYPE8, AJAL,
+
+ "BEQ", LTYPE9, ABEQ,
+ "BNE", LTYPE9, ABNE,
+
+ "BGEZ", LTYPEA, ABGEZ,
+ "BGEZAL", LTYPEA, ABGEZAL,
+ "BGTZ", LTYPEA, ABGTZ,
+ "BLEZ", LTYPEA, ABLEZ,
+ "BLTZ", LTYPEA, ABLTZ,
+ "BLTZAL", LTYPEA, ABLTZAL,
+
+ "TEXT", LTYPEB, ATEXT,
+ "GLOBL", LTYPEB, AGLOBL,
+
+ "DATA", LTYPEC, ADATA,
+
+ "MOVDF", LTYPE5, AMOVDF,
+ "MOVDW", LTYPE5, AMOVDW,
+ "MOVFD", LTYPE5, AMOVFD,
+ "MOVFW", LTYPE5, AMOVFW,
+ "MOVWD", LTYPE5, AMOVWD,
+ "MOVWF", LTYPE5, AMOVWF,
+
+ "ABSD", LTYPED, AABSD,
+ "ABSF", LTYPED, AABSF,
+ "ABSW", LTYPED, AABSW,
+ "NEGD", LTYPED, ANEGD,
+ "NEGF", LTYPED, ANEGF,
+ "NEGW", LTYPED, ANEGW,
+
+ "CMPEQD", LTYPEF, ACMPEQD,
+ "CMPEQF", LTYPEF, ACMPEQF,
+ "CMPGED", LTYPEF, ACMPGED,
+ "CMPGEF", LTYPEF, ACMPGEF,
+ "CMPGTD", LTYPEF, ACMPGTD,
+ "CMPGTF", LTYPEF, ACMPGTF,
+
+ "ADDD", LTYPEE, AADDD,
+ "ADDF", LTYPEE, AADDF,
+ "ADDW", LTYPEE, AADDW,
+ "DIVD", LTYPEE, ADIVD,
+ "DIVF", LTYPEE, ADIVF,
+ "DIVW", LTYPEE, ADIVW,
+ "MULD", LTYPEE, AMULD,
+ "MULF", LTYPEE, AMULF,
+ "MULW", LTYPEE, AMULW,
+ "SUBD", LTYPEE, ASUBD,
+ "SUBF", LTYPEE, ASUBF,
+ "SUBW", LTYPEE, ASUBW,
+
+ "BFPT", LTYPEG, ABFPT,
+ "BFPF", LTYPEG, ABFPF,
+
+ "WORD", LTYPEH, AWORD,
+ "NOP", LTYPEI, ANOP,
+ "SCHED", LSCHED, 0,
+ "NOSCHED", LSCHED, 0x80,
+ 0
+};
+
+void
+cinit(void)
+{
+ Sym *s;
+ int i;
+
+ nullgen.sym = S;
+ nullgen.offset = 0;
+ nullgen.type = D_NONE;
+ nullgen.name = D_NONE;
+ nullgen.reg = NREG;
+ if(FPCHIP)
+ nullgen.dval = 0;
+ for(i=0; i<sizeof(nullgen.sval); i++)
+ nullgen.sval[i] = 0;
+
+ nerrors = 0;
+ iostack = I;
+ iofree = I;
+ peekc = IGN;
+ nhunk = 0;
+ for(i=0; i<NHASH; i++)
+ hash[i] = S;
+ for(i=0; itab[i].name; i++) {
+ s = slookup(itab[i].name);
+ s->type = itab[i].type;
+ s->value = itab[i].value;
+ }
+
+ pathname = allocn(pathname, 0, 100);
+ if(mygetwd(pathname, 99) == 0) {
+ pathname = allocn(pathname, 100, 900);
+ if(mygetwd(pathname, 999) == 0)
+ strcpy(pathname, "/???");
+ }
+}
+
+void
+syminit(Sym *s)
+{
+
+ s->type = LNAME;
+ s->value = 0;
+}
+
+int
+isreg(Gen *g)
+{
+
+ USED(g);
+ return 1;
+}
+
+void
+cclean(void)
+{
+
+ outcode(AEND, &nullgen, NREG, &nullgen);
+ Bflush(&obuf);
+}
+
+void
+zname(char *n, int t, int s)
+{
+
+ Bputc(&obuf, ANAME);
+ Bputc(&obuf, t); /* type */
+ Bputc(&obuf, s); /* sym */
+ while(*n) {
+ Bputc(&obuf, *n);
+ n++;
+ }
+ Bputc(&obuf, 0);
+}
+
+void
+zaddr(Gen *a, int s)
+{
+ long l;
+ int i;
+ char *n;
+ Ieee e;
+
+ Bputc(&obuf, a->type);
+ Bputc(&obuf, a->reg);
+ Bputc(&obuf, s);
+ Bputc(&obuf, a->name);
+ switch(a->type) {
+ default:
+ print("unknown type %d\n", a->type);
+ exits("arg");
+
+ 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_OCONST:
+ case D_BRANCH:
+ l = a->offset;
+ Bputc(&obuf, l);
+ Bputc(&obuf, l>>8);
+ Bputc(&obuf, l>>16);
+ Bputc(&obuf, l>>24);
+ break;
+
+ case D_SCONST:
+ n = a->sval;
+ for(i=0; i<NSNAME; i++) {
+ Bputc(&obuf, *n);
+ n++;
+ }
+ break;
+
+ case D_FCONST:
+ ieeedtod(&e, a->dval);
+ Bputc(&obuf, e.l);
+ Bputc(&obuf, e.l>>8);
+ Bputc(&obuf, e.l>>16);
+ Bputc(&obuf, e.l>>24);
+ Bputc(&obuf, e.h);
+ Bputc(&obuf, e.h>>8);
+ Bputc(&obuf, e.h>>16);
+ Bputc(&obuf, e.h>>24);
+ break;
+ }
+}
+
+void
+outcode(int a, Gen *g1, int reg, Gen *g2)
+{
+ int sf, st, t;
+ Sym *s;
+
+ if(pass == 1)
+ goto out;
+jackpot:
+ sf = 0;
+ s = g1->sym;
+ while(s != S) {
+ sf = s->sym;
+ if(sf < 0 || sf >= NSYM)
+ sf = 0;
+ t = g1->name;
+ if(h[sf].type == t)
+ if(h[sf].sym == s)
+ break;
+ zname(s->name, t, sym);
+ s->sym = sym;
+ h[sym].sym = s;
+ h[sym].type = t;
+ sf = sym;
+ sym++;
+ if(sym >= NSYM)
+ sym = 1;
+ break;
+ }
+ st = 0;
+ s = g2->sym;
+ while(s != S) {
+ st = s->sym;
+ if(st < 0 || st >= NSYM)
+ st = 0;
+ t = g2->name;
+ if(h[st].type == t)
+ if(h[st].sym == s)
+ break;
+ zname(s->name, t, sym);
+ s->sym = sym;
+ h[sym].sym = s;
+ h[sym].type = t;
+ st = sym;
+ sym++;
+ if(sym >= NSYM)
+ sym = 1;
+ if(st == sf)
+ goto jackpot;
+ break;
+ }
+ Bputc(&obuf, a);
+ Bputc(&obuf, reg|nosched);
+ Bputc(&obuf, lineno);
+ Bputc(&obuf, lineno>>8);
+ Bputc(&obuf, lineno>>16);
+ Bputc(&obuf, lineno>>24);
+ zaddr(g1, sf);
+ zaddr(g2, st);
+
+out:
+ if(a != AGLOBL && a != ADATA)
+ pc++;
+}
+
+void
+outhist(void)
+{
+ Gen g;
+ Hist *h;
+ char *p, *q, *op, c;
+ int n;
+
+ g = nullgen;
+ c = pathchar();
+ 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[1] == ':') {
+ op = p;
+ p = pathname+2;
+ c = *p;
+ } else if(pathname[0] == c){
+ op = p;
+ p = pathname;
+ }
+ }
+ while(p) {
+ q = strchr(p, c);
+ if(q) {
+ n = q-p;
+ if(n == 0){
+ n = 1; /* leading "/" */
+ *p = '/'; /* don't emit "\" on windows */
+ }
+ q++;
+ } else {
+ n = strlen(p);
+ q = 0;
+ }
+ if(n) {
+ Bputc(&obuf, ANAME);
+ Bputc(&obuf, D_FILE); /* type */
+ Bputc(&obuf, 1); /* sym */
+ Bputc(&obuf, '<');
+ Bwrite(&obuf, p, n);
+ Bputc(&obuf, 0);
+ }
+ p = q;
+ if(p == 0 && op) {
+ p = op;
+ op = 0;
+ }
+ }
+ g.offset = h->offset;
+
+ Bputc(&obuf, AHISTORY);
+ Bputc(&obuf, 0);
+ Bputc(&obuf, h->line);
+ Bputc(&obuf, h->line>>8);
+ Bputc(&obuf, h->line>>16);
+ Bputc(&obuf, h->line>>24);
+ zaddr(&nullgen, 0);
+ zaddr(&g, 0);
+ }
+}
+
+#include "../cc/lexbody"
+#include "../cc/macbody"
+#include "../cc/compat"
diff --git a/sys/src/cmd/va/mkfile b/sys/src/cmd/va/mkfile
new file mode 100755
index 000000000..170c66b89
--- /dev/null
+++ b/sys/src/cmd/va/mkfile
@@ -0,0 +1,19 @@
+</$objtype/mkfile
+
+TARG=va
+OFILES=\
+ y.tab.$O\
+ lex.$O\
+
+HFILES=\
+ ../vc/v.out.h\
+ y.tab.h\
+ a.h\
+
+YFILES=a.y\
+
+BIN=/$objtype/bin
+< /sys/src/cmd/mkone
+YFLAGS=-D1 -d
+
+lex.$O: ../cc/macbody ../cc/lexbody ../cc/compat