%start list %{ #include "TIasm.h" #include #include "mio.h" short isbuf; /* A place to build object */ short lcctr = 0; /* The relocation counter */ extern int Ofd; /* The object file */ extern FILE *Sdvec[]; /* For doing our funny I/O */ extern char yytext[]; extern int yyleng; extern flag Ferror; extern flag Error; extern int Debug; %} %union { short val; /* Any old integer */ struct p { /* Pointer to a stab ent */ struct stab *pntr; flag enterd; } sinfo; struct infop opspec; /* Operand spec info */ } %token OPTYP1 1 %token OPTYP2 2 %token OPTYP3 3 %token OPTYP4 4 %token OPTYP5 5 %token OPTYP6 6 %token OPTYP7 7 %token OPTYP8 8 %token OPTYP9 9 %token OPTYP10 10 %token OPTYP11 11 %token STRINGDIR %token EXTNLDIR %token WORDDIR %token DATADIR %token REG %token IDENT %token STRING %token NUMBER %token ERROR %type mopnd %type pcrel %type indir %type iauto %type symbol %type isymb %type ident %% list : /* EMPTY */ { DEBUG (10, "list -> EMPTY\n", NULL); DEBUG (10, "lcctr = 0X%x\n", lcctr); } | list line { DEBUG (10, "list -> list line\n", NULL); DEBUG (10, "lcctr = 0X%x\n", lcctr); } | error { DEBUG (10, "list -> error\n", NULL); DEBUG (10, "lcctr = 0X%x\n", lcctr); } ; line : ident ':' { struct j_lst *tptr, *t2ptr; unsigned tmp; DEBUG (10, "line -> ident ':'\n", NULL); /* The ONLY place an address may be resolved is here */ if ($1.pntr->st_type & TYRSLVD) { yyerror ("Redeclaration error"); YYERROR; } $1.pntr->st_type |= TYRSLVD; $1.pntr->en_addr = lcctr; DEBUG (9, "Resolving \"%s\"", $1.pntr->st_symnm); DEBUG (9, " to addr 0X%x\n", $1.pntr->en_addr); /* Now resolve jumps and make these patches */ for (tptr = $1.pntr->en_jl; tptr != NULL; ) { DEBUG (9, "Resolving jumps, addr = 0x%x\n", tptr->j_addr); DEBUG (9, "0x%x - ", lcctr); DEBUG (9, "0x%x / 2 = ", tptr->j_addr); DEBUG (9, "0x%x\n", (lcctr - tptr->j_addr) / 2); /* We KNOW this is a forward reference so * we can just make the following subtraction. */ if ((tmp = (lcctr - tptr->j_addr) / 2) > 0x7f) { yyerror ("Jump target out of range"); } else { /* Offset size of execute header */ xseek (Ofd, (long )tptr->j_addr + sizeof(struct format) - 1, 0); xwrite (Ofd, tmp, 1); xseek (Ofd, (long )0, 2); } t2ptr = tptr; tptr = tptr->j_next; rmjinf (t2ptr); } /* It is possible to trip through the above loop * again. So...... */ $1.pntr->en_jl = NULL; } | stmnt { DEBUG (10, "line -> stmnt\n", NULL); } ; stmnt : OPTYP1 mopnd ',' mopnd { DEBUG (10, "stmnt -> OPTYP1 mopnd ',' mopnd\n", NULL); isbuf = $1.pntr->st_opc; /* Source */ isbuf |= ((0x3 & $2.t) << 4); isbuf |= (0xf & $2.r); /* Destination */ isbuf |= ((0x3 & $4.t) << 10); isbuf |= ((0xf & $4.r) << 6); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & SYMTAG) { if ($2.in_tag & RELOCATABLE) adrinf($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } if ($4.in_tag & SYMTAG) { if ($4.in_tag & RELOCATABLE) adrinf($4.in_stb, lcctr); lcctr += sizeof($4.in_loc); xwrite (Ofd, $4.in_loc, sizeof($4.in_loc)); } } | OPTYP2 pcrel { DEBUG (10, "fmt2 -> OPTYP2 pcrel\n", NULL); isbuf = $1.pntr->st_opc; isbuf |= (0xff & $2); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); } | OPTYP2 symbol { int tmp; DEBUG (10, "fmt2 -> OPTYP2 symbol\n", NULL); isbuf = $1.pntr->st_opc; if ($2.in_stb->st_type & TYRSLVD) { DEBUG (9, "fmt2: Label resolved do jump now\n", NULL); /* This reference is definately rearward * so the following is legal. */ tmp = ($2.in_stb->en_addr - lcctr - 2) / 2; if ( tmp < -0x7f) { yyerror ("Jump target out of range"); YYERROR; } else isbuf |= (0xff & (unsigned )tmp); } else { DEBUG (9, "fmt2: Not resolved, save addr\n", NULL); adjinf ($2.in_stb, lcctr + 1); } lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); } | OPTYP3 mopnd ',' REG { DEBUG (10, "fmt3 -> OPTYP3 mopnd ',' REG\n", NULL); isbuf = $1.pntr->st_opc; /* source */ isbuf |= ((0x3 & $2.t) << 4); isbuf |= (0xf & $2.r); /* Destination register */ isbuf |= ((0xf & $4) << 6); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & SYMTAG) { if ($2.in_tag & RELOCATABLE) adrinf($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } } | OPTYP4 mopnd ',' NUMBER { DEBUG (10, "fmt4 -> OPTYP4 mopnd ',' NUMBER\n", NULL); isbuf = $1.pntr->st_opc; /* Register */ isbuf |= ((0x3 & $2.t) << 4); isbuf |= (0xf & $2.r); /* count */ if ($4 < 0) { yyerror("transfer/shift count < 0"); YYERROR; } if ($4 > 0xf) { yyerror ("transfer/shift count > 0xf"); YYERROR; } isbuf |= ((0xf & $4) << 6); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & SYMTAG) { if ($2.in_tag & RELOCATABLE) adrinf($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } } | OPTYP5 REG ',' NUMBER { DEBUG (10, "fmt5 -> OPTYP5 REG ',' NUMBER\n", NULL); isbuf = $1.pntr->st_opc; /* register */ isbuf |= (0xf & $2); /* Count/shift */ if ($4 < 0) { yyerror("transfer/shift count < 0"); YYERROR; } if ($4 > 0xf) { yyerror("transfer/shift count > 0xf"); YYERROR; } isbuf |= ((0xf & $4) << 4); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); } | OPTYP6 mopnd { DEBUG (10, "fmt6 -> OPTYP6 mopnd\n", NULL); isbuf = $1.pntr->st_opc; /* Source */ isbuf |= ((0x3 & $2.t) << 4); isbuf |= (0xf & $2.r); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & SYMTAG) { if ($2.in_tag & RELOCATABLE) adrinf ($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } } | OPTYP7 { DEBUG (10, "fmt7 -> OPTYP7\n", NULL); isbuf = $1.pntr->st_opc; lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); } | OPTYP8 REG ',' symbol { DEBUG (10, "fmt8 -> OPTYP8 REG ',' symbol\n", NULL); isbuf = $1.pntr->st_opc; /* Destination */ isbuf |= (0xf & $2); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); /* Source */ if ($4.in_tag & RELOCATABLE) adrinf ($4.in_stb, lcctr); lcctr += sizeof($4.in_loc); xwrite (Ofd, $4.in_loc, sizeof($4.in_loc)); } | OPTYP9 mopnd ',' NUMBER { DEBUG (10, "OPTYP9 mopnd ',' NUM (%d)\n", $4); isbuf = $1.pntr->st_opc; /* Destination register */ isbuf |= ((0xf & $4) << 6); /* Source */ isbuf |= ((0x3 & $2.t) << 4); isbuf |= (0xf & $2.r); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & SYMTAG) { if ($2.in_tag & RELOCATABLE) /* Enter it to the list of addrs. * So, there is garbage in the slot; * We need to reserve space for the * patch anyway. Who cares what is in * there? */ adrinf($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } } | OPTYP10 symbol { DEBUG (10, "stmnt -> OPTYP10\n", NULL); isbuf = $1.pntr->st_opc; lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); if ($2.in_tag & RELOCATABLE) adrinf ($2.in_stb, lcctr); lcctr += sizeof($2.in_loc); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); } | OPTYP11 REG { DEBUG (10, "stmnt -> OPTYP11\n", NULL); isbuf = $1.pntr->st_opc; isbuf |= (0xf & $2); lcctr += sizeof(isbuf); xwrite (Ofd, isbuf, sizeof(isbuf)); } | dirctv { DEBUG (10, "stmnt -> dirctv\n", NULL); } ; dirctv : STRINGDIR STRING { char null = NULL; /* Will want address, so.... */ DEBUG (10, "dirctv -> STRINGDIR STRING\n", NULL); dostr (yytext, &yyleng); if (Error == TRUE) { yyerror ("Illegal meta-character(s) in string"); YYERROR; } lcctr += yyleng; /* The I/O macros force this..... BE CAREFUL if * you change them! */ xwrite (Ofd, yytext[0], yyleng); /* If odd length, then align */ if (odd(yyleng)) { lcctr += 1; xwrite (Ofd, null, 1); } } | EXTNLDIR ident { DEBUG (10, "dirctv -> EXTNLDIR ident\n", NULL); $2.pntr->st_type |= TYEXTID; } | WORDDIR NUMBER { short awrd; short x; DEBUG (10, "dirctv -> WORDDIR number\n", NULL); lcctr += $2 * 2; for (x = 0; x < $2; ++x) xwrite (Ofd, awrd, sizeof(awrd)); } | WORDDIR { short awrd; DEBUG (10, "dirctv -> WORDDIR\n", NULL); lcctr += 2; xwrite (Ofd, awrd, sizeof(awrd)); } | DATADIR symbol { DEBUG (10, "dirctv -> DATADIR symbol\n", NULL); xwrite (Ofd, $2.in_loc, sizeof($2.in_loc)); if ($2.in_tag & RELOCATABLE) adrinf ($2.in_stb, lcctr); lcctr += 2; } ; mopnd : REG { DEBUG (10, "mopnd -> REG\n", NULL); $$.t = 0; $$.r = $1; $$.in_tag &= ~SYMTAG; /* Paranoid */ } | iauto { DEBUG (10, "mopnd -> iauto\n", NULL); $$.t = 03; $$.r = $1; $$.in_tag &= ~SYMTAG; /* Paranoid */ } | isymb { DEBUG (10, "mopnd -> isymb\n", NULL); $$ = $1; $$.t = 02; /* Register to index off of is already set */ } | symbol { DEBUG (10, "mopnd -> symbol\n", NULL); $$ = $1; $$.t = 02; $$.r = 0; /* Force non-indexed */ } | indir { DEBUG (10, "mopnd -> indir\n", NULL); $$.t = 01; $$.r = $1; $$.in_tag &= ~SYMTAG; /* Paranoid */ } ; pcrel : '$' { DEBUG (10, "pcrel -> '$'\n", NULL); $$ = lcctr; } | '$' '+' NUMBER { DEBUG (10, "pcrel -> '$' '+' NUMBER\n", NULL); $$ = lcctr + $3; /* Check signed 8 bit jump range */ if (abs($$) > 0x7f) { yyerror ("Jump target out of range"); YYERROR; } } | '$' '-' NUMBER { DEBUG (10, "pcrel -> '$' '-' NUMBER\n", NULL); $$ = lcctr - $3; /* Check signed 8 bit jump range */ if (abs($$) > 0xff) { yyerror ("Jump out of range"); YYERROR; } } ; indir : '(' REG ')' { DEBUG (10, "indir -> '(' REG ')'\n", NULL); $$ = $2; } ; iauto : '(' REG ')' '+' { DEBUG (10, "iauto -> '(' REG ')' '+'\n", NULL); $$ = $2; } ; isymb : symbol '[' REG ']' { DEBUG (10, "isymb -> symbol '[' REG ']'\n", NULL); /* The identifier/absolute address */ $$ = $1; $$.r = $3; /* Change this field to reflect indexed */ } ; symbol : ident { DEBUG (10, "symbol -> ident\n", NULL); /* The identifier is entered into the relocation * table already. */ $$.in_tag = SYMTAG | RELOCATABLE; $$.in_stb = $1.pntr; } | NUMBER { DEBUG (10, "symbol -> NUMBER\n", NULL); /* An absolute address */ $$.in_tag |= SYMTAG & ~RELOCATABLE; $$.in_loc = $1; } ; ident : IDENT { /* This way so that we can enter it into the * relocation table here */ extern struct stab *insert(); DEBUG (10, "ident -> IDENT; name = %s\n", $1.pntr->st_symnm); if ($1.enterd != TRUE) { /* Mark it as entered */ $1.enterd = TRUE; /* And, enter it */ if (insert($1.pntr) == NULL) aabort ("Symbol table overflow\n"); } $$ = $1; } ; %% /* yyerror * The assemblers error reporting, flagging, clearing routine. * * Returns: * Nothing, though for consistency it must be declared int */ int yyerror (string) char *string; { char c; extern flag Ferror; extern int Lincnt; fprintf (stderr, "%d: %s\n", Lincnt, string); /* while ((c = input()) != '\n' && c != 0) ; unput(c); */ Ferror = TRUE; }