⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 na.y

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 Y
📖 第 1 页 / 共 2 页
字号:
/* NCR53c8xx assembler */%{#include <u.h>#include <libc.h>#include <stdio.h>#include <ctype.h>#include "na.h"#define COND_WAIT (1L << 16)#define COND_TRUE (1L << 19)#define COND_INTFLY (1L << 20)#define COND_CARRY (1L << 21)#define COND_REL (1L << 23)#define COND_PHASE (1L << 17)#define COND_DATA (1L << 18)#define IO_REL (1L << 26)#define MOVE_MODE (1L << 27)int yylex(void);int yyparse(void);void assemble(void);void yyerror(char *, ...);void yywarn(char *, ...);void p2error(int line, char *);struct addr {	int type; /* 0 - direct, 1 - indirect 2 - table indirect */	unsigned long offset;};typedef enum Type { Const, Addr, Table, Extern, Reg, Unknown, Error } Type;struct sym {	char *name;	int set;	Type t;	long value;	struct sym *next;};struct sym *findsym(char *name);struct sym *symlist;void newsym(struct sym *s, Type t, long v);struct binary {	char len;	unsigned long data[3];	unsigned char patch[3];};#define MAXCPPOPTS 30#define MAX_PATCHES 1000struct na_patch patch[MAX_PATCHES];int patches;struct binary out;struct expval {	Type t;	long value;};struct expval eval(struct expval a, struct expval b, char op);int patchtype(Type t);void fixup(void);unsigned dot;unsigned externs;int errors, warnings;struct sym *externp[100];void regmove(unsigned char src_reg, unsigned char op,    unsigned char dst_reg, struct expval *imm);void preprocess(char *in, FILE *out);int mk24bitssigned(long *l);long mkreladdr(long value, int len);long chkreladdr(int d, struct expval *e, int len, long relrv);int pass2;FILE *in_f;int yyline = 0;char yyfilename[200];char line[500];char *cppopts[MAXCPPOPTS];int ncppopts;int wflag;%}%union {	long n;	struct sym *s;	struct expval e;}%token NUM MOVE WHEN SYMBOL SELECT WAIT DISCONNECT RESELECT SET CLEAR%token DATA_OUT DATA_IN COMMAND STATUS RESERVED_OUT RESERVED_IN MESSAGE_OUT%token MESSAGE_IN WITH ATN FAIL CARRY TARGET ACK COMMENT TO%token SCNTL0 SCNTL1 SCNTL2 SCNTL3 SCID SXFER SDID GPREG%token SFBR SOCL SSID SBCL DSTAT SSTAT0 SSTAT1 SSTAT2%token ISTAT CTEST0 CTEST1 CTEST2 CTEST3 TEMP DFIFO CTEST4 CTEST5 CTEST6%token DBC DCMD DNAD DSP DSPS DMODE DIEN DWT DCNTL ADDER%token SIEN0 SIEN1 SIST0 SIST1 SLPAR MACNTL GPCNTL STIME0 STIME1 RESPID%token STEST0 STEST1 STEST2 STEST3 SIDL SODL SBDL%token SHL SHR AND OR XOR ADD ADDC%token JUMP CALL RETURN INT INTFLY NOT ABSOLUTE MASK IF REL PTR%token TABLE FROM MEMORY NOP EXTERN%token SCRATCHA0 SCRATCHA1 SCRATCHA2 SCRATCHA3%token SCRATCHB0 SCRATCHB1 SCRATCHB2 SCRATCHB3%token SCRATCHC0 SCRATCHC1 SCRATCHC2 SCRATCHC3%token DSA0 DSA1 DSA2 DSA3%token DEFW%left '-' '+'%left '*' '/'%left NEG     /* negation--unary minus */%right '^'    /* exponentiation        */%type <n> NUM phase .atn set_list set_bit regA reg%type <n> set_cmd .cond condsfbr condphase%type <n> jump_or_call .ptr%type <s> SYMBOL%type <e> exp byteexp regexp/* Grammar follows */%%input:    /* empty string */        | input line;line:	.label .opcode .comment '\n'	{		if (pass2) {			int x;			for (x = 0; x < out.len; x++) {				printf("/* %.4x */ 0x%.8lxL,",				    dot, out.data[x]);				if (x == 0) {					printf(" /*\t");					fwrite(line,					    strlen(line) - 1, 1, stdout);					printf(" */");				}				printf("\n");				if (out.patch[x]) {					patch[patches].lwoff = dot / 4;					patch[patches].type = out.patch[x];					patches++;				}				dot += 4;			}		}		else			dot += 4 * out.len;	}	| ABSOLUTE SYMBOL '=' exp .comment '\n'	{		setsym($2, $4.t, $4.value);		if (pass2) {			printf("\t\t\t/*\t");			fwrite(line, strlen(line) - 1, 1, stdout);			printf(" */\n");		}	}	| SYMBOL '=' exp .comment '\n'	{		setsym($1, $3.t, $3.value);		if (pass2) {			printf("\t\t\t/*\t");			fwrite(line, strlen(line) - 1, 1, stdout);			printf(" */\n");		}	}	| EXTERN SYMBOL {		if (pass2) {			printf("\t\t\t/*\t");			fwrite(line, strlen(line) - 1, 1, stdout);			printf(" */\n");		}		else {			if (!pass2)				externp[externs] = $2;			setsym($2, Extern, externs++);		}	}	;.comment: COMMENT	| /* nothing */	;.label:	SYMBOL ':' {		if ($1->t != Unknown)		{			if (!pass2)				yyerror("multiply defined symbol");		}		else {			$1->t = Addr;			$1->value = dot;		}	}	| /* nothing */	;set_cmd: SET { $$ = 3; }	| CLEAR { $$ = 4; }	;set_bit: CARRY { $$ = 0x400; }	| TARGET { $$ = 0x200; }	| ACK { $$ = 0x40; }	| ATN { $$ = 0x8; }	;	set_list: set_list ',' set_bit { $$ = $1 | $3; }	| set_list AND set_bit { $$ = $1 | $3; }	| set_bit { $$ = $1; }	;opcode: set_cmd set_list {		out.len = 2;		out.data[0] = (1L << 30) | ((long)$1 << 27) | $2;		out.data[1] = 0;		out.patch[0] = out.patch[1] = 0;	}	| DISCONNECT	{		out.len = 2;		out.data[0] = 0x48020000L;		out.data[1] = 0;		out.patch[0] = out.patch[1] = 0;	}	| INT exp .cond {		out.len = 2;		out.data[0] = $3 | 0x98000000L;		out.data[1] = $2.value;		out.patch[0] = out.patch[1] = 0;	}	| INTFLY exp .cond {		out.len = 2;		out.data[0] = $3 | 0x98000000L | COND_INTFLY;		out.data[1] = $2.value;		out.patch[0] = out.patch[1] = 0;	}	| jump_or_call exp .cond {		out.len = 2;		out.data[0] = $1 | $3 | chkreladdr(1, &$2, 2, COND_REL);		out.patch[0] = 0;	}	| jump_or_call REL '(' exp ')' .cond {		out.len = 2;		out.data[0] = $1 | $6 | COND_REL;		out.data[1] = mkreladdr($4.value, 2);		out.patch[0] = out.patch[1] = 0;	}	| MOVE exp ',' .ptr regexp ',' with_or_when phase {		out.len = 2;		out.data[0] = ($8 << 24) | $2.value | ($4 << 29) | MOVE_MODE;		out.data[1] = $5.value;		out.patch[0] = 0;		out.patch[1] = patchtype($5.t);	}	| MOVE FROM exp ',' with_or_when phase {		out.len = 2;		out.data[0] = ($6 << 24) | (1L << 28) | MOVE_MODE;		out.data[1] = $3.value;		out.patch[0] = 0;		out.patch[1] = patchtype($3.t);	}	| MOVE MEMORY exp ',' regexp ',' regexp {		out.len = 3;		out.data[0] = 0xc0000000L | $3.value;		out.data[1] = $5.value;		out.data[2] = $7.value;		out.patch[0] = 0;		out.patch[1] = patchtype($5.t);		out.patch[2] = patchtype($7.t);	}	| MOVE regA TO regA		{ regmove($2, 2, $4, 0); }	/* do reg to sfbr moves using or 0 */	| MOVE exp TO regA		{ regmove($4, 0, $4, &$2); }	| MOVE regA '|' exp TO regA	{ regmove($2, 2, $6, &$4); }	| MOVE regA '&' exp TO regA	{ regmove($2, 4, $6, &$4); }	| MOVE regA '+' exp TO regA	{ regmove($2, 6, $6, &$4); }	| MOVE regA '-' exp TO regA	{ regmove($2, 6, $6, &$4); }	| MOVE regA '+' exp TO regA WITH CARRY	{		regmove($2, 7, $6, &$4);	}	| MOVE regA '-' exp TO regA WITH CARRY	{		$4.value = -$4.value;		regmove($2, 7, $6, &$4);	}	| MOVE regA SHL TO regA		{ regmove($2, 1, $5, 0); }	| MOVE regA SHR TO regA		{ regmove($2, 5, $5, 0); }	| MOVE regA XOR exp TO regA	{ regmove($2, 3, $6, &$4); }	| NOP {		out.len = 2;		out.data[0] = 0x80000000L;		out.data[1] = 0;		out.patch[0] = out.patch[1] = 0;	}	| RESELECT exp ',' exp {		out.len = 2;		out.data[0] = 0x40000000L | ((long)$2.value << 16) | (1L << 9) | chkreladdr(1, &$4, 2, IO_REL);		out.patch[0] = 0;	}	| RESELECT exp ',' REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x40000000L | IO_REL		    | ((long)$2.value << 16) | (1L << 9);		out.data[1] = mkreladdr($6.value, 2);		out.patch[0] = out.patch[1] = 0;	}	| RESELECT FROM exp ',' exp {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 25) | $3.value | chkreladdr(1, &$5, 2, IO_REL);		out.patch[0] = 5;	}	| RESELECT FROM exp ',' REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $3.value;		out.patch[0] = 5;		out.data[1] = mkreladdr($7.value, 2);		out.patch[1] = 0;	}	| RETURN .cond {				out.len = 2;		out.data[0] = 0x90000000L | $2;		out.data[1] = 0;		out.patch[0] = out.patch[1] = 0;	}	| SELECT .atn exp ',' exp {		out.len = 2;		out.data[0] =		    0x40000000L | ((long)$3.value << 16) | (1L << 9) | $2 | chkreladdr(1, &$5, 2, IO_REL);		out.patch[0] = 0;	}	| SELECT .atn exp ',' REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 26)		    | ((long)$3.value << 16) | (1L << 9) | $2;		out.data[1] = mkreladdr($7.value, 2);		out.patch[0] = out.patch[1] = 0;	}	| SELECT .atn FROM exp ',' exp {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 25) | $4.value | $2 | chkreladdr(1, &$6, 2, IO_REL);		out.patch[0] = 5;	}	| SELECT .atn FROM exp ',' REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 25) | IO_REL | $4.value | $2;		out.patch[0] = 5;		out.data[1] = mkreladdr($8.value, 2);		out.patch[1] = 0;	}	| WAIT DISCONNECT {		out.len = 2;		out.data[0] = 0x48000000L;		out.data[1] = 0;		out.patch[0] = out.patch[1] = 0;	}	| WAIT RESELECT exp {		out.len = 2;		out.data[0] = 0x50000000L | chkreladdr(1, &$3, 2, IO_REL);		out.patch[0] = 0;	}	| WAIT RESELECT REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x50000000L | (1L << 26);		out.data[1] = mkreladdr($5.value, 2);		out.patch[0] = out.patch[1] = 0;	}	| WAIT SELECT exp {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 9) | chkreladdr(1, &$3, 2, IO_REL);		out.patch[0] = 0;	}	| WAIT SELECT REL '(' exp ')' {		out.len = 2;		out.data[0] = 0x40000000L | (1L << 26) | (1L << 9);		out.data[1] = mkreladdr($5.value, 2);		out.patch[0] = out.patch[1] = 0;	}	| DEFW exp {		out.len = 1;		out.data[0] = $2.value;		out.patch[0] = patchtype($2.t);	}	;.ptr:	PTR { $$ = 1; }	| { $$ = 0; }	;with_or_when: WITH	| WHEN	;	jump_or_call: JUMP	 { $$ = 0x80000000L; }	| CALL		 { $$ = 0x88000000L; }	;condsfbr: byteexp { $$ = $1.value | COND_DATA; }	| byteexp AND MASK byteexp { $$ = ($4.value << 8) | $1.value | COND_DATA; }	;condphase: phase { $$ = ($1 << 24) | COND_PHASE; }.cond:    ',' IF ATN { $$ = COND_TRUE; }	| ',' IF condphase { $$ = $3 | COND_TRUE; }	| ',' IF CARRY { $$ = COND_CARRY | COND_TRUE; }	| ',' IF condsfbr { $$ = $3 | COND_TRUE; }	| ',' IF ATN AND condsfbr { $$ = $5 | COND_TRUE; }	| ',' IF condphase AND condsfbr { $$ = $3 | $5 | COND_TRUE; }	| ',' WHEN condphase { $$ = $3 | COND_WAIT | COND_TRUE; }	| ',' WHEN CARRY { $$ = COND_CARRY | COND_WAIT | COND_TRUE; }	| ',' WHEN condsfbr { $$ = $3 | COND_WAIT | COND_TRUE; }	| ',' WHEN condphase AND condsfbr { $$ = $3 | $5 | COND_WAIT | COND_TRUE; }	| ',' IF NOT ATN { $$ = 0; }	| ',' IF NOT condphase { $$ = $4; }	| ',' IF NOT CARRY { $$ = COND_CARRY; }	| ',' IF NOT condsfbr { $$ = $4; }	| ',' IF NOT ATN OR condsfbr { $$ = $6; }	| ',' IF NOT condphase OR condsfbr { $$ = $4 | $6; }	| ',' WHEN NOT condphase { $$ = $4 | COND_WAIT; }	| ',' WHEN NOT CARRY { $$ = COND_CARRY | COND_WAIT; }	| ',' WHEN NOT condsfbr { $$ = $4 | COND_WAIT; }	| ',' WHEN NOT condphase OR condsfbr { $$ = $4 | $6 | COND_WAIT; }	| { $$ = COND_TRUE; }	;.opcode: opcode	| { out.len = 0; }	;regA:	reg	| SFBR { $$ = 8; }	;reg:	  SCNTL0	{ $$ = 0; }	| SCNTL1	{ $$ = 1; }	| SCNTL2	{ $$ = 2; }	| SCNTL3	{ $$ = 3; }	| SCID		{ $$ = 4; }	| SXFER		{ $$ = 5; }	| SDID		{ $$ = 6; }	| GPREG		{ $$ = 7; }	| SOCL		{ $$ = 9; }	| SSID		{ $$ = 0xa; }	| SBCL		{ $$ = 0xb; }	| DSTAT		{ $$ = 0xc; }	| SSTAT0	{ $$ = 0xd; }	| SSTAT1	{ $$ = 0xe; }	| SSTAT2	{ $$ = 0xf; }	| DSA0		{ $$ = 0x10; }	| DSA1		{ $$ = 0x11; }	| DSA2		{ $$ = 0x12; }	| DSA3		{ $$ = 0x13; }	| ISTAT		{ $$ = 0x14; }	| CTEST0	{ $$ = 0x18; }	| CTEST1	{ $$ = 0x19; }	| CTEST2	{ $$ = 0x1a; }	| CTEST3	{ $$ = 0x1b; }	| TEMP		{ $$ = 0x1c; }	| DFIFO		{ $$ = 0x20; }	| CTEST4	{ $$ = 0x21; }	| CTEST5	{ $$ = 0x22; }	| CTEST6	{ $$ = 0x23; }	| DBC		{ $$ = 0x24; }	| DCMD		{ $$ = 0x27; }	| DNAD		{ $$ = 0x28; }	| DSP		{ $$ = 0x2c; }	| DSPS		{ $$ = 0x30; }	| SCRATCHA0	{ $$ = 0x34; }	| SCRATCHA1	{ $$ = 0x35; }	| SCRATCHA2	{ $$ = 0x36; }	| SCRATCHA3	{ $$ = 0x37; }	| DMODE		{ $$ = 0x38; }	| DIEN		{ $$ = 0x39; }	| DWT		{ $$ = 0x3a; }	| DCNTL		{ $$ = 0x3b; }	| ADDER		{ $$ = 0x3c; }	| SIEN0		{ $$ = 0x40; }	| SIEN1		{ $$ = 0x41; }	| SIST0		{ $$ = 0x42; }	| SIST1		{ $$ = 0x43; }	| SLPAR		{ $$ = 0x44; }	| MACNTL	{ $$ = 0x46; }	| GPCNTL	{ $$ = 0x47; }	| STIME0	{ $$ = 0x48; }	| STIME1	{ $$ = 0x49; }	| RESPID	{ $$ = 0x4a; }	| STEST0	{ $$ = 0x4c; }	| STEST1	{ $$ = 0x4d; }	| STEST2	{ $$ = 0x4e; }	| STEST3	{ $$ = 0x4f; }	| SIDL		{ $$ = 0x50; }	| SODL		{ $$ = 0x54; }	| SBDL		{ $$ = 0x58; }	| SCRATCHB0	{ $$ = 0x5c; }	| SCRATCHB1	{ $$ = 0x5d; }	| SCRATCHB2	{ $$ = 0x5e; }	| SCRATCHB3	{ $$ = 0x5f; }	| SCRATCHC0	{ $$ = 0x60; }	| SCRATCHC1	{ $$ = 0x61; }	| SCRATCHC2	{ $$ = 0x62; }	| SCRATCHC3	{ $$ = 0x63; }	;.atn:	ATN		{ $$ = (1 << 24); }	| /* nothing */ { $$ = 0; };phase:	DATA_OUT 	{ $$ = 0; }	| DATA_IN	{ $$ = 1; }	| COMMAND 	{ $$ = 2; }	| STATUS	{ $$ = 3; }	| RESERVED_OUT 	{ $$ = 4; }	| RESERVED_IN	{ $$ = 5; }	| MESSAGE_OUT   { $$ = 6; }	| MESSAGE_IN	{ $$ = 7; };byteexp: exp	{		if (pass2 && ($1.value < 0 || $1.value > 255)) {			if (wflag)				yywarn("conversion causes truncation");			$$.value = $1.value & 0xff;		}		else			$$.value = $1.value;	}	;regexp:	exp	| regA { $$.t = Reg; $$.value = $1; }	;exp:	NUM { $$.t = Const; $$.value = $1; }	| SYMBOL {		$$.t = $1->t; $$.value = $1->value;		if (pass2 && $1->t == Unknown)		{			yyerror("Undefined symbol %s", $1->name);			$1->t = Error;			$1->value = 0;			$$.t = Error;			$$.value = 0;		}	}        | exp '+' exp { $$ = eval($1, $3, '+'); }        | exp '-' exp { $$ = eval($1, $3, '-'); }        | exp '*' exp { $$ = eval($1, $3, '*'); }        | exp '/' exp { $$ = eval($1, $3, '/'); }        | '-' exp  %prec NEG { $$ = eval($2, $2, '_'); }        | '(' exp ')'        { $$ = $2; }	| '~' exp %prec NEG { $$ = eval($2, $2, '~'); }	;%%struct {	char *name;	int tok;} toktab[] ={	{ "when", WHEN },	{ "data_out", DATA_OUT },	{ "data_in", DATA_IN },	{ "msg_out", MESSAGE_OUT },	{ "msg_in", MESSAGE_IN },	{ "cmd", COMMAND },	{ "command", COMMAND },	{ "status", STATUS },	{ "move", MOVE },	{ "select", SELECT },	{ "reselect", RESELECT },	{ "disconnect", DISCONNECT },	{ "wait", WAIT },	{ "set", SET },	{ "clear", CLEAR },	{ "with", WITH },	{ "atn", ATN },	{ "fail", FAIL },	{ "carry", CARRY },	{ "target", TARGET },	{ "ack", ACK },	{ "scntl0", SCNTL0 },	{ "scntl1", SCNTL1 },	{ "scntl2", SCNTL2 },	{ "scntl3", SCNTL3 },	{ "scid", SCID },	{ "sxfer", SXFER },	{ "sdid", SDID },

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -