432 lines
8.2 KiB
Plaintext
432 lines
8.2 KiB
Plaintext
/* $Id$ */
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
/* @(#)comm2.y 1.7 */
|
|
|
|
/*
|
|
* delay inclusion of machine dependent stuff (see comm0.h)
|
|
*/
|
|
#define _include #include
|
|
|
|
%{
|
|
#include "comm0.h"
|
|
#include "comm1.h"
|
|
|
|
static item_t *last_it, *o_it;
|
|
%}
|
|
|
|
/* ========== Machine independent Yacc definitions ========== */
|
|
|
|
%union {
|
|
word_t y_word;
|
|
valu_t y_valu;
|
|
expr_t y_expr;
|
|
item_t *y_item;
|
|
#ifdef ASLD
|
|
char *y_strp;
|
|
#endif
|
|
};
|
|
|
|
#ifdef ASLD
|
|
%token <y_strp> MODULE
|
|
#endif
|
|
%token STRING
|
|
%token <y_item> IDENT
|
|
%token <y_item> FBSYM
|
|
%token <y_valu> CODE1
|
|
%token <y_valu> CODE2
|
|
%token <y_valu> CODE4
|
|
%token NUMBER0 /* keep NUMBER* in this order */
|
|
%token NUMBER1
|
|
%token NUMBER2
|
|
%token NUMBER3
|
|
%token <y_valu> NUMBER
|
|
%token DOT
|
|
%token EXTERN
|
|
%token <y_word> DATA
|
|
%token <y_word> ASCII
|
|
%token SECTION
|
|
%token COMMON
|
|
%token BASE
|
|
%token SYMB
|
|
%token SYMD
|
|
%token ALIGN
|
|
%token ASSERT
|
|
%token SPACE
|
|
%token <y_word> LINE
|
|
%token FILe
|
|
%token <y_word> LIST
|
|
%token OP_EQ
|
|
%token OP_NE
|
|
%token OP_LE
|
|
%token OP_GE
|
|
%token OP_LL
|
|
%token OP_RR
|
|
%token OP_OO
|
|
%token OP_AA
|
|
|
|
%left OP_OO
|
|
%left OP_AA
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left OP_EQ OP_NE
|
|
%left '<' '>' OP_LE OP_GE
|
|
%left OP_LL OP_RR
|
|
%left '+' '-'
|
|
%left '*' '/' '%'
|
|
%nonassoc '~'
|
|
|
|
%type <y_valu> absexp optabs1 optabs2
|
|
%type <y_expr> expr
|
|
%type <y_item> id_fb
|
|
|
|
/* ========== Machine dependent Yacc definitions ========== */
|
|
|
|
#include "mach2.c"
|
|
|
|
%%
|
|
|
|
/* ========== Machine independent rules ========== */
|
|
|
|
#ifdef LISTING
|
|
#define LISTLINE(n) if (listflag) listline(n); \
|
|
else if (listtemp) { listflag = listtemp; listeoln = 1; }
|
|
#else
|
|
#define LISTLINE(n) /* empty */
|
|
#endif /* LISTING */
|
|
|
|
#ifdef ASLD
|
|
#define RELODONE /* empty */
|
|
#else
|
|
#define RELODONE assert(relonami == 0)
|
|
#endif
|
|
|
|
program : /* empty */
|
|
#ifdef ASLD
|
|
| program MODULE /* not in PASS_1 */
|
|
{ newmodule($2);}
|
|
#endif
|
|
| program IDENT ':'
|
|
{ newident($2, DOTTYP); newlabel($2);}
|
|
| program NUMBER ':'
|
|
{ if ($2 < 0 || $2 > 9) {
|
|
serror("bad f/b label");
|
|
$2 = 0;
|
|
}
|
|
newlabel(fb_shift((int)$2));
|
|
}
|
|
| program CODE1
|
|
{ emit1((int)$2); LISTLINE(0);}
|
|
| program CODE2
|
|
{ emit2((int)$2); LISTLINE(0);}
|
|
| program CODE4
|
|
{ emit4((long)$2); LISTLINE(0);}
|
|
| program operation ';'
|
|
| program operation '\n'
|
|
{ lineno++; LISTLINE(1); RELODONE;}
|
|
| program '#' NUMBER STRING '\n'
|
|
{ lineno = $3;
|
|
if (modulename) strncpy(modulename, stringbuf, STRINGMAX-1);
|
|
LISTLINE(1); RELODONE;
|
|
}
|
|
| program error '\n'
|
|
{ serror("syntax error"); yyerrok;
|
|
lineno++; LISTLINE(1); RELODONE;
|
|
}
|
|
;
|
|
#undef LISTLINE
|
|
#undef RELODONE
|
|
operation
|
|
: /* empty */
|
|
| IDENT '=' expr
|
|
{
|
|
#ifdef LISTING
|
|
if (listflag & 1)
|
|
listcolm += printx(VALWIDTH, $3.val);
|
|
#endif
|
|
newequate($1, $3.typ);
|
|
store($1, $3.val);
|
|
}
|
|
#ifdef LISTING
|
|
| LIST
|
|
{ if ($1)
|
|
listtemp = listmode;
|
|
else if ((dflag & 01000) == 0)
|
|
listtemp = 0;
|
|
}
|
|
#endif
|
|
| SECTION IDENT
|
|
{ newsect($2);}
|
|
| COMMON IDENT ',' absexp
|
|
{ newcomm($2, $4);}
|
|
| BASE absexp
|
|
{ if (pass == PASS_1) newbase($2);}
|
|
| ASSERT expr
|
|
{ if ($2.val == 0 && pass == PASS_3)
|
|
warning("assertion failed");
|
|
}
|
|
| SYMB STRING ',' expr { o_it = last_it; }
|
|
optabs2 optabs2
|
|
{ if ((sflag & SYM_SMB) && PASS_SYMB) {
|
|
#ifndef ASLD
|
|
if (
|
|
pass == PASS_3
|
|
&&
|
|
($4.typ & S_TYP) == S_UND
|
|
) {
|
|
serror("expression undefined");
|
|
relonami = -1;
|
|
}
|
|
if (
|
|
PASS_SYMB
|
|
&&
|
|
($4.typ & S_COM)
|
|
) {
|
|
/* No value is known at
|
|
assembler time.
|
|
Generate reference to other
|
|
entry in name table
|
|
*/
|
|
$4.typ = S_CRS;
|
|
$4.val = new_string(o_it->i_name);
|
|
relonami = 0;
|
|
}
|
|
#endif
|
|
|
|
newsymb(
|
|
*stringbuf ? stringbuf : (char *) 0,
|
|
(short)(
|
|
($4.typ & (S_EXT|S_TYP))
|
|
|
|
|
((unsigned short)$6<<8)
|
|
),
|
|
(short)$7,
|
|
$4.val
|
|
);
|
|
}
|
|
}
|
|
| SYMD STRING ',' absexp ',' absexp
|
|
{ if ((sflag & SYM_SMB) && PASS_SYMB) {
|
|
newsymb(
|
|
*stringbuf ? stringbuf : (char *) 0,
|
|
(short)(
|
|
(DOTTYP & (S_EXT|S_TYP))
|
|
|
|
|
((unsigned short)$4<<8)
|
|
),
|
|
(short)$6,
|
|
(valu_t)DOTVAL
|
|
);
|
|
}
|
|
}
|
|
| LINE optabs1
|
|
{ if ((sflag & SYM_LIN) && PASS_SYMB) {
|
|
if ($2)
|
|
hllino = (short)$2;
|
|
else
|
|
hllino++;
|
|
newsymb(
|
|
(char *)0,
|
|
(DOTTYP | S_LIN),
|
|
hllino,
|
|
(valu_t)DOTVAL
|
|
);
|
|
}
|
|
}
|
|
| FILe STRING
|
|
{ if ((sflag & SYM_LIN) && PASS_SYMB) {
|
|
hllino = 0;
|
|
newsymb(
|
|
stringbuf,
|
|
(DOTTYP | S_FIL),
|
|
0,
|
|
(valu_t)DOTVAL
|
|
);
|
|
}
|
|
}
|
|
| EXTERN externlist
|
|
| ALIGN optabs1
|
|
{ align($2);}
|
|
| SPACE absexp
|
|
{ if (DOTSCT == NULL)
|
|
nosect();
|
|
DOTVAL += $2;
|
|
DOTSCT->s_zero += $2;
|
|
}
|
|
| DATA datalist
|
|
| ASCII STRING
|
|
{ emitstr($1);}
|
|
;
|
|
externlist
|
|
: IDENT
|
|
{ $1->i_type |= S_EXT;}
|
|
| externlist ',' IDENT
|
|
{ $3->i_type |= S_EXT;}
|
|
;
|
|
datalist
|
|
: expr
|
|
{
|
|
#ifdef RELOCATION
|
|
if (rflag != 0 && PASS_RELO)
|
|
newrelo($1.typ, (int)$<y_word>0|MACHREL_BWR);
|
|
#endif
|
|
emitx($1.val, (int)$<y_word>0);
|
|
}
|
|
| datalist ',' expr
|
|
{
|
|
#ifdef RELOCATION
|
|
if (rflag != 0 && PASS_RELO)
|
|
newrelo($3.typ, (int)$<y_word>0|MACHREL_BWR);
|
|
#endif
|
|
emitx($3.val, (int)$<y_word>0);
|
|
}
|
|
;
|
|
expr : error
|
|
{ serror("expr syntax err");
|
|
$$.val = 0; $$.typ = S_UND;
|
|
}
|
|
| NUMBER
|
|
{ $$.val = $1; $$.typ = S_ABS;}
|
|
| id_fb
|
|
{ $$.val = load($1);
|
|
last_it = $1;
|
|
$$.typ = $1->i_type & ~S_EXT;
|
|
}
|
|
| STRING
|
|
{ if (stringlen != 1)
|
|
serror("too many chars");
|
|
$$.val = stringbuf[0];
|
|
$$.typ = S_ABS;
|
|
}
|
|
| ASC_LPAR expr ASC_RPAR
|
|
{ $$ = $2;}
|
|
| expr OP_OO expr
|
|
{ $$.val = ($1.val || $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr OP_AA expr
|
|
{ $$.val = ($1.val && $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '|' expr
|
|
{ $$.val = ($1.val | $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '^' expr
|
|
{ $$.val = ($1.val ^ $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '&' expr
|
|
{ $$.val = ($1.val & $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr OP_EQ expr
|
|
{ $$.val = ($1.val == $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr OP_NE expr
|
|
{ $$.val = ($1.val != $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr '<' expr
|
|
{ $$.val = ($1.val < $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr '>' expr
|
|
{ $$.val = ($1.val > $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr OP_LE expr
|
|
{ $$.val = ($1.val <= $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr OP_GE expr
|
|
{ $$.val = ($1.val >= $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '>');
|
|
}
|
|
| expr OP_RR expr
|
|
{ $$.val = ($1.val >> $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr OP_LL expr
|
|
{ $$.val = ($1.val << $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '+' expr
|
|
{ $$.val = ($1.val + $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '+');
|
|
}
|
|
| expr '-' expr
|
|
{ $$.val = ($1.val - $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, '-');
|
|
}
|
|
| expr '*' expr
|
|
{ $$.val = ($1.val * $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '/' expr
|
|
{ if ($3.val == 0) {
|
|
if (pass == PASS_3)
|
|
serror("divide by zero");
|
|
$$.val = 0;
|
|
} else
|
|
$$.val = ($1.val / $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| expr '%' expr
|
|
{ if ($3.val == 0) {
|
|
if (pass == PASS_3)
|
|
serror("divide by zero");
|
|
$$.val = 0;
|
|
} else
|
|
$$.val = ($1.val % $3.val);
|
|
$$.typ = combine($1.typ, $3.typ, 0);
|
|
}
|
|
| '+' expr %prec '*'
|
|
{ $$.val = $2.val;
|
|
$$.typ = combine(S_ABS, $2.typ, 0);
|
|
}
|
|
| '-' expr %prec '*'
|
|
{ $$.val = -$2.val;
|
|
$$.typ = combine(S_ABS, $2.typ, 0);
|
|
}
|
|
| '~' expr
|
|
{ $$.val = ~$2.val;
|
|
$$.typ = combine(S_ABS, $2.typ, 0);
|
|
}
|
|
| DOT
|
|
{ $$.val = DOTVAL;
|
|
$$.typ = DOTTYP|S_DOT;
|
|
}
|
|
;
|
|
id_fb : IDENT
|
|
| FBSYM
|
|
;
|
|
absexp : expr
|
|
{ if (($1.typ & ~S_EXT) != S_ABS)
|
|
serror("must be absolute");
|
|
$$ = $1.val;
|
|
}
|
|
;
|
|
optabs1
|
|
: /* empty */
|
|
{ $$ = 0;}
|
|
| absexp
|
|
{ $$ = $1;}
|
|
;
|
|
optabs2
|
|
: /* empty */
|
|
{ $$ = 0;}
|
|
| ',' absexp
|
|
{ $$ = $2;}
|
|
;
|
|
|
|
/* ========== Machine dependent rules ========== */
|
|
|
|
#include "mach4.c"
|
|
|
|
%%
|