summaryrefslogtreecommitdiff
path: root/sys/src/cmd/7a
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/7a
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/7a')
-rwxr-xr-xsys/src/cmd/7a/a.h208
-rwxr-xr-xsys/src/cmd/7a/a.y537
-rwxr-xr-xsys/src/cmd/7a/lex.c694
-rwxr-xr-xsys/src/cmd/7a/mkfile19
4 files changed, 1458 insertions, 0 deletions
diff --git a/sys/src/cmd/7a/a.h b/sys/src/cmd/7a/a.h
new file mode 100755
index 000000000..bb44001a2
--- /dev/null
+++ b/sys/src/cmd/7a/a.h
@@ -0,0 +1,208 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "../7c/7.out.h"
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#define MAXALIGN 7
+
+typedef struct Sym Sym;
+typedef struct Ref Ref;
+typedef struct Gen Gen;
+typedef struct Io Io;
+typedef struct Hist Hist;
+
+#define FPCHIP 1
+#define NSYMB 500
+#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
+
+#define ALLOC(lhs, type)\
+ while(nhunk < sizeof(type))\
+ gethunk();\
+ lhs = (type*)hunk;\
+ nhunk -= sizeof(type);\
+ hunk += sizeof(type);
+
+#define ALLOCN(lhs, len, n)\
+ if(lhs+len != hunk || nhunk < n) {\
+ while(nhunk <= len)\
+ gethunk();\
+ memmove(hunk, lhs, len);\
+ lhs = hunk;\
+ hunk += len;\
+ nhunk -= len;\
+ }\
+ hunk += n;\
+ nhunk -= n;
+
+struct Sym
+{
+ Sym* link;
+ Ref* ref;
+ char* macro;
+ vlong value;
+ long dummy_pad;
+ ushort type;
+ char *name;
+ char sym;
+};
+#define S ((Sym*)0)
+
+struct Ref
+{
+ int class;
+};
+
+struct
+{
+ char* p;
+ int c;
+} fi;
+
+struct Io
+{
+ Io* link;
+ char b[BUFSIZ];
+ char* p;
+ short c;
+ short f;
+};
+#define I ((Io*)0)
+
+struct
+{
+ Sym* sym;
+ short type;
+} h[NSYM];
+
+struct Gen
+{
+ Sym* sym;
+ vlong offset;
+ long dummy_pad;
+ short type;
+ short reg;
+ short name;
+ double dval;
+ char sval[8];
+};
+
+struct Hist
+{
+ Hist* link;
+ char* name;
+ long line;
+ vlong offset;
+};
+#define H ((Hist*)0)
+
+enum
+{
+ CLAST,
+ CMACARG,
+ CMACRO,
+ CPREPROC,
+};
+
+char debug[256];
+Sym* hash[NHASH];
+char* Dlist[30];
+int nDlist;
+Hist* ehist;
+int newflag;
+Hist* hist;
+char* hunk;
+char* include[NINCLUDE];
+Io* iofree;
+Io* ionext;
+Io* iostack;
+long lineno;
+int nerrors;
+long nhunk;
+int ninclude;
+Gen nullgen;
+char* outfile;
+int pass;
+char* pathname;
+vlong pc;
+int peekc;
+int sym;
+char symb[NSYMB];
+int thechar;
+char* thestring;
+long thunk;
+Biobuf obuf;
+
+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/7a/a.y b/sys/src/cmd/7a/a.y
new file mode 100755
index 000000000..8e0565032
--- /dev/null
+++ b/sys/src/cmd/7a/a.y
@@ -0,0 +1,537 @@
+%{
+#include "a.h"
+%}
+%union
+{
+ Sym *sym;
+ vlong 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 LPREG LPCC
+%token <lval> LTYPEX LREG LFREG LFPCR LR LP LF
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr pointer offset sreg
+%type <gen> gen vgen lgen vlgen flgen rel reg freg preg fcreg
+%type <gen> imm ximm ireg name oreg imr nireg fgen pcc
+%%
+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;
+ }
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+/*
+ * Integer operates
+ */
+ LTYPE1 imr ',' sreg ',' reg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LTYPE1 imr ',' reg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * floating-type
+ */
+| LTYPE2 freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPE3 freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPE3 freg ',' LFREG ',' freg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * MOVQ
+ */
+| LTYPE4 vlgen ',' vgen
+ {
+ if(!isreg(&$2) && !isreg(&$4))
+ print("one side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * integer LOAD/STORE, but not MOVQ
+ */
+| LTYPE5 lgen ',' gen
+ {
+ if(!isreg(&$2) && !isreg(&$4))
+ print("one side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * integer LOAD/STORE (only)
+ */
+| LTYPE6 oreg ',' reg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPEK reg ',' oreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * floating LOAD/STORE
+ */
+| LTYPE7 flgen ',' fgen
+ {
+ if(!isreg(&$2) && !isreg(&$4))
+ print("one side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * JMP/JSR/RET
+ */
+| LTYPE8 comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE8 comma nireg
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LTYPE8 sreg ',' nireg
+ {
+ outcode($1, &nullgen, $2, &$4);
+ }
+| LTYPE9 comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+/*
+ * integer conditional branches
+ */
+| LTYPEA gen ',' rel
+ {
+ if(!isreg(&$2))
+ print("left side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * floating conditional branches
+ */
+| LTYPEB fgen ',' rel
+ {
+ if(!isreg(&$2))
+ print("left side must be register\n");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * TRAPB/MB/REI
+ */
+| LTYPEC comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+/*
+ * FETCH/FETCHM
+ */
+| LTYPED ireg comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+/*
+ * Call-pal
+ */
+| LTYPEE imm
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+/*
+ * TEXT/GLOBL
+ */
+| LTYPEF name ',' imm
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTYPEF name ',' con ',' imm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * DATA
+ */
+| LTYPEG name '/' con ',' ximm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * 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);
+ }
+
+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
+| preg
+| pcc
+
+vgen:
+ gen
+| preg
+
+lgen:
+ gen
+| ximm
+
+flgen:
+ fgen
+| ximm
+
+fgen:
+ gen
+| freg
+| fcreg
+
+preg:
+ LPREG
+ {
+ $$ = nullgen;
+ $$.type = D_PREG;
+ $$.reg = $1;
+ }
+| LP '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_PREG;
+ $$.reg = $1+$3;
+ }
+
+fcreg:
+ LFPCR
+ {
+ $$ = nullgen;
+ $$.type = D_FCREG;
+ $$.reg = $1;
+ }
+
+freg:
+ LFREG
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $1;
+ }
+| LF '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $3;
+ }
+
+pcc:
+ LPCC
+ {
+ $$ = nullgen;
+ $$.type = D_PCC;
+ $$.reg = $1;
+ }
+
+ximm: '$' con
+ {
+ $$ = nullgen;
+ $$.type = D_CONST;
+ $$.offset = $2;
+ }
+| '$' oreg
+ {
+ $$ = $2;
+ $$.type = D_CONST;
+ }
+| '$' 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
+| 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/7a/lex.c b/sys/src/cmd/7a/lex.c
new file mode 100755
index 000000000..30cfd2417
--- /dev/null
+++ b/sys/src/cmd/7a/lex.c
@@ -0,0 +1,694 @@
+#include <ctype.h>
+#define EXTERN
+#include "a.h"
+#include "y.tab.h"
+
+void
+main(int argc, char *argv[])
+{
+ char ofile[100], incfile[20], *p;
+ int nout, nproc, status, i, c, of;
+
+ thechar = '7'; /* of 9 */
+ thestring = "alpha";
+ 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();
+ if(p)
+ include[ninclude++] = p;
+ break;
+ } ARGEND
+ if(*argv == 0) {
+ print("usage: %ca [-options] file.s\n", thechar);
+ errorexit();
+ }
+ nproc = 3;
+ if(p = getenv("NPROC"))
+ nproc = atol(p);
+ if(argc > 1) {
+ c = 0;
+ nout = 0;
+ for(;;) {
+ while(nout < nproc && argc > 0) {
+ i = fork();
+ if(i < 0) {
+ i = mywait(&status);
+ if(i < 0)
+ errorexit();
+ if(status)
+ c++;
+ nout--;
+ continue;
+ }
+ if(i == 0) {
+ print("%s:\n", *argv);
+ goto child;
+ }
+ nout++;
+ argc--;
+ argv++;
+ }
+ i = mywait(&status);
+ if(i < 0) {
+ if(c)
+ errorexit();
+ exits(0);
+ }
+ if(status)
+ c++;
+ nout--;
+ }
+ }
+
+child:
+ strecpy(ofile, ofile+sizeof ofile, *argv);
+ if(p = strrchr(ofile, '/')) {
+ include[0] = ofile;
+ *p++ = 0;
+ } else
+ p = ofile;
+ if(outfile == 0) {
+ outfile = p;
+ if(p = strrchr(outfile, '.'))
+ if(p[1] == 's' && p[2] == 0)
+ p[0] = 0;
+ p = strrchr(outfile, 0);
+ p[0] = '.';
+ p[1] = thechar;
+ p[2] = 0;
+ }
+ if(0) {
+ strcpy(incfile, "/usr/%include");
+ p = strrchr(incfile, '%');
+ if(p)
+ *p = thechar;
+ } else {
+ strcpy(incfile, "/");
+ strcat(incfile, thestring);
+ strcat(incfile, "/include");
+ }
+ include[ninclude++] = incfile;
+ if(p = getenv("INCLUDE"))
+ include[ninclude-1] = p; /* */
+ of = mycreat(outfile, 0664);
+ if(of < 0) {
+ yyerror("%ca: cannot create %s", thechar, outfile);
+ errorexit();
+ }
+ Binit(&obuf, of, OWRITE);
+
+ pass = 1;
+ pinit(*argv);
+ for(i=0; i<nDlist; i++)
+ dodefine(Dlist[i]);
+ yyparse();
+ if(nerrors) {
+ cclean();
+ errorexit();
+ }
+
+ pass = 2;
+ outhist();
+ pinit(*argv);
+ for(i=0; i<nDlist; i++)
+ dodefine(Dlist[i]);
+ yyparse();
+ cclean();
+ if(nerrors)
+ errorexit();
+ exits(0);
+}
+
+struct
+{
+ char *name;
+ ushort type;
+ ushort value;
+} itab[] =
+{
+ "SP", LSP, D_AUTO,
+ "SB", LSB, D_EXTERN,
+ "FP", LFP, D_PARAM,
+ "PC", LPC, D_BRANCH,
+
+ "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,
+
+ "P", LP, 0,
+ "I", LP, 32,
+ "A", LP, 64,
+ "IA", LP, 96,
+ "T", LP, 128,
+ "IT", LP, 32+128,
+ "AT", LP, 64+128,
+ "IAT", LP, 96+128,
+ "T0", LPREG, 0+128,
+ "T1", LPREG, 1+128,
+ "T2", LPREG, 2+128,
+ "T3", LPREG, 3+128,
+ "T4", LPREG, 4+128,
+ "T5", LPREG, 5+128,
+ "T6", LPREG, 6+128,
+ "T7", LPREG, 7+128,
+ "T8", LPREG, 8+128,
+ "T9", LPREG, 9+128,
+ "T10", LPREG, 10+128,
+ "T11", LPREG, 11+128,
+ "T12", LPREG, 12+128,
+ "T13", LPREG, 13+128,
+ "T14", LPREG, 14+128,
+ "T15", LPREG, 15+128,
+ "T16", LPREG, 16+128,
+ "T17", LPREG, 17+128,
+ "T18", LPREG, 18+128,
+ "T19", LPREG, 19+128,
+ "T20", LPREG, 20+128,
+ "T21", LPREG, 21+128,
+ "T22", LPREG, 22+128,
+ "T23", LPREG, 23+128,
+ "T24", LPREG, 24+128,
+ "T25", LPREG, 25+128,
+ "T26", LPREG, 26+128,
+ "T27", LPREG, 27+128,
+ "T28", LPREG, 28+128,
+ "T29", LPREG, 29+128,
+ "T30", LPREG, 30+128,
+ "T31", LPREG, 31+128,
+
+ "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,
+
+ "FPCR", LFPCR, 0,
+ "PCC", LPCC, 0,
+
+ /* 1: integer operates */
+ "ADDQ", LTYPE1, AADDQ,
+ "ADDL", LTYPE1, AADDL,
+ "SUBL", LTYPE1, ASUBL,
+ "SUBQ", LTYPE1, ASUBQ,
+ "CMPEQ", LTYPE1, ACMPEQ,
+ "CMPGT", LTYPE1, ACMPGT,
+ "CMPGE", LTYPE1, ACMPGE,
+ "CMPUGT", LTYPE1, ACMPUGT,
+ "CMPUGE", LTYPE1, ACMPUGE,
+ "CMPBLE", LTYPE1, ACMPBLE,
+
+ "AND", LTYPE1, AAND,
+ "ANDNOT", LTYPE1, AANDNOT,
+ "OR", LTYPE1, AOR,
+ "ORNOT", LTYPE1, AORNOT,
+ "XOR", LTYPE1, AXOR,
+ "XORNOT", LTYPE1, AXORNOT,
+
+ "CMOVEQ", LTYPE1, ACMOVEQ,
+ "CMOVNE", LTYPE1, ACMOVNE,
+ "CMOVLT", LTYPE1, ACMOVLT,
+ "CMOVGE", LTYPE1, ACMOVGE,
+ "CMOVLE", LTYPE1, ACMOVLE,
+ "CMOVGT", LTYPE1, ACMOVGT,
+ "CMOVLBS", LTYPE1, ACMOVLBS,
+ "CMOVLBC", LTYPE1, ACMOVLBC,
+
+ "MULL", LTYPE1, AMULL,
+ "MULQ", LTYPE1, AMULQ,
+ "UMULH", LTYPE1, AUMULH,
+ "DIVQ", LTYPE1, ADIVQ,
+ "MODQ", LTYPE1, AMODQ,
+ "DIVQU", LTYPE1, ADIVQU,
+ "MODQU", LTYPE1, AMODQU,
+ "DIVL", LTYPE1, ADIVL,
+ "MODL", LTYPE1, AMODL,
+ "DIVLU", LTYPE1, ADIVLU,
+ "MODLU", LTYPE1, AMODLU,
+
+ "SLLQ", LTYPE1, ASLLQ,
+ "SRLQ", LTYPE1, ASRLQ,
+ "SRAQ", LTYPE1, ASRAQ,
+
+ "SLLL", LTYPE1, ASLLL,
+ "SRLL", LTYPE1, ASRLL,
+ "SRAL", LTYPE1, ASRAL,
+
+ "EXTBL", LTYPE1, AEXTBL,
+ "EXTWL", LTYPE1, AEXTWL,
+ "EXTLL", LTYPE1, AEXTLL,
+ "EXTQL", LTYPE1, AEXTQL,
+ "EXTWH", LTYPE1, AEXTWH,
+ "EXTLH", LTYPE1, AEXTLH,
+ "EXTQH", LTYPE1, AEXTQH,
+
+ "INSBL", LTYPE1, AINSBL,
+ "INSWL", LTYPE1, AINSWL,
+ "INSLL", LTYPE1, AINSLL,
+ "INSQL", LTYPE1, AINSQL,
+ "INSWH", LTYPE1, AINSWH,
+ "INSLH", LTYPE1, AINSLH,
+ "INSQH", LTYPE1, AINSQH,
+
+ "MSKBL", LTYPE1, AMSKBL,
+ "MSKWL", LTYPE1, AMSKWL,
+ "MSKLL", LTYPE1, AMSKLL,
+ "MSKQL", LTYPE1, AMSKQL,
+ "MSKWH", LTYPE1, AMSKWH,
+ "MSKLH", LTYPE1, AMSKLH,
+ "MSKQH", LTYPE1, AMSKQH,
+
+ "ZAP", LTYPE1, AZAP,
+ "ZAPNOT", LTYPE1, AZAPNOT,
+
+ /* 2: floating operates with 2 operands */
+ "CVTQS", LTYPE2, ACVTQS,
+ "CVTQT", LTYPE2, ACVTQT,
+ "CVTTS", LTYPE2, ACVTTS,
+ "CVTTQ", LTYPE2, ACVTTQ,
+ "CVTLQ", LTYPE2, ACVTLQ,
+ "CVTQL", LTYPE2, ACVTQL,
+
+ /* 3: floating operates with 2 or 3 operands */
+ "CPYS", LTYPE3, ACPYS,
+ "CPYSN", LTYPE3, ACPYSN,
+ "CPYSE", LTYPE3, ACPYSE,
+ "ADDS", LTYPE3, AADDS,
+ "ADDT", LTYPE3, AADDT,
+ "CMPTEQ", LTYPE3, ACMPTEQ,
+ "CMPTGT", LTYPE3, ACMPTGT,
+ "CMPTGE", LTYPE3, ACMPTGE,
+ "CMPTUN", LTYPE3, ACMPTUN,
+ "DIVS", LTYPE3, ADIVS,
+ "DIVT", LTYPE3, ADIVT,
+ "MULS", LTYPE3, AMULS,
+ "MULT", LTYPE3, AMULT,
+ "SUBS", LTYPE3, ASUBS,
+ "SUBT", LTYPE3, ASUBT,
+ "FCMOVEQ", LTYPE3, AFCMOVEQ,
+ "FCMOVNE", LTYPE3, AFCMOVNE,
+ "FCMOVLT", LTYPE3, AFCMOVLT,
+ "FCMOVGE", LTYPE3, AFCMOVGE,
+ "FCMOVLE", LTYPE3, AFCMOVLE,
+ "FCMOVGT", LTYPE3, AFCMOVGT,
+
+ /* 4: integer load/store and reg->reg (incl special regs) */
+ "MOVQ", LTYPE4, AMOVQ,
+
+ /* 5: integer load/store and reg->reg */
+ "MOVL", LTYPE5, AMOVL,
+ "MOVQU", LTYPE5, AMOVQU,
+ "MOVB", LTYPE5, AMOVB,
+ "MOVBU", LTYPE5, AMOVBU,
+ "MOVW", LTYPE5, AMOVW,
+ "MOVWU", LTYPE5, AMOVWU,
+ "MOVLP", LTYPE5, AMOVLP,
+ "MOVQP", LTYPE5, AMOVQP,
+
+ /* 6: integer load/store (only) */
+ "MOVA", LTYPE6, AMOVA,
+ "MOVAH", LTYPE6, AMOVAH,
+ "MOVLL", LTYPE6, AMOVLL,
+ "MOVQL", LTYPE6, AMOVQL,
+ "MOVLC", LTYPEK, AMOVLC,
+ "MOVQC", LTYPEK, AMOVQC,
+
+ /* 7: floating load/store and reg->reg */
+ "MOVS", LTYPE7, AMOVS,
+ "MOVT", LTYPE7, AMOVT,
+
+ /* 8,9: jumps */
+ "JMP", LTYPE8, AJMP,
+ "JSR", LTYPE8, AJSR,
+ "RET", LTYPE9, ARET,
+
+ /* A: integer conditional branches */
+ "BEQ", LTYPEA, ABEQ,
+ "BNE", LTYPEA, ABNE,
+ "BLT", LTYPEA, ABLT,
+ "BGE", LTYPEA, ABGE,
+ "BLE", LTYPEA, ABLE,
+ "BGT", LTYPEA, ABGT,
+ "BLBC", LTYPEA, ABLBC,
+ "BLBS", LTYPEA, ABLBS,
+
+ /* B: floating conditional branches */
+ "FBEQ", LTYPEB, AFBEQ,
+ "FBNE", LTYPEB, AFBNE,
+ "FBLT", LTYPEB, AFBLT,
+ "FBGE", LTYPEB, AFBGE,
+ "FBLE", LTYPEB, AFBLE,
+ "FBGT", LTYPEB, AFBGT,
+
+ /* C-J: miscellaneous */
+ "TRAPB", LTYPEC, ATRAPB,
+ "MB", LTYPEC, AMB,
+ "REI", LTYPEC, AREI,
+ "END", LTYPEC, AEND,
+ "FETCH", LTYPED, AFETCH,
+ "FETCHM", LTYPED, AFETCHM,
+ "CALL_PAL", LTYPEE, ACALL_PAL,
+ "TEXT", LTYPEF, ATEXT,
+ "GLOBL", LTYPEF, AGLOBL,
+ "DATA", LTYPEG, ADATA,
+ "WORD", LTYPEH, AWORD,
+ "NOP", LTYPEI, ANOP,
+ 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;
+ }
+
+ ALLOCN(pathname, 0, 100);
+ if(getwd(pathname, 99) == 0) {
+ ALLOCN(pathname, 100, 900);
+ if(getwd(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)
+{
+ vlong 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_PREG:
+ case D_FCREG:
+ case D_PCC:
+ break;
+
+ case D_OREG:
+ case D_CONST:
+ case D_BRANCH:
+ l = a->offset;
+ Bputc(&obuf, l);
+ Bputc(&obuf, l>>8);
+ Bputc(&obuf, l>>16);
+ Bputc(&obuf, l>>24);
+ Bputc(&obuf, l>>32);
+ Bputc(&obuf, l>>40);
+ Bputc(&obuf, l>>48);
+ Bputc(&obuf, l>>56);
+ 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);
+ 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;
+ int n;
+
+ g = nullgen;
+ for(h = hist; h != H; h = h->link) {
+ p = h->name;
+ op = 0;
+ if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
+ op = p;
+ p = pathname;
+ }
+ while(p) {
+ q = strchr(p, '/');
+ if(q) {
+ n = q-p;
+ if(n == 0)
+ n = 1; /* leading "/" */
+ 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/7a/mkfile b/sys/src/cmd/7a/mkfile
new file mode 100755
index 000000000..e48fbea48
--- /dev/null
+++ b/sys/src/cmd/7a/mkfile
@@ -0,0 +1,19 @@
+</$objtype/mkfile
+
+TARG=7a
+OFILES=\
+ y.tab.$O\
+ lex.$O\
+
+HFILES=\
+ ../7c/7.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