📄 na.y
字号:
/* 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 + -