329 lines
6.5 KiB
C
329 lines
6.5 KiB
C
#define RCSID4 "$Id$"
|
|
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Zilog Z80 parsing rules
|
|
*/
|
|
operation
|
|
: NOOPOP
|
|
{ emit1($1);}
|
|
| LDOP ldargs
|
|
| PSHPOP R16
|
|
{ switch ($2) {
|
|
case BC: emit1($1); break;
|
|
case DE: emit1($1 | 020); break;
|
|
case AF: emit1($1 | 060); break;
|
|
case HL:
|
|
case IX:
|
|
case IY: xyreg($2,$1 | 040); break;
|
|
default: serror("register error");
|
|
}
|
|
}
|
|
| EXOP R16 ',' R16
|
|
{ if ($2==DE && $4==HL)
|
|
emit1(0353);
|
|
else if ($2==AF && $4==AF2)
|
|
emit1(010);
|
|
else serror("register error");
|
|
}
|
|
| EXOP '(' R16 ')' ',' R16
|
|
{ if ($3!=SP) serror("register error");
|
|
xyreg($6,$1);
|
|
}
|
|
| E_ED
|
|
{ emit1(0355); emit1($1);}
|
|
| ADDOP R16 ',' R16
|
|
{ if ($4 == $2)
|
|
xyreg($2,051);
|
|
else {
|
|
if ($4==HL || $4>SP)
|
|
serror("register error");
|
|
xyreg($2,011 | $4<<4);
|
|
}
|
|
}
|
|
| ADCSBC R16 ',' R16
|
|
{ if ($2!=HL || $4>SP) serror("register error");
|
|
emit1(0355);
|
|
emit1(($1==0210 ? 0112 : 0102) | ($4<<4));
|
|
}
|
|
| INCDEC R16
|
|
{ switch ($2) {
|
|
case BC: case DE: case SP:
|
|
emit1(($1==04 ? 03 : 013) | $2<<4);
|
|
break;
|
|
case HL: case IX: case IY:
|
|
xyreg($2,$1==04 ? 043 : 053);
|
|
break;
|
|
default: serror("register error");
|
|
}
|
|
}
|
|
| INCDEC r8
|
|
{ emit1($1 | $2<<3);}
|
|
| INCDEC ind
|
|
{ xymem($2,$1 | 060);}
|
|
| ari8 r8
|
|
{ emit1($1 | $2);}
|
|
| ari8 expr
|
|
{ emit1($1 | 0106); emit1($2.val);}
|
|
| ari8 ind
|
|
{ xymem($2,$1 | 06);}
|
|
| IMOP absexp
|
|
{ emit1(0355);
|
|
switch ($2) {
|
|
case 0: emit1(0106); break;
|
|
case 1: emit1(0126); break;
|
|
case 2: emit1(0136); break;
|
|
default: serror("range 0..2");
|
|
}
|
|
}
|
|
| ROTATE r8
|
|
{ emit1(0313); emit1($1 | $2);}
|
|
| ROTATE ind
|
|
{ xymem($2,0313); emit1($1 | 06);}
|
|
| BITS absexp ',' r8
|
|
{ fit(fit3($2));
|
|
emit1(0313); emit1($1 | low3($2)<<3 | $4);
|
|
}
|
|
| BITS absexp ',' ind
|
|
{ fit(fit3($2));
|
|
xymem($4,0313);
|
|
emit1($1 | low3($2)<<3 | 06);
|
|
}
|
|
| JP expr
|
|
{ emit1($1);
|
|
#ifdef RELOCATION
|
|
newrelo($2.typ, RELO2);
|
|
#endif
|
|
emit2($2.val);
|
|
}
|
|
| JP coco ',' expr
|
|
{ emit1(0302 | $2<<3);
|
|
#ifdef RELOCATION
|
|
newrelo($4.typ, RELO2);
|
|
#endif
|
|
emit2($4.val);
|
|
}
|
|
| JP indir
|
|
{ xyreg($2,0351);}
|
|
| JR expr
|
|
{ branch($1,$2);}
|
|
| JR coco ',' expr
|
|
{ if ($2 > 3) serror("bad condition code");
|
|
branch(040 | ($2<<3), $4);
|
|
}
|
|
| DJNZ expr
|
|
{ branch($1,$2);}
|
|
| CALL expr
|
|
{ emit1($1);
|
|
#ifdef RELOCATION
|
|
newrelo($2.typ, RELO2);
|
|
#endif
|
|
emit2($2.val);
|
|
}
|
|
| CALL coco ',' expr
|
|
{ emit1(0304 | $2<<3);
|
|
#ifdef RELOCATION
|
|
newrelo($4.typ, RELO2);
|
|
#endif
|
|
emit2($4.val);
|
|
}
|
|
| RET
|
|
{ emit1($1);}
|
|
| RET coco
|
|
{ emit1(0300 | $2<<3);}
|
|
| RST absexp
|
|
{ if (($2&070)!=$2)
|
|
serror("rst expression out of range");
|
|
emit1($1 | $2);
|
|
}
|
|
| IN R8 ',' expr
|
|
{ if ($2 != A) serror("register error");
|
|
emit1($1);
|
|
#ifdef RELOCATION
|
|
newrelo($4.typ, RELO1);
|
|
#endif
|
|
emit1($4.val);
|
|
}
|
|
| IN R8 ',' R8
|
|
{ if ($4 != C) serror("register error");
|
|
emit1(0355); emit1(0100 | $2<<3);
|
|
}
|
|
| OUT expr ',' R8
|
|
{ if ($4 != A) serror("register error");
|
|
emit1($1);
|
|
#ifdef RELOCATION
|
|
newrelo($2.typ, RELO1);
|
|
#endif
|
|
emit1($2.val);
|
|
}
|
|
| OUT R8 ',' R8
|
|
{ if ($2 != C) serror("register error");
|
|
emit1(0355); emit1(0101 | $4<<3);
|
|
}
|
|
;
|
|
ari8 : ARI8
|
|
| ADDOP R8 ','
|
|
{ if ($2 != A) serror("register error");}
|
|
| ADCSBC R8 ','
|
|
{ if ($2 != A) serror("register error");}
|
|
;
|
|
ldargs : R8 ',' R8
|
|
{ if ($1==F || $3==F) serror("register error");
|
|
if ($1<=A && $3<=A)
|
|
emit1(0100 | $1<<3 | $3);
|
|
else {
|
|
emit1(0355);
|
|
if ((($1==A) ^ ($3==A)) == 0)
|
|
serror("register error");
|
|
emit1( 0107 |
|
|
($1==R||$3==R)<<3 |
|
|
($1==A)<<4
|
|
);
|
|
}
|
|
}
|
|
| R8 ',' expr
|
|
{ if ($1==F || $1==I || $1==R)
|
|
serror("register error");
|
|
emit1(06 | $1<<3);
|
|
#ifdef RELOCATION
|
|
newrelo($3.typ, RELO1);
|
|
#endif
|
|
emit1($3.val);
|
|
}
|
|
| R8 ',' indir
|
|
{ if ($1==F || $1==I || $1==R)
|
|
serror("register error");
|
|
if ($1==A && ($3==BC || $3==DE))
|
|
emit1($3==BC ? 012 : 032);
|
|
else
|
|
xymem($3,0106 | $1<<3);
|
|
}
|
|
| R8 ',' index
|
|
{ if ($1==F || $1==I || $1==R)
|
|
serror("register error");
|
|
xymem($3,0106 | $1<<3);
|
|
}
|
|
| R8 ',' '(' expr ')'
|
|
{ if ($1!=A) serror("register error");
|
|
emit1(072);
|
|
#ifdef RELOCATION
|
|
newrelo($4.typ, RELO2);
|
|
#endif
|
|
emit2($4.val);
|
|
}
|
|
| indir ',' r8
|
|
{ if ($3==A && ($1==BC || $1==DE))
|
|
emit1($1==BC ? 02 : 022);
|
|
else
|
|
xymem($1,0160 | $3);
|
|
}
|
|
| index ',' r8
|
|
{ xymem($1,0160 | $3);}
|
|
| indir ',' expr
|
|
{ xymem($1,066);
|
|
#ifdef RELOCATION
|
|
newrelo($3.typ, RELO1);
|
|
#endif
|
|
emit1($3.val);
|
|
}
|
|
| index ',' expr
|
|
{ xymem($1,066);
|
|
#ifdef RELOCATION
|
|
newrelo($3.typ, RELO1);
|
|
#endif
|
|
emit1($3.val);
|
|
}
|
|
| R16 ',' expr
|
|
{ switch ($1) {
|
|
case BC: case DE: case HL: case SP:
|
|
emit1(01 | $1<<4); break;
|
|
case IX: case IY:
|
|
xyreg($1,041); break;
|
|
default: serror("register error");
|
|
}
|
|
#ifdef RELOCATION
|
|
newrelo($3.typ, RELO2);
|
|
#endif
|
|
emit2($3.val);
|
|
}
|
|
| R16 ',' R16
|
|
{ if ($1!=SP) serror("register error");
|
|
xyreg($3,0371);
|
|
}
|
|
| R16 ',' '(' expr ')'
|
|
{ switch ($1) {
|
|
case BC: case DE: case SP:
|
|
emit1(0355); emit1(0113 | $1<<4); break;
|
|
case HL: case IX: case IY:
|
|
xyreg($1,052); break;
|
|
default: serror("register error");
|
|
}
|
|
#ifdef RELOCATION
|
|
newrelo($4.typ, RELO2);
|
|
#endif
|
|
emit2($4.val);
|
|
}
|
|
| '(' expr ')' ',' R8
|
|
{ if ($5!=A) serror("register error");
|
|
emit1(062);
|
|
#ifdef RELOCATION
|
|
newrelo($2.typ, RELO2);
|
|
#endif
|
|
emit2($2.val);
|
|
}
|
|
| '(' expr ')' ',' R16
|
|
{ switch ($5) {
|
|
case BC: case DE: case SP:
|
|
emit1(0355); emit1(0103 | $5<<4); break;
|
|
case HL: case IX: case IY:
|
|
xyreg($5,042); break;
|
|
default: serror("register error");
|
|
}
|
|
#ifdef RELOCATION
|
|
newrelo($2.typ, RELO2);
|
|
#endif
|
|
emit2($2.val);
|
|
}
|
|
;
|
|
r8 : R8
|
|
{ if ($1==F || $1==I || $1==R)
|
|
serror("register error");
|
|
}
|
|
;
|
|
indir : '(' R16 ')'
|
|
{ if ($2>=SP && $2!=IX && $2!=IY)
|
|
serror("register error");
|
|
exp_ind.typ = S_ABS; exp_ind.val = 0;
|
|
$$ = $2;
|
|
}
|
|
;
|
|
index : '(' R16 '+' expr ')'
|
|
{ if ($2!=IX && $2!=IY) serror("register error");
|
|
exp_ind = $4;
|
|
RELOMOVE(rel_ind, relonami);
|
|
$$ = $2;
|
|
}
|
|
| '(' R16 '-' expr ')'
|
|
{
|
|
if ($2!=IX && $2!=IY) serror("register error");
|
|
fit(fitb($4.val));
|
|
exp_ind = $4;
|
|
RELOMOVE(rel_ind, relonami);
|
|
$$ = $2;
|
|
}
|
|
;
|
|
ind : indir
|
|
| index
|
|
;
|
|
coco : CC
|
|
| R8
|
|
{ if ($1 != C) serror("bad condition code");
|
|
$$ = 3;
|
|
}
|
|
;
|